diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..cbe62527
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,305 @@
+# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
+###############################
+# Core EditorConfig Options #
+###############################
+root = true
+# All files
+[*]
+indent_style = space
+end_of_line = lf
+
+# XML project files
+[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
+indent_size = 2
+
+# XML config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
+indent_size = 2
+
+# YAML config files
+[*.{yml,yaml}]
+tab_width = 2
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+# JSON config files
+[*.json]
+tab_width = 2
+indent_size = 2
+insert_final_newline = false
+trim_trailing_whitespace = true
+
+# Stylesheet files
+[*.{css,scss,sass,less}]
+insert_final_newline = true
+trim_trailing_whitespace = true
+tab_width = 4
+indent_size = 4
+
+# Code files
+[*.{cs,csx,vb,vbx}]
+tab_width = 4
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8-bom
+file_header_template = Copyright (c) Microsoft. All rights reserved.
+
+###############################
+# Java Coding Conventions #
+###############################
+[*.java]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = false
+tab_width = 4
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_smart_tabs = false
+ij_visual_guides = none
+
+max_line_length = 100
+ij_continuation_indent_size = 4
+ij_formatter_tags_enabled = false
+ij_wrap_on_typing = false
+
+ij_java_align_consecutive_assignments = false
+ij_java_align_consecutive_variable_declarations = false
+ij_java_align_group_field_declarations = false
+ij_java_align_multiline_annotation_parameters = false
+ij_java_align_multiline_array_initializer_expression = false
+ij_java_align_multiline_assignment = false
+ij_java_align_multiline_binary_operation = false
+ij_java_align_multiline_chained_methods = false
+ij_java_align_multiline_extends_list = false
+ij_java_align_multiline_for = false
+ij_java_align_multiline_method_parentheses = false
+ij_java_align_multiline_parameters = false
+ij_java_align_multiline_parameters_in_calls = false
+ij_java_align_multiline_parenthesized_expression = false
+ij_java_align_multiline_resources = false
+ij_java_align_multiline_ternary_operation = false
+ij_java_align_multiline_throws_list = false
+ij_java_align_subsequent_simple_methods = false
+ij_java_align_throws_keyword = false
+ij_java_annotation_parameter_wrap = off
+ij_java_array_initializer_new_line_after_left_brace = false
+ij_java_array_initializer_right_brace_on_new_line = false
+ij_java_array_initializer_wrap = normal
+ij_java_assert_statement_colon_on_next_line = false
+ij_java_assert_statement_wrap = off
+ij_java_assignment_wrap = off
+ij_java_binary_operation_sign_on_next_line = true
+ij_java_binary_operation_wrap = normal
+ij_java_blank_lines_after_anonymous_class_header = 0
+ij_java_blank_lines_after_class_header = 1
+ij_java_blank_lines_after_imports = 1
+ij_java_blank_lines_after_package = 1
+ij_java_blank_lines_around_class = 1
+ij_java_blank_lines_around_field = 0
+ij_java_blank_lines_around_field_in_interface = 0
+ij_java_blank_lines_around_initializer = 1
+ij_java_blank_lines_around_method = 1
+ij_java_blank_lines_around_method_in_interface = 1
+ij_java_blank_lines_before_class_end = 0
+ij_java_blank_lines_before_imports = 1
+ij_java_blank_lines_before_method_body = 0
+ij_java_blank_lines_before_package = 0
+ij_java_block_brace_style = end_of_line
+ij_java_block_comment_at_first_column = true
+ij_java_call_parameters_new_line_after_left_paren = false
+ij_java_call_parameters_right_paren_on_new_line = false
+ij_java_call_parameters_wrap = normal
+ij_java_case_statement_on_separate_line = true
+ij_java_catch_on_new_line = false
+ij_java_class_annotation_wrap = split_into_lines
+ij_java_class_brace_style = end_of_line
+ij_java_class_count_to_use_import_on_demand = 999
+ij_java_class_names_in_javadoc = 1
+ij_java_do_not_indent_top_level_class_members = false
+ij_java_do_not_wrap_after_single_annotation = false
+ij_java_do_while_brace_force = always
+ij_java_doc_add_blank_line_after_description = true
+ij_java_doc_add_blank_line_after_param_comments = false
+ij_java_doc_add_blank_line_after_return = false
+ij_java_doc_add_p_tag_on_empty_lines = true
+ij_java_doc_align_exception_comments = true
+ij_java_doc_align_param_comments = true
+ij_java_doc_do_not_wrap_if_one_line = false
+ij_java_doc_enable_formatting = true
+ij_java_doc_enable_leading_asterisks = true
+ij_java_doc_indent_on_continuation = false
+ij_java_doc_keep_empty_lines = true
+ij_java_doc_keep_empty_parameter_tag = true
+ij_java_doc_keep_empty_return_tag = true
+ij_java_doc_keep_empty_throws_tag = true
+ij_java_doc_keep_invalid_tags = true
+ij_java_doc_param_description_on_new_line = false
+ij_java_doc_preserve_line_breaks = false
+ij_java_doc_use_throws_not_exception_tag = true
+ij_java_else_on_new_line = false
+ij_java_entity_dd_suffix = EJB
+ij_java_entity_eb_suffix = Bean
+ij_java_entity_hi_suffix = Home
+ij_java_entity_lhi_prefix = Local
+ij_java_entity_lhi_suffix = Home
+ij_java_entity_li_prefix = Local
+ij_java_entity_pk_class = java.lang.String
+ij_java_entity_vo_suffix = VO
+ij_java_enum_constants_wrap = off
+ij_java_extends_keyword_wrap = off
+ij_java_extends_list_wrap = normal
+ij_java_field_annotation_wrap = split_into_lines
+ij_java_finally_on_new_line = false
+ij_java_for_brace_force = always
+ij_java_for_statement_new_line_after_left_paren = false
+ij_java_for_statement_right_paren_on_new_line = false
+ij_java_for_statement_wrap = normal
+ij_java_generate_final_locals = false
+ij_java_generate_final_parameters = false
+ij_java_if_brace_force = always
+ij_java_imports_layout = $*, |, *
+ij_java_indent_case_from_switch = true
+ij_java_insert_inner_class_imports = true
+ij_java_insert_override_annotation = true
+ij_java_keep_blank_lines_before_right_brace = 2
+ij_java_keep_blank_lines_between_package_declaration_and_header = 2
+ij_java_keep_blank_lines_in_code = 1
+ij_java_keep_blank_lines_in_declarations = 2
+ij_java_keep_control_statement_in_one_line = false
+ij_java_keep_first_column_comment = true
+ij_java_keep_indents_on_empty_lines = false
+ij_java_keep_line_breaks = true
+ij_java_keep_multiple_expressions_in_one_line = false
+ij_java_keep_simple_blocks_in_one_line = false
+ij_java_keep_simple_classes_in_one_line = false
+ij_java_keep_simple_lambdas_in_one_line = false
+ij_java_keep_simple_methods_in_one_line = false
+ij_java_lambda_brace_style = end_of_line
+ij_java_layout_static_imports_separately = true
+ij_java_line_comment_add_space = false
+ij_java_line_comment_at_first_column = true
+ij_java_message_dd_suffix = EJB
+ij_java_message_eb_suffix = Bean
+ij_java_method_annotation_wrap = split_into_lines
+ij_java_method_brace_style = end_of_line
+ij_java_method_call_chain_wrap = normal
+ij_java_method_parameters_new_line_after_left_paren = false
+ij_java_method_parameters_right_paren_on_new_line = false
+ij_java_method_parameters_wrap = normal
+ij_java_modifier_list_wrap = false
+ij_java_names_count_to_use_import_on_demand = 999
+ij_java_parameter_annotation_wrap = off
+ij_java_parentheses_expression_new_line_after_left_paren = false
+ij_java_parentheses_expression_right_paren_on_new_line = false
+ij_java_place_assignment_sign_on_next_line = false
+ij_java_prefer_longer_names = true
+ij_java_prefer_parameters_wrap = false
+ij_java_repeat_synchronized = true
+ij_java_replace_instanceof_and_cast = false
+ij_java_replace_null_check = true
+ij_java_replace_sum_lambda_with_method_ref = true
+ij_java_resource_list_new_line_after_left_paren = false
+ij_java_resource_list_right_paren_on_new_line = false
+ij_java_resource_list_wrap = off
+ij_java_session_dd_suffix = EJB
+ij_java_session_eb_suffix = Bean
+ij_java_session_hi_suffix = Home
+ij_java_session_lhi_prefix = Local
+ij_java_session_lhi_suffix = Home
+ij_java_session_li_prefix = Local
+ij_java_session_si_suffix = Service
+ij_java_space_after_closing_angle_bracket_in_type_argument = false
+ij_java_space_after_colon = true
+ij_java_space_after_comma = true
+ij_java_space_after_comma_in_type_arguments = true
+ij_java_space_after_for_semicolon = true
+ij_java_space_after_quest = true
+ij_java_space_after_type_cast = true
+ij_java_space_before_annotation_array_initializer_left_brace = false
+ij_java_space_before_annotation_parameter_list = false
+ij_java_space_before_array_initializer_left_brace = false
+ij_java_space_before_catch_keyword = true
+ij_java_space_before_catch_left_brace = true
+ij_java_space_before_catch_parentheses = true
+ij_java_space_before_class_left_brace = true
+ij_java_space_before_colon = true
+ij_java_space_before_colon_in_foreach = true
+ij_java_space_before_comma = false
+ij_java_space_before_do_left_brace = true
+ij_java_space_before_else_keyword = true
+ij_java_space_before_else_left_brace = true
+ij_java_space_before_finally_keyword = true
+ij_java_space_before_finally_left_brace = true
+ij_java_space_before_for_left_brace = true
+ij_java_space_before_for_parentheses = true
+ij_java_space_before_for_semicolon = false
+ij_java_space_before_if_left_brace = true
+ij_java_space_before_if_parentheses = true
+ij_java_space_before_method_call_parentheses = false
+ij_java_space_before_method_left_brace = true
+ij_java_space_before_method_parentheses = false
+ij_java_space_before_opening_angle_bracket_in_type_parameter = false
+ij_java_space_before_quest = true
+ij_java_space_before_switch_left_brace = true
+ij_java_space_before_switch_parentheses = true
+ij_java_space_before_synchronized_left_brace = true
+ij_java_space_before_synchronized_parentheses = true
+ij_java_space_before_try_left_brace = true
+ij_java_space_before_try_parentheses = true
+ij_java_space_before_type_parameter_list = false
+ij_java_space_before_while_keyword = true
+ij_java_space_before_while_left_brace = true
+ij_java_space_before_while_parentheses = true
+ij_java_space_inside_one_line_enum_braces = false
+ij_java_space_within_empty_array_initializer_braces = false
+ij_java_space_within_empty_method_call_parentheses = false
+ij_java_space_within_empty_method_parentheses = false
+ij_java_spaces_around_additive_operators = true
+ij_java_spaces_around_assignment_operators = true
+ij_java_spaces_around_bitwise_operators = true
+ij_java_spaces_around_equality_operators = true
+ij_java_spaces_around_lambda_arrow = true
+ij_java_spaces_around_logical_operators = true
+ij_java_spaces_around_method_ref_dbl_colon = false
+ij_java_spaces_around_multiplicative_operators = true
+ij_java_spaces_around_relational_operators = true
+ij_java_spaces_around_shift_operators = true
+ij_java_spaces_around_type_bounds_in_type_parameters = true
+ij_java_spaces_around_unary_operator = false
+ij_java_spaces_within_angle_brackets = false
+ij_java_spaces_within_annotation_parentheses = false
+ij_java_spaces_within_array_initializer_braces = false
+ij_java_spaces_within_braces = false
+ij_java_spaces_within_brackets = false
+ij_java_spaces_within_cast_parentheses = false
+ij_java_spaces_within_catch_parentheses = false
+ij_java_spaces_within_for_parentheses = false
+ij_java_spaces_within_if_parentheses = false
+ij_java_spaces_within_method_call_parentheses = false
+ij_java_spaces_within_method_parentheses = false
+ij_java_spaces_within_parentheses = false
+ij_java_spaces_within_switch_parentheses = false
+ij_java_spaces_within_synchronized_parentheses = false
+ij_java_spaces_within_try_parentheses = false
+ij_java_spaces_within_while_parentheses = false
+ij_java_special_else_if_treatment = true
+ij_java_subclass_name_suffix = Impl
+ij_java_ternary_operation_signs_on_next_line = true
+ij_java_ternary_operation_wrap = normal
+ij_java_test_name_suffix = Test
+ij_java_throws_keyword_wrap = normal
+ij_java_throws_list_wrap = off
+ij_java_use_external_annotations = false
+ij_java_use_fq_class_names = false
+ij_java_use_single_class_imports = true
+ij_java_variable_annotation_wrap = off
+ij_java_visibility = public
+ij_java_while_brace_force = always
+ij_java_while_on_new_line = false
+ij_java_wrap_comments = true
+ij_java_wrap_first_method_in_call_chain = false
+ij_java_wrap_long_lines = false
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..b5845d14
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,6 @@
+# Auto-detect text files, ensure they use LF.
+* text=auto eol=lf working-tree-encoding=UTF-8
+
+# Bash scripts
+*.sh text eol=lf
+*.cmd text eol=crlf
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 00000000..d6e7dac3
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,4 @@
+# @microsoft/octo-semantickernel-pr-java owns any files in the java
+# directory at the root of the repository and any of its
+# subdirectories.
+/ @microsoft/octo-semantickernel-pr-java
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..6f781500
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,36 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: 'Bug: '
+labels: ["bug", "triage"]
+projects: ["semantic-kernel"]
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Maven**
+ - Version: [e.g. 1.1.5]
+ - Dependencies: list of semantic-kernel related dependencies in your `pom.xml`
+
+**Platform**
+ - IDE: [e.g. IntelliJ, Eclipse, VS Code]
+ - JDK version: [e.g. JDK 11.0.17]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_graduation.md b/.github/ISSUE_TEMPLATE/feature_graduation.md
new file mode 100644
index 00000000..37d207ea
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_graduation.md
@@ -0,0 +1,29 @@
+---
+name: Feature graduation
+about: Plan the graduation of an experimental feature
+title: 'Graduate XXX feature'
+labels: ["feature_graduation"]
+projects: ["semantic-kernel"]
+assignees: ''
+
+---
+
+---
+name: Feature graduation
+about: Plan the graduation of an experimental feature
+
+---
+
+Checklist to be completed when graduating an experimental feature
+
+- [ ] Notify PM's and EM's that feature is read for graduation
+- [ ] Contact PM for list of sample use cases
+- [ ] Verify there are sample implementations for each of the use cases
+- [ ] Verify telemetry and logging are complete
+- [ ] Verify API docs are complete and arrange to have them published
+- [ ] Make appropriate updates to Learn docs
+- [ ] Make appropriate updates to Concept samples
+- [ ] Male appropriate updates to Blog posts
+- [ ] Verify there are no serious open Issues
+- [ ] Update table in EXPERIMENTS.md
+- [ ] Remove SKEXP flag from the experimental code
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..ca7db808
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,21 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: 'New Feature: '
+labels: '["triage", "enhancement"]'
+projects: ["semantic-kernel"]
+assignees: ''
+
+---
+
+---
+name: Feature request
+about: Suggest an idea for this project
+
+---
+
+
+
+
+
+
diff --git a/.github/_typos.toml b/.github/_typos.toml
new file mode 100644
index 00000000..a92576ba
--- /dev/null
+++ b/.github/_typos.toml
@@ -0,0 +1,44 @@
+# Typos configuration file
+#
+# Info: https://github.com/marketplace/actions/typos-action
+# Install: brew install typos-cli
+# Install: conda install typos
+# Run: typos -c .github/_typos.toml
+
+[files]
+extend-exclude = [
+ "_typos.toml",
+ "package-lock.json",
+ "*.bicep",
+ "encoder.json",
+ "vocab.bpe",
+ "CodeTokenizerTests.cs",
+ "test_code_tokenizer.py",
+ "*response.json",
+ "samples/semantickernel-demos/sk-presidio-sample/README.md"
+]
+
+[default.extend-words]
+ACI = "ACI" # Azure Container Instance
+exercize = "exercize" # test typos
+gramatical = "gramatical" # test typos
+Guid = "Guid" # Globally Unique Identifier
+HD = "HD" # Test header value
+EOF = "EOF" # End of File
+ans = "ans" # Short for answers
+arange = "arange" # Method in Python numpy package
+prompty = "prompty" # prompty is a format name.
+ist = "ist" # German language
+
+[default.extend-identifiers]
+ags = "ags" # Azure Graph Service
+
+[type.jupyter]
+extend-ignore-re = [
+ '"[A-Fa-f0-9]{8}"', # cell id strings
+]
+
+[type.msbuild]
+extend-ignore-re = [
+ 'Version=".*"', # ignore package version numbers
+]
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..97b4f664
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,58 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ # Maintain dependencies for nuget
+ - package-ecosystem: "nuget"
+ directory: "dotnet/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ ignore:
+ # For all System.* and Microsoft.Extensions/Bcl.* packages, ignore all major version updates
+ - dependency-name: "System.*"
+ update-types: ["version-update:semver-major"]
+ - dependency-name: "Microsoft.Extensions.*"
+ update-types: ["version-update:semver-major"]
+ - dependency-name: "Microsoft.Bcl.*"
+ update-types: ["version-update:semver-major"]
+ - dependency-name: "Moq"
+ labels:
+ - ".NET"
+ - "dependencies"
+
+ # Maintain dependencies for nuget
+ - package-ecosystem: "nuget"
+ directory: "samples/dotnet"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+
+ # Maintain dependencies for npm
+ - package-ecosystem: "npm"
+ directory: "samples/apps"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+
+ # Maintain dependencies for pip
+ - package-ecosystem: "pip"
+ directory: "python/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ labels:
+ - "python"
+ - "dependencies"
+
+ # Maintain dependencies for github-actions
+ - package-ecosystem: "github-actions"
+ # Workflow files stored in the
+ # default location of `.github/workflows`
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..38e62262
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,23 @@
+### 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:
diff --git a/.github/workflows/close-inactive-issues.yml b/.github/workflows/close-inactive-issues.yml
new file mode 100644
index 00000000..10244c76
--- /dev/null
+++ b/.github/workflows/close-inactive-issues.yml
@@ -0,0 +1,22 @@
+name: Close inactive issues
+on:
+ schedule:
+ - cron: "30 1 * * *"
+
+jobs:
+ close-issues:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - uses: actions/stale@v5
+ with:
+ days-before-issue-stale: 90
+ days-before-issue-close: 14
+ stale-issue-label: "stale"
+ stale-issue-message: "This issue is stale because it has been open for 90 days with no activity."
+ close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
+ days-before-pr-stale: -1
+ days-before-pr-close: -1
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 00000000..caf56980
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,78 @@
+# CodeQL is the code analysis engine developed by GitHub to automate security checks.
+# The results are shown as code scanning alerts in GitHub. For more details, visit:
+# https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning-with-codeql
+
+name: "CodeQL"
+
+on:
+ push:
+ branches: ["main"]
+ schedule:
+ - cron: "17 11 * * 2"
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: ["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
+
+ # 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
+
+ # 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
+
+ - name: Setup JDK
+ uses: actions/setup-java@v4
+ if: ${{ matrix.language == 'java' }}
+ with:
+ java-version: 17
+ distribution: microsoft
+ cache: maven
+
+ - name: Build Java
+ if: ${{ matrix.language == 'java' }}
+ run: ./mvnw -B -DskipTests -Pcompile-jdk17 clean install --file pom.xml
+
+ # ℹ️ 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
+
+ # 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.
+
+ # - 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 00000000..d4b487cf
--- /dev/null
+++ b/.github/workflows/java-build.yml
@@ -0,0 +1,63 @@
+name: Build Java Semantic Kernel
+
+# Triggers the workflow on manual dispatch, push, and pull request events
+# for the specified branches and paths
+on:
+ workflow_dispatch:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+permissions:
+ contents: read
+
+jobs:
+ # Builds and tests the Java project
+ java-build:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ # Defines a matrix strategy for JDK versions 8 and 17
+ java-versions: [8, 17]
+
+ name: Java CI on JDK${{ matrix.java-versions }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ # 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
+
+ # Sets up the specified JDK version from the matrix
+ - uses: actions/setup-java@v4
+ with:
+ java-version: ${{ steps.set-jdk.outputs.JDK_VERSION }}
+ distribution: microsoft
+ cache: maven
+
+ # Builds the project with Maven using the matrix JDK version
+ - name: Build with Maven
+ run: ./mvnw -B -Pbug-check -DskipTests -Pcompile-jdk${{ matrix.java-versions }} clean install --file pom.xml
+
+ # Runs tests with Maven using the matrix JDK version
+ - name: Run tests
+ run: ./mvnw -B -Pbug-check -Pcompile-jdk${{ matrix.java-versions }} test --file pom.xml
+
+ # Uploads test artifacts for each JDK version
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: test_output_sk_jdk${{ matrix.java-versions }}u
+ path: ./**/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 00000000..a65ee5cc
--- /dev/null
+++ b/.github/workflows/java-integration-tests.yml
@@ -0,0 +1,64 @@
+name: Run Java Integration Tests and Samples
+
+on:
+ workflow_dispatch:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+permissions:
+ contents: read
+
+jobs:
+ java-integration-tests:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ java-versions: [8, 17]
+
+ name: Java Tests on JDK${{ matrix.java-versions }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ # 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@v4
+ with:
+ java-version: ${{ steps.set-jdk.outputs.JDK_VERSION }}
+ distribution: microsoft
+ cache: maven
+
+ - name: Build with Maven
+ run: ./mvnw -B -Pwith-samples -Pbug-check -DskipTests -Pcompile-jdk${{ matrix.java-versions }} clean install --file pom.xml
+ if: ${{ matrix.java-versions >= 17 }}
+
+ # API tests run on JDK 17+
+ - name: Run integration tests
+ run: ../mvnw -B -Pbug-check clean install --file pom.xml
+ working-directory: 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: samples
+ if: ${{ matrix.java-versions >= 17 }}
diff --git a/.github/workflows/java-publish-package.yml b/.github/workflows/java-publish-package.yml
new file mode 100644
index 00000000..25afec46
--- /dev/null
+++ b/.github/workflows/java-publish-package.yml
@@ -0,0 +1,41 @@
+name: Deploy Java Semantic Kernel Package
+
+# Triggers the workflow on merging a PR
+on:
+ pull_request:
+ types:
+ - closed
+ branches: [ "main" ]
+
+permissions:
+ contents: read
+ packages: write
+
+jobs:
+ if_merged:
+ if: github.event.pull_request.merged == true
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ # Sets up the specified JDK version from the matrix
+ - uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: microsoft
+ cache: maven
+
+ - name: Build artifacts
+ run: ./mvnw -B -DskipTests -Pcompile-jdk8 -P-compile-jdk17 clean deploy --file pom.xml -DaltDeploymentRepository=local::file:///tmp/target/staging-deploy
+
+ - name: Upload Artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: Artifacts
+ path: /tmp/target/staging-deploy
+
+ - name: Deploy to github packages
+ run: ./mvnw -B -DskipTests -Pcompile-jdk8 -P-compile-jdk17 -Pgithub-packages clean deploy --file pom.xml
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/label-issues.yml b/.github/workflows/label-issues.yml
new file mode 100644
index 00000000..42806188
--- /dev/null
+++ b/.github/workflows/label-issues.yml
@@ -0,0 +1,54 @@
+name: Label issues
+on:
+ issues:
+ types:
+ - reopened
+ - opened
+
+jobs:
+ label_issues:
+ name: "Issue: add labels"
+ if: ${{ github.event.action == 'opened' || github.event.action == 'reopened' }}
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ steps:
+ - uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
+ script: |
+ // Get the issue body and title
+ const body = context.payload.issue.body
+ let title = context.payload.issue.title
+
+ // Define the labels array
+ let labels = ["triage"]
+
+ // Check if the body or the title contains the word 'python' (case-insensitive)
+ if ((body != null && body.match(/python/i)) || (title != null && title.match(/python/i))) {
+ // Add the 'python' label to the array
+ labels.push("python")
+ }
+
+ // Check if the body or the title contains the word 'java' (case-insensitive)
+ if ((body != null && body.match(/java/i)) || (title != null && title.match(/java/i))) {
+ // Add the 'java' label to the array
+ labels.push("java")
+ }
+
+ // Check if the body or the title contains the words 'dotnet', '.net', 'c#' or 'csharp' (case-insensitive)
+ if ((body != null && body.match(/.net/i)) || (title != null && title.match(/.net/i)) ||
+ (body != null && body.match(/dotnet/i)) || (title != null && title.match(/dotnet/i)) ||
+ (body != null && body.match(/C#/i)) || (title != null && title.match(/C#/i)) ||
+ (body != null && body.match(/csharp/i)) || (title != null && title.match(/csharp/i))) {
+ // Add the '.NET' label to the array
+ labels.push(".NET")
+ }
+
+ // Add the labels to the issue
+ github.rest.issues.addLabels({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ labels: labels
+ });
diff --git a/.github/workflows/label-title-prefix.yml b/.github/workflows/label-title-prefix.yml
new file mode 100644
index 00000000..f443c980
--- /dev/null
+++ b/.github/workflows/label-title-prefix.yml
@@ -0,0 +1,73 @@
+name: Label title prefix
+on:
+ issues:
+ types: [labeled]
+ pull_request_target:
+ types: [labeled]
+
+jobs:
+ add_title_prefix:
+ name: "Issue/PR: add title prefix"
+ continue-on-error: true
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+
+ steps:
+ - uses: actions/github-script@v7
+ name: "Issue/PR: update title"
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ let prefixLabels = {
+ "python": "Python",
+ "java": "Java",
+ ".NET": ".Net"
+ };
+
+ function addTitlePrefix(title, prefix)
+ {
+ // Update the title based on the label and prefix
+ // Check if the title starts with the prefix (case-sensitive)
+ if (!title.startsWith(prefix + ": ")) {
+ // If not, check if the first word is the label (case-insensitive)
+ if (title.match(new RegExp(`^${prefix}`, 'i'))) {
+ // If yes, replace it with the prefix (case-sensitive)
+ title = title.replace(new RegExp(`^${prefix}`, 'i'), prefix);
+ } else {
+ // If not, prepend the prefix to the title
+ title = prefix + ": " + title;
+ }
+ }
+
+ return title;
+ }
+
+ labelAdded = context.payload.label.name
+
+ // Check if the issue or PR has the label
+ if (labelAdded in prefixLabels) {
+ let prefix = prefixLabels[labelAdded];
+ switch(context.eventName) {
+ case 'issues':
+ github.rest.issues.update({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title: addTitlePrefix(context.payload.issue.title, prefix)
+ });
+ break
+
+ case 'pull_request_target':
+ github.rest.pulls.update({
+ pull_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title: addTitlePrefix(context.payload.pull_request.title, prefix)
+ });
+ break
+ default:
+ core.setFailed('Unrecognited eventName: ' + context.eventName);
+ }
+ }
diff --git a/.github/workflows/markdown-link-check-config.json b/.github/workflows/markdown-link-check-config.json
new file mode 100644
index 00000000..50ada491
--- /dev/null
+++ b/.github/workflows/markdown-link-check-config.json
@@ -0,0 +1,39 @@
+{
+ "ignorePatterns": [
+ {
+ "pattern": "/github/"
+ },
+ {
+ "pattern": "./actions"
+ },
+ {
+ "pattern": "./blob"
+ },
+ {
+ "pattern": "./issues"
+ },
+ {
+ "pattern": "./discussions"
+ },
+ {
+ "pattern": "./pulls"
+ },
+ {
+ "pattern": "^http://localhost"
+ },
+ {
+ "pattern": "^https://localhost"
+ },
+ {
+ "pattern": "^https://platform.openai.com"
+ },
+ {
+ "pattern": "^https://outlook.office.com/bookings"
+ }
+ ],
+ "timeout": "20s",
+ "retryOn429": true,
+ "retryCount": 3,
+ "fallbackRetryDelay": "30s",
+ "aliveStatusCodes": [200, 206, 429, 500, 503]
+}
diff --git a/.github/workflows/markdown-link-check.yml b/.github/workflows/markdown-link-check.yml
new file mode 100644
index 00000000..c0993625
--- /dev/null
+++ b/.github/workflows/markdown-link-check.yml
@@ -0,0 +1,23 @@
+name: Check .md links
+
+on:
+ workflow_dispatch:
+ pull_request:
+ branches: [ "main" ]
+
+permissions:
+ contents: read
+
+jobs:
+ markdown-link-check:
+ runs-on: ubuntu-latest
+ # check out the latest version of the code
+ steps:
+ - 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"
diff --git a/.github/workflows/merge-gatekeeper.yml b/.github/workflows/merge-gatekeeper.yml
new file mode 100644
index 00000000..adb6811a
--- /dev/null
+++ b/.github/workflows/merge-gatekeeper.yml
@@ -0,0 +1,30 @@
+name: Merge Gatekeeper
+
+on:
+ pull_request:
+ branches: [ "main", "feature*" ]
+ merge_group:
+ branches: ["main"]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ merge-gatekeeper:
+ runs-on: ubuntu-latest
+ # Restrict permissions of the GITHUB_TOKEN.
+ # Docs: https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
+ permissions:
+ checks: read
+ statuses: read
+ steps:
+ - name: Run Merge Gatekeeper
+ # NOTE: v1 is updated to reflect the latest v1.x.y. Please use any tag/branch that suits your needs:
+ # https://github.com/upsidr/merge-gatekeeper/tags
+ # https://github.com/upsidr/merge-gatekeeper/branches
+ uses: upsidr/merge-gatekeeper@v1
+ if: github.event_name == 'pull_request'
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ timeout: 3600
diff --git a/.github/workflows/typos.yaml b/.github/workflows/typos.yaml
new file mode 100644
index 00000000..d7a937ba
--- /dev/null
+++ b/.github/workflows/typos.yaml
@@ -0,0 +1,29 @@
+# Check pull requests for typos.
+#
+# Configuration: .github/_typos.toml
+#
+# Info: https://github.com/marketplace/actions/typos-action
+# Local install: brew install typos-cli
+# Local install: conda install typos
+# Local run: typos -c .github/_typos.toml
+
+name: Spell Check
+
+on:
+ workflow_dispatch:
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ run:
+ name: Spell Check with Typos
+ runs-on: ubuntu-latest
+ steps:
+ - 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
diff --git a/.github/workflows/update-version.sh b/.github/workflows/update-version.sh
new file mode 100755
index 00000000..5db3622f
--- /dev/null
+++ b/.github/workflows/update-version.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+
+POSITIONAL_ARGS=()
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -f|--file)
+ file="$2"
+ shift # past argument
+ shift # past value
+ ;;
+ -p|--propsFile)
+ propsFile="$2"
+ shift # past argument
+ shift # past value
+ ;;
+ -b|--buildAndRevisionNumber)
+ buildAndRevisionNumber="$2"
+ shift # past argument
+ shift # past value
+ ;;
+ -*|--*)
+ echo "Unknown option $1"
+ exit 1
+ ;;
+ *)
+ POSITIONAL_ARGS+=("$1") # save positional arg
+ shift # past argument
+ ;;
+ esac
+done
+
+set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
+
+if [ -z "$file" ]; then
+ echo "ERROR: Parameter file (-f|--file) not provided"
+ exit 1;
+elif [ ! -f "$file" ]; then
+ echo "ERROR: file ${file} not found"
+ exit 1;
+fi
+
+if [ -n "$(cat $file | grep -i "false")" ]; then
+ echo "Project is marked as NOT packable - skipping."
+ exit 0;
+fi
+
+if [ -z "$propsFile" ]; then
+ echo "ERROR: Parameter propsFile (-f|--file) not provided"
+ exit 1;
+elif [ ! -f "$propsFile" ]; then
+ echo "ERROR: propsFile ${file} not found"
+ exit 1;
+fi
+
+if [ -z "$buildAndRevisionNumber" ]; then
+ echo "ERROR: Parameter buildAndRevisionNumber (-b|--buildAndRevisionNumber) not provided"
+ exit 1;
+fi
+
+propsVersionString=$(cat $propsFile | grep -i "");
+regex="([0-9.]*)<\/Version>"
+if [[ $propsVersionString =~ $regex ]]; then
+ propsVersion=${BASH_REMATCH[1]}
+else
+ echo "ERROR: Version tag not found in propsFile"
+ exit 1;
+fi
+
+if [ -z "$propsVersion" ]; then
+ echo "ERROR: Version tag not found in propsFile"
+ exit 1;
+elif [[ ! "$propsVersion" =~ ^0.* ]]; then
+ echo "ERROR: Version expected to start with 0. Actual: ${propsVersion}"
+ exit 1;
+fi
+
+fullVersionString="${propsVersion}.${buildAndRevisionNumber}-preview"
+
+if [[ ! "$fullVersionString" =~ ^0.* ]]; then
+ echo "ERROR: Version expected to start with 0. Actual: ${fullVersionString}"
+ exit 1;
+fi
+
+echo "==== Project: ${file} ====";
+echo "propsFile = ${propsFile}"
+echo "buildAndRevisionNumber = ${buildAndRevisionNumber}"
+echo "version prefix from propsFile = ${propsVersion}"
+echo "full version string: ${fullVersionString}"
+
+versionInProj=$(cat $file | grep -i "");
+if [ -n "$versionInProj" ]; then
+ # Version tag already exists in the csproj. Let's replace it.
+ echo "Updating version tag..."
+ content=$(cat $file | sed --expression="s/\([0-9]*.[0-9]*\)<\/Version>/$fullVersionString<\/Version>/g");
+else
+ # Version tag not found in the csproj. Let's add it.
+ echo "Project is packable - adding version tag..."
+ content=$(cat $file | sed --expression="s/<\/Project>/$fullVersionString<\/Version><\/PropertyGroup><\/Project>/g");
+fi
+
+if [ $? -ne 0 ]; then exit 1; fi
+echo "$content" && echo "$content" > $file;
+if [ $? -ne 0 ]; then exit 1; fi
+
+echo "DONE";
+echo "";
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..e6f26223
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,63 @@
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# JetBrains IntelliJ
+.idea
+*.ipr
+*.iml
+*.iws
+
+# Maven settings
+conf.properties
+java/**/target
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+
+# Eclipse m2e generated files
+# Eclipse Core
+.project
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+# Other
+.env
+certs/
+launchSettings.json
+config.development.yaml
+*.development.config
+*.development.json
+.DS_Store
+node_modules/
+obj/
+bin/
+_dev/
+.dev/
+*.devis.*
+.vs/
+*.user
+**/.vscode/chrome
+**/.vscode/.ropeproject/objectdb
+*.pyc
+.ipynb_checkpoints
+.jython_cache/
+__pycache__/
+.mypy_cache/
+__pypackages__/
+.pdm.toml
+global.json
diff --git a/java/.mvn/jvm.config b/.mvn/jvm.config
similarity index 100%
rename from java/.mvn/jvm.config
rename to .mvn/jvm.config
diff --git a/java/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
similarity index 100%
rename from java/.mvn/wrapper/maven-wrapper.properties
rename to .mvn/wrapper/maven-wrapper.properties
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 00000000..d24ed88a
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "ms-java.vscode-java-pack",
+ ]
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..bd5534a5
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,5 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..16667e41
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,25 @@
+{
+ "editor.formatOnType": true,
+ "editor.formatOnSave": true,
+ "editor.formatOnPaste": true,
+ "editor.bracketPairColorization.enabled": true,
+ "editor.guides.bracketPairs": "active",
+ "notebook.output.textLineLimit": 500,
+ "files.exclude": {
+ "**/.git": true,
+ "**/.svn": true,
+ "**/.hg": true,
+ "**/CVS": true,
+ "**/.DS_Store": true,
+ "**/Thumbs.db": true
+ },
+ "[java]": {
+ "editor.formatOnSave": false,
+ "editor.tabSize": 4,
+ "editor.codeActionsOnSave": {
+ "source.fixAll": "never"
+ },
+ },
+ "java.debug.settings.onBuildFailureProceed": true,
+ "java.compile.nullAnalysis.mode": "disabled"
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 00000000..feea3bb0
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,11 @@
+{
+ "version": "2.0.0",
+ "inputs": [
+ {
+ "id": "filter",
+ "type": "promptString",
+ "default": "",
+ "description": "Enter a filter to pass as argument or filter"
+ }
+ ]
+}
diff --git a/java/README.md b/BUILD.md
similarity index 97%
rename from java/README.md
rename to BUILD.md
index 190eb7f2..7c45218d 100644
--- a/java/README.md
+++ b/BUILD.md
@@ -111,8 +111,8 @@ Make sure your pull request has an objective title and a clear description expla
## License
-This project is licensed under the [MIT License](../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).
+This project has adopted the [Microsoft Open Source Code of Conduct](CODE_OF_CONDUCT.md).
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..3ad56c82
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,59 @@
+# 1.2.0
+
+- Add ability to use image_url as content for a OpenAi chat completion
+ - As part of this `ChatMessageTextContent` and `ChatMessageImageContent` was added that extends the
+ existing `ChatMessageContent` class. `ChatMessageContent` for now defaults to a text content type for backwards
+ compatibility. However, users are encouraged to migrate to using the builders on `ChatMessageTextContent` to
+ create text based chat messages.
+ - Constructors of `ChatMessageContent` were also modified to support this change.
+- Added preliminary hugging face implementation that is still in development/beta.
+- Added Gemini support
+- Added OpenTelemetry spans for OpenAI requests
+- Update the user agent for OpenAI requests
+- Move XML parsing classes to implementation package as they are not expected to be used by users.
+
+#### Non-API Changes
+
+- Reorganized the repository when moving to the new Github location
+- Removed non-Java files
+- Update readmes
+- Update build scripts
+- Bring back Spring example project
+
+# 1.1.5
+
+- Fix bug with removing new lines on function parameters on Windows
+- Fix bug forming serializing arguments to tool calls
+
+# 1.1.3
+
+- Fix bug appending plugin name to tool calls
+- Improve exception handling in OpenAIChatCompletion
+
+# 1.1.2
+
+- Upgrade azure-identity to 1.12.1
+- Remove fixed netty version in bom
+
+# 1.1.1
+
+- Upgrade azure-ai-openai to 1.0.0-beta.8
+
+# 1.1.0
+
+### Breaking Changes
+
+- `ChatHistory` no longer has a default message, see below for more details.
+
+### Api Changes
+
+- Allow setting deployment name in addition to modelId on AI services.
+- Remove default message of "Assistant is a large language model" from ChatHistory
+ - **This is a breaking change if you were relying on the default message in your code**
+- Add InvocationReturnMode and rework OpenAi chat completion to allow configuring what data is returned from Chat
+ requests
+
+### Other
+
+- Reorganize example projects and documentation structure.
+- Number of sample updates and bug fixes.
\ No newline at end of file
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..f9ba8cf6
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,9 @@
+# Microsoft Open Source Code of Conduct
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+
+Resources:
+
+- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
+- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
+- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
diff --git a/COMMUNITY.md b/COMMUNITY.md
new file mode 100644
index 00000000..be98d425
--- /dev/null
+++ b/COMMUNITY.md
@@ -0,0 +1,32 @@
+# Welcome to the Semantic Kernel Community!
+
+Below are some ways that you can get involved in the SK Community.
+
+## Engage on Github
+
+File issues, submit PRs, and provide feedback and ideas to what you'd like to see from the Semantic Kernel.
+We do our best to respond to each submission.
+
+## Public Community Office Hours
+
+We regularly have Community Office Hours that are open to the **public** to join.
+
+Add Semantic Kernel events to your calendar - we're running two community calls to cater different timezones for Q&A Office Hours:
+* Americas timezone: download the [calendar.ics](https://aka.ms/sk-community-calendar) file.
+* Asia Pacific timezone: download the [calendar-APAC.ics](https://aka.ms/sk-community-calendar-apac) file.
+
+Add Semantic Kernel Development Office Hours for Python and Java to your calendar to help with development:
+* Java Development Office Hours: [Java Development Office Hours](https://aka.ms/sk-java-dev-sync)
+* Python Development Office Hours: [Python Development Office Hours](https://aka.ms/sk-python-dev-sync)
+
+If you have any questions or if you would like to showcase your project(s), please email what you'd like us to cover here: skofficehours[at]microsoft.com.
+
+If you are unable to make it live, all meetings will be recorded and posted online.
+
+## Join the conversation on Discord
+
+We have a growing and active channel on Discord where you can get help, engage in lively discussion,
+and share what you've built with Semantic Kernel!
+
+Join our Discord:
+[https://aka.ms/SKDiscord](https://aka.ms/SKDiscord)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..14cbb9be
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,147 @@
+# Contributing to Semantic Kernel
+
+You can contribute to Semantic Kernel with issues and pull requests (PRs). Simply
+filing issues for problems you encounter is a great way to contribute. Contributing
+code is greatly appreciated.
+
+## Reporting Issues
+
+We always welcome bug reports, API proposals and overall feedback. Here are a few
+tips on how you can make reporting your issue as effective as possible.
+
+### Where to Report
+
+New issues can be reported in our [list of issues](https://github.com/microsoft/semantic-kernel/issues).
+
+Before filing a new issue, please search the list of issues to make sure it does
+not already exist.
+
+If you do find an existing issue for what you wanted to report, please include
+your own feedback in the discussion. Do consider upvoting (👍 reaction) the original
+post, as this helps us prioritize popular issues in our backlog.
+
+### Writing a Good Bug Report
+
+Good bug reports make it easier for maintainers to verify and root cause the
+underlying problem.
+The better a bug report, the faster the problem will be resolved. Ideally, a bug
+report should contain the following information:
+
+- A high-level description of the problem.
+- A _minimal reproduction_, i.e. the smallest size of code/configuration required
+ to reproduce the wrong behavior.
+- A description of the _expected behavior_, contrasted with the _actual behavior_ observed.
+- Information on the environment: OS/distribution, CPU architecture, SDK version, etc.
+- Additional information, e.g. Is it a regression from previous versions? Are there
+ any known workarounds?
+
+## Contributing Changes
+
+Project maintainers will merge accepted code changes from contributors.
+
+### DOs and DON'Ts
+
+DO's:
+
+- **DO** follow the standard coding conventions
+
+ - [.NET](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions)
+ - [Python](https://pypi.org/project/black/)
+ - [Typescript](https://typescript-eslint.io/rules/)/[React](https://github.com/jsx-eslint/eslint-plugin-react/tree/master/docs/rules)
+
+- **DO** give priority to the current style of the project or file you're changing
+ if it diverges from the general guidelines.
+- **DO** include tests when adding new features. When fixing bugs, start with
+ adding a test that highlights how the current behavior is broken.
+- **DO** keep the discussions focused. When a new or related topic comes up
+ it's often better to create new issue than to side track the discussion.
+- **DO** clearly state on an issue that you are going to take on implementing it.
+- **DO** blog and tweet (or whatever) about your contributions, frequently!
+
+DON'Ts:
+
+- **DON'T** surprise us with big pull requests. Instead, file an issue and start
+ a discussion so we can agree on a direction before you invest a large amount of time.
+- **DON'T** commit code that you didn't write. If you find code that you think is a good
+ fit to add to Semantic Kernel, file an issue and start a discussion before proceeding.
+- **DON'T** submit PRs that alter licensing related files or headers. If you believe
+ there's a problem with them, file an issue and we'll be happy to discuss it.
+- **DON'T** make new APIs without filing an issue and discussing with us first.
+
+### Breaking Changes
+
+Contributions must maintain API signature and behavioral compatibility. Contributions
+that include breaking changes will be rejected. Please file an issue to discuss
+your idea or change if you believe that a breaking change is warranted.
+
+### Suggested Workflow
+
+We use and recommend the following workflow:
+
+1. Create an issue for your work.
+ - You can skip this step for trivial changes.
+ - Reuse an existing issue on the topic, if there is one.
+ - Get agreement from the team and the community that your proposed change is
+ a good one.
+ - Clearly state that you are going to take on implementing it, if that's the case.
+ You can request that the issue be assigned to you. Note: The issue filer and
+ the implementer don't have to be the same person.
+2. Create a personal fork of the repository on GitHub (if you don't already have one).
+3. In your fork, create a branch off of main (`git checkout -b mybranch`).
+ - Name the branch so that it clearly communicates your intentions, such as
+ "issue-123" or "githubhandle-issue".
+4. Make and commit your changes to your branch.
+5. Add new tests corresponding to your change, if applicable.
+6. Run the relevant scripts in [the section below](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#dev-scripts) to ensure that your build is clean and all tests are passing.
+7. Create a PR against the repository's **main** branch.
+ - State in the description what issue or improvement your change is addressing.
+ - Verify that all the Continuous Integration checks are passing.
+8. Wait for feedback or approval of your changes from the code maintainers.
+9. When area owners have signed off, and all checks are green, your PR will be merged.
+
+### Development scripts
+
+The scripts below are used to build, test, and lint within the project.
+
+- Python: see [python/DEV_SETUP.md](https://github.com/microsoft/semantic-kernel/blob/main/python/DEV_SETUP.md#pipeline-checks).
+- .NET:
+ - Build/Test: `run build.cmd` or `bash build.sh`
+ - Linting (auto-fix): `dotnet format`
+- Typescript:
+ - Build/Test: `yarn build`
+ - Linting (auto-fix): `yarn lint:fix`
+
+### Adding Plugins and Memory Connectors
+
+When considering contributions to plugins and memory connectors for Semantic
+Kernel, please note the following guidelines:
+
+#### Plugins
+
+We appreciate your interest in extending Semantic Kernel's functionality through
+plugins. However, we want to clarify our approach to hosting plugins within our
+GitHub repository. To maintain a clean and manageable codebase, we will not be
+hosting plugins directly in the Semantic Kernel GitHub repository.
+Instead, we encourage contributors to host their plugin code in separate
+repositories under their own GitHub accounts or organization. You can then
+provide a link to your plugin repository in the relevant discussions, issues,
+or documentation within the Semantic Kernel repository. This approach ensures
+that each plugin can be maintained independently and allows for easier tracking
+of updates and issues specific to each plugin.
+
+#### Memory Connectors
+
+For memory connectors, while we won't be directly adding hosting for them within
+the Semantic Kernel repository, we highly recommend building memory connectors
+as separate plugins. Memory connectors play a crucial role in interfacing with
+external memory systems, and treating them as plugins enhances modularity and
+maintainability.
+
+### PR - CI Process
+
+The continuous integration (CI) system will automatically perform the required
+builds and run tests (including the ones you are expected to run) for PRs. Builds
+and test runs must be clean.
+
+If the CI build fails for any reason, the PR issue will be updated with a link
+that can be used to determine the cause of the failure.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..9e841e7a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/java/PACKAGES.md b/PACKAGES.md
similarity index 100%
rename from java/PACKAGES.md
rename to PACKAGES.md
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..715b979a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+[](https://github.com/microsoft/semantic-kernel-java/actions/workflows/java-build.yml)
+[](https://maven-badges.herokuapp.com/maven-central/com.microsoft.semantic-kernel/semantickernel-api)
+[](https://github.com/microsoft/semantic-kernel-java/blob/main/LICENSE)
+[](https://aka.ms/SKDiscord)
+
+# Semantic Kernel for Java
+
+Welcome to the Semantic Kernel for Java. For detailed documentation, visit [Microsoft Learn](https://learn.microsoft.com/en-us/semantic-kernel/overview/?tabs=Java).
+
+[Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/overview/) is an SDK that integrates Large Language Models (LLMs) like [OpenAI](https://platform.openai.com/docs/introduction), [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), and [Hugging Face](https://huggingface.co/)
+with conventional programming languages like C#, Python, and Java. Semantic Kernel achieves this by allowing you to define [plugins](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/plugins) that can be chained together in just a [few lines of code](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/chaining-functions?tabs=Java#using-the-runasync-method-to-simplify-your-code).
+
+What makes Semantic Kernel _special_, however, is its ability to _automatically_ orchestrate plugins with AI. With Semantic Kernel [planners](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planner), you can ask an LLM to generate a plan that achieves a user's unique goal. Afterwards, Semantic Kernel will execute the plan for the user.
+
+For C#, Python and other language support, see [microsoft/semantic-kernel](https://github.com/microsoft/semantic-kernel).
+
+#### Please star the repo to show your support for this project!
+
+
+
+## Getting started with Semantic Kernel for Java
+
+The quickest way to get started with the basics is to get an API key from either OpenAI or Azure OpenAI and to run one of the Java console applications/scripts below.
+
+1. Clone the repository: `git clone https://github.com/microsoft/semantic-kernel-java.git`
+2. Follow the instructions [Start learning how to use Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/get-started/quick-start-guide?tabs=Java).
+
+## Documentation: Learning how to use Semantic Kernel
+
+The fastest way to learn how to use Semantic Kernel is with our walkthroughs
+on our Learn site.
+
+1. 📖 [Overview of the kernel](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/?tabs=Java)
+1. 🔌 [Understanding AI plugins](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/plugins?tabs=Java)
+1. 👄 [Creating semantic functions](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/semantic-functions?tabs=Java)
+1. 💽 [Creating native functions](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/native-functions?tabs=Java)
+1. ⛓️ [Chaining functions together](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/chaining-functions?tabs=Java)
+1. 🤖 [Auto create plans with planner](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planner?tabs=Java)
+1. 💡 [Create and run a ChatGPT plugin](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/chatgpt-plugins?tabs=Java)
+
+## Join the community
+
+We welcome your contributions and suggestions to SK community! One of the easiest
+ways to participate is to engage in discussions in the GitHub repository.
+Bug reports and fixes are welcome!
+
+For new features, components, or extensions, please open an issue and discuss with
+us before sending a PR. This is to avoid rejection as we might be taking the core
+in a different direction, but also to consider the impact on the larger ecosystem.
+
+To learn more and get started:
+
+- Read the [documentation](https://learn.microsoft.com/en-us/semantic-kernel/overview/?tabs=Java)
+- Learn how to [contribute](https://learn.microsoft.com/en-us/semantic-kernel/get-started/contributing) to the project
+- Join the [Discord community](https://aka.ms/SKDiscord)
+- Attend [regular office hours and SK community events](COMMUNITY.md)
+- Follow the team on our [blog](https://aka.ms/sk/blog)
+
+## Contributor Wall of Fame
+
+[](https://github.com/microsoft/semantic-kernel-java/graphs/contributors)
+
+## Code of Conduct
+
+This project has adopted the
+[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the
+[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
+or contact [opencode@microsoft.com](mailto:opencode@microsoft.com)
+with any additional questions or comments.
+
+## License
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Licensed under the [MIT](LICENSE) license.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..eed215e1
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,41 @@
+
+
+## Security
+
+Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
+
+If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://www.microsoft.com/en-us/msrc/definition-of-a-security-vulnerability?rtc=1), please report it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
+
+If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc?rtc=2).
+
+You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/en-us/msrc?rtc=2).
+
+Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
+
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+ * Full paths of source file(s) related to the manifestation of the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://www.microsoft.com/en-us/msrc/bounty?rtc=2) page for more details about our active programs.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd?rtc=2).
+
+
diff --git a/aiservices/google/pom.xml b/aiservices/google/pom.xml
new file mode 100644
index 00000000..ef878373
--- /dev/null
+++ b/aiservices/google/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ com.microsoft.semantic-kernel
+ semantickernel-parent
+ 1.2.0
+ ../../pom.xml
+
+
+ semantickernel-aiservices-google
+ Semantic Kernel Google Services
+ Google services for Semantic Kernel
+
+
+
+
+ com.google.cloud
+ libraries-bom
+ 26.37.0
+ pom
+ import
+
+
+
+
+
+
+ com.google.cloud
+ google-cloud-vertexai
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-api
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ compile
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ compile
+
+
+
+
+ javax.xml.stream
+ stax-api
+ provided
+
+
+
+
\ No newline at end of file
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/GeminiService.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/GeminiService.java
new file mode 100644
index 00000000..7155074f
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/GeminiService.java
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google;
+
+import com.google.cloud.vertexai.VertexAI;
+import com.microsoft.semantickernel.services.AIService;
+
+import javax.annotation.Nullable;
+
+public class GeminiService implements AIService {
+ private final VertexAI client;
+ private final String modelId;
+
+ protected GeminiService(VertexAI client, String modelId) {
+ this.client = client;
+ this.modelId = modelId;
+ }
+
+ @Nullable
+ @Override
+ public String getModelId() {
+ return modelId;
+ }
+
+ @Nullable
+ @Override
+ public String getServiceId() {
+ return null;
+ }
+
+ protected VertexAI getClient() {
+ return client;
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/GeminiServiceBuilder.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/GeminiServiceBuilder.java
new file mode 100644
index 00000000..c5d3f658
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/GeminiServiceBuilder.java
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google;
+
+import com.google.cloud.vertexai.VertexAI;
+import com.microsoft.semantickernel.builders.SemanticKernelBuilder;
+import javax.annotation.Nullable;
+
+/**
+ * Builder for a Gemini service.
+ */
+public abstract class GeminiServiceBuilder> implements
+ SemanticKernelBuilder {
+
+ @Nullable
+ protected String modelId;
+ @Nullable
+ protected VertexAI client;
+
+ /**
+ * Sets the model ID for the service
+ *
+ * @param modelId The model ID
+ * @return The builder
+ */
+ public U withModelId(String modelId) {
+ this.modelId = modelId;
+ return (U) this;
+ }
+
+ /**
+ * Sets the VertexAI client for the service
+ *
+ * @param client The VertexAI client
+ * @return The builder
+ */
+ public U withVertexAIClient(VertexAI client) {
+ this.client = client;
+ return (U) this;
+ }
+
+ @Override
+ public abstract T build();
+}
\ No newline at end of file
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java
new file mode 100644
index 00000000..8aa669f0
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatCompletion.java
@@ -0,0 +1,402 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.chatcompletion;
+
+import com.google.cloud.vertexai.VertexAI;
+import com.google.cloud.vertexai.api.Content;
+import com.google.cloud.vertexai.api.FunctionDeclaration;
+import com.google.cloud.vertexai.api.FunctionResponse;
+import com.google.cloud.vertexai.api.GenerateContentResponse;
+import com.google.cloud.vertexai.api.GenerationConfig;
+import com.google.cloud.vertexai.api.Part;
+import com.google.cloud.vertexai.api.Schema;
+import com.google.cloud.vertexai.api.Tool;
+import com.google.cloud.vertexai.api.Type;
+import com.google.cloud.vertexai.generativeai.GenerativeModel;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Value;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.google.GeminiService;
+import com.microsoft.semantickernel.aiservices.google.implementation.MonoConverter;
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
+import com.microsoft.semantickernel.exceptions.AIException;
+import com.microsoft.semantickernel.exceptions.SKCheckedException;
+import com.microsoft.semantickernel.exceptions.SKException;
+import com.microsoft.semantickernel.orchestration.FunctionResult;
+import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
+import com.microsoft.semantickernel.orchestration.InvocationContext;
+import com.microsoft.semantickernel.orchestration.InvocationReturnMode;
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
+import com.microsoft.semantickernel.plugin.KernelPlugin;
+import com.microsoft.semantickernel.semanticfunctions.InputVariable;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import com.microsoft.semantickernel.aiservices.google.GeminiServiceBuilder;
+import java.io.IOException;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+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;
+
+public class GeminiChatCompletion extends GeminiService implements ChatCompletionService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GeminiChatCompletion.class);
+
+ public GeminiChatCompletion(VertexAI client, String modelId) {
+ super(client, modelId);
+ }
+
+ /**
+ * Create a new instance of {@link GeminiChatCompletion.Builder}.
+ *
+ * @return a new instance of {@link GeminiChatCompletion.Builder}
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Mono>> getChatMessageContentsAsync(String prompt,
+ @Nullable Kernel kernel, @Nullable InvocationContext invocationContext) {
+ GeminiXMLPromptParser.GeminiParsedPrompt parsedPrompt = GeminiXMLPromptParser.parse(prompt);
+
+ return this.getChatMessageContentsAsync(parsedPrompt.getChatHistory(), kernel,
+ invocationContext);
+ }
+
+ @Override
+ public Mono>> getChatMessageContentsAsync(ChatHistory chatHistory,
+ @Nullable Kernel kernel, @Nullable InvocationContext invocationContext) {
+ return internalChatMessageContentsAsync(
+ new ChatHistory(chatHistory.getMessages()),
+ new ChatHistory(),
+ kernel,
+ invocationContext,
+ Math.min(MAXIMUM_INFLIGHT_AUTO_INVOKES,
+ invocationContext != null && invocationContext.getToolCallBehavior() != null
+ ? invocationContext.getToolCallBehavior().getMaximumAutoInvokeAttempts()
+ : 0));
+ }
+
+ private Mono>> internalChatMessageContentsAsync(
+ ChatHistory fullHistory, ChatHistory newHistory, @Nullable Kernel kernel,
+ @Nullable InvocationContext invocationContext, int invocationAttempts) {
+
+ List contents = getContents(fullHistory);
+
+ try {
+ GenerativeModel model = getGenerativeModel(kernel, invocationContext);
+ return MonoConverter.fromApiFuture(model.generateContentAsync(contents))
+ .doOnError(e -> LOGGER.error("Error generating chat completion", e))
+ .flatMap(result -> {
+ // Get ChatMessageContent from the response
+ GeminiChatMessageContent> response = getGeminiChatMessageContentFromResponse(
+ result);
+
+ // Add assistant response to the chat history
+ fullHistory.addMessage(response);
+ newHistory.addMessage(response);
+
+ // Just return the result:
+ // If we don't want to attempt to invoke any functions or if we have no function calls
+ if (invocationAttempts <= 0 || response.getGeminiFunctionCalls().isEmpty()) {
+ if (invocationContext != null && invocationContext
+ .returnMode() == InvocationReturnMode.FULL_HISTORY) {
+ return Mono.just(fullHistory.getMessages());
+ }
+ if (invocationContext != null && invocationContext
+ .returnMode() == InvocationReturnMode.LAST_MESSAGE_ONLY) {
+ ChatHistory lastMessage = new ChatHistory();
+ lastMessage.addMessage(response);
+
+ return Mono.just(lastMessage.getMessages());
+ }
+
+ return Mono.just(newHistory.getMessages());
+ }
+
+ // Perform the function calls
+ List> functionResults = response
+ .getGeminiFunctionCalls().stream()
+ .map(geminiFunctionCall -> performFunctionCall(kernel, invocationContext,
+ geminiFunctionCall))
+ .collect(Collectors.toList());
+
+ Mono> combinedResults = Flux
+ .fromIterable(functionResults)
+ .flatMap(mono -> mono)
+ .collectList();
+
+ // Add the function responses to the chat history
+ return combinedResults.flatMap(results -> {
+ ChatMessageContent> functionResponsesMessage = new GeminiChatMessageContent<>(
+ AuthorRole.USER,
+ "", null, null, null, null, results);
+
+ fullHistory.addMessage(functionResponsesMessage);
+ newHistory.addMessage(functionResponsesMessage);
+
+ return internalChatMessageContentsAsync(fullHistory, newHistory, kernel,
+ invocationContext, invocationAttempts - 1);
+ });
+ });
+ } catch (SKCheckedException | IOException e) {
+ return Mono.error(new SKException("Error generating chat completion", e));
+ }
+ }
+
+ // Convert from ChatHistory to List
+ private List getContents(ChatHistory chatHistory) {
+ List contents = new ArrayList<>();
+ chatHistory.forEach(chatMessageContent -> {
+ Content.Builder contentBuilder = Content.newBuilder();
+
+ if (chatMessageContent.getAuthorRole() == AuthorRole.USER) {
+ contentBuilder.setRole(GeminiRole.USER.toString());
+
+ if (chatMessageContent instanceof GeminiChatMessageContent) {
+ GeminiChatMessageContent> message = (GeminiChatMessageContent>) chatMessageContent;
+
+ message.getGeminiFunctionCalls().forEach(geminiFunction -> {
+ FunctionResult> functionResult = geminiFunction.getFunctionResult();
+ if (functionResult == null || functionResult.getResult() == null) {
+ throw new SKException("Gemini failed to return a result");
+ }
+
+ FunctionResponse functionResponse = FunctionResponse.newBuilder()
+ .setName(geminiFunction.getFunctionCall().getName())
+ .setResponse(Struct.newBuilder().putFields("result",
+ Value.newBuilder()
+ .setStringValue(
+ (String) functionResult.getResult())
+ .build()))
+ .build();
+
+ contentBuilder
+ .addParts(Part.newBuilder().setFunctionResponse(functionResponse));
+ });
+ }
+ } else if (chatMessageContent.getAuthorRole() == AuthorRole.ASSISTANT) {
+ contentBuilder.setRole(GeminiRole.MODEL.toString());
+
+ if (chatMessageContent instanceof GeminiChatMessageContent) {
+ GeminiChatMessageContent> message = (GeminiChatMessageContent>) chatMessageContent;
+
+ message.getGeminiFunctionCalls().forEach(geminiFunctionCall -> {
+ contentBuilder.addParts(Part.newBuilder()
+ .setFunctionCall(geminiFunctionCall.getFunctionCall()));
+ });
+ }
+ }
+
+ if (chatMessageContent.getContent() != null
+ && !chatMessageContent.getContent().isEmpty()) {
+ contentBuilder.addParts(Part.newBuilder().setText(chatMessageContent.getContent()));
+ }
+
+ contents.add(contentBuilder.build());
+ });
+
+ return contents;
+ }
+
+ private GeminiChatMessageContent> getGeminiChatMessageContentFromResponse(
+ GenerateContentResponse response) {
+ StringBuilder message = new StringBuilder();
+ List functionCalls = new ArrayList<>();
+
+ response.getCandidatesList().forEach(
+ candidate -> {
+ Content content = candidate.getContent();
+ if (content.getPartsCount() == 0) {
+ return;
+ }
+
+ content.getPartsList().forEach(part -> {
+ if (!part.getFunctionCall().getName().isEmpty()) {
+ // We only care about the function call here
+ // Execution of the function call will be done later
+ functionCalls.add(new GeminiFunctionCall(part.getFunctionCall(), null));
+ }
+ if (!part.getText().isEmpty()) {
+ message.append(part.getText());
+ }
+ });
+ });
+
+ FunctionResultMetadata metadata = FunctionResultMetadata
+ .build(UUID.randomUUID().toString(), response.getUsageMetadata(), OffsetDateTime.now());
+
+ return new GeminiChatMessageContent<>(AuthorRole.ASSISTANT,
+ message.toString(), null, null, null, metadata, functionCalls);
+ }
+
+ private GenerativeModel getGenerativeModel(@Nullable Kernel kernel,
+ @Nullable InvocationContext invocationContext) throws SKCheckedException {
+ GenerativeModel.Builder modelBuilder = new GenerativeModel.Builder()
+ .setModelName(getModelId())
+ .setVertexAi(getClient());
+
+ if (invocationContext != null) {
+ if (invocationContext.getPromptExecutionSettings() != null) {
+ PromptExecutionSettings settings = invocationContext.getPromptExecutionSettings();
+
+ if (settings.getResultsPerPrompt() < 1
+ || settings.getResultsPerPrompt() > MAX_RESULTS_PER_PROMPT) {
+ throw SKCheckedException.build("Error building generative model.",
+ new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ String.format(
+ "Results per prompt must be in range between 1 and %d, inclusive.",
+ MAX_RESULTS_PER_PROMPT)));
+ }
+
+ GenerationConfig config = GenerationConfig.newBuilder()
+ .setMaxOutputTokens(settings.getMaxTokens())
+ .setTemperature((float) settings.getTemperature())
+ .setTopP((float) settings.getTopP())
+ .setCandidateCount(settings.getResultsPerPrompt())
+ .build();
+
+ modelBuilder.setGenerationConfig(config);
+ }
+
+ if (invocationContext.getToolCallBehavior() != null && kernel != null) {
+ List tools = new ArrayList<>();
+ Tool tool = getTool(kernel, invocationContext.getToolCallBehavior());
+ if (tool != null) {
+ tools.add(tool);
+ }
+ modelBuilder.setTools(tools);
+ }
+ }
+
+ return modelBuilder.build();
+ }
+
+ private FunctionDeclaration buildFunctionDeclaration(KernelFunction> function) {
+ FunctionDeclaration.Builder functionBuilder = FunctionDeclaration.newBuilder();
+ functionBuilder.setName(
+ ToolCallBehavior.formFullFunctionName(function.getPluginName(), function.getName()));
+ functionBuilder.setDescription(function.getDescription());
+
+ List parameters = function.getMetadata().getParameters();
+ if (parameters != null && !parameters.isEmpty()) {
+ Schema.Builder parametersBuilder = Schema.newBuilder();
+
+ function.getMetadata().getParameters().forEach(parameter -> {
+ parametersBuilder.setType(Type.OBJECT);
+ parametersBuilder.putProperties(
+ parameter.getName(),
+ Schema.newBuilder().setType(Type.STRING)
+ .setDescription(parameter.getDescription()).build());
+ });
+
+ functionBuilder.setParameters(parametersBuilder.build());
+ }
+
+ return functionBuilder.build();
+ }
+
+ @Nullable
+ private Tool getTool(@Nullable Kernel kernel, @Nullable ToolCallBehavior toolCallBehavior) {
+ if (kernel == null || toolCallBehavior == null) {
+ return null;
+ }
+
+ Tool.Builder toolBuilder = Tool.newBuilder();
+
+ // If a specific function is required to be called
+ if (toolCallBehavior instanceof ToolCallBehavior.RequiredKernelFunction) {
+ KernelFunction> kernelFunction = ((ToolCallBehavior.RequiredKernelFunction) toolCallBehavior)
+ .getRequiredFunction();
+
+ toolBuilder.addFunctionDeclarations(buildFunctionDeclaration(kernelFunction));
+ }
+ // If a set of functions are enabled to be called
+ if (toolCallBehavior instanceof ToolCallBehavior.AllowedKernelFunctions) {
+ ToolCallBehavior.AllowedKernelFunctions enabledKernelFunctions = (ToolCallBehavior.AllowedKernelFunctions) toolCallBehavior;
+
+ kernel.getPlugins()
+ .forEach(plugin -> plugin.getFunctions().forEach((name, function) -> {
+ // check if all kernel functions are enabled or if the specific function is enabled
+ if (enabledKernelFunctions.isAllKernelFunctionsAllowed() ||
+ enabledKernelFunctions.isFunctionAllowed(function.getPluginName(),
+ function.getName())) {
+ toolBuilder.addFunctionDeclarations(buildFunctionDeclaration(function));
+ }
+ }));
+ }
+
+ return toolBuilder.build();
+ }
+
+ public Mono performFunctionCall(@Nullable Kernel kernel,
+ @Nullable InvocationContext invocationContext, GeminiFunctionCall geminiFunction) {
+ if (kernel == null) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "Kernel must be provided to perform function call");
+ }
+
+ String[] name = geminiFunction.getFunctionCall().getName()
+ .split(ToolCallBehavior.FUNCTION_NAME_SEPARATOR);
+
+ String pluginName = name[0];
+ String functionName = name[1];
+
+ KernelPlugin plugin = kernel.getPlugin(pluginName);
+ if (plugin == null) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ String.format("Plugin %s not found in kernel", pluginName));
+ }
+ KernelFunction> function = plugin.get(functionName);
+
+ if (function == null) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ String.format("Kernel function %s not found in plugin %s", functionName,
+ pluginName));
+ }
+
+ ContextVariableTypes contextVariableTypes = invocationContext == null
+ ? new ContextVariableTypes()
+ : invocationContext.getContextVariableTypes();
+
+ KernelFunctionArguments.Builder arguments = KernelFunctionArguments.builder();
+ geminiFunction.getFunctionCall().getArgs().getFieldsMap().forEach((key, value) -> {
+ arguments.withVariable(key, value.getStringValue());
+ });
+
+ return function
+ .invokeAsync(kernel)
+ .withArguments(arguments.build())
+ .withResultType(contextVariableTypes.getVariableTypeForClass(String.class))
+ .map(result -> new GeminiFunctionCall(geminiFunction.getFunctionCall(), result));
+ }
+
+ public static class Builder extends GeminiServiceBuilder {
+
+ @Override
+ public GeminiChatCompletion build() {
+ if (this.client == null) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "VertexAI client must be provided");
+ }
+
+ if (this.modelId == null || modelId.isEmpty()) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "Gemini model id must be provided");
+ }
+
+ return new GeminiChatCompletion(client, modelId);
+ }
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatMessageContent.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatMessageContent.java
new file mode 100644
index 00000000..28cae4fb
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiChatMessageContent.java
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.chatcompletion;
+
+import com.google.cloud.vertexai.api.FunctionCall;
+import com.google.cloud.vertexai.api.FunctionResponse;
+import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Represents the content of a chat message.
+ *
+ * @param The type of the inner content.
+ */
+public class GeminiChatMessageContent extends ChatMessageContent {
+ @Nonnull
+ private final List geminiFunctionCalls;
+
+ /**
+ * Creates a new instance of the {@link GeminiChatMessageContent} class.
+ *
+ * @param authorRole The author role that generated the content.
+ * @param content The content.
+ * @param modelId The model id.
+ * @param innerContent The inner content.
+ * @param encoding The encoding.
+ * @param metadata The metadata.
+ * @param geminiFunctionCalls The function calls.
+ */
+ public GeminiChatMessageContent(
+ AuthorRole authorRole,
+ String content,
+ @Nullable String modelId,
+ @Nullable T innerContent,
+ @Nullable Charset encoding,
+ @Nullable FunctionResultMetadata metadata,
+ @Nullable List geminiFunctionCalls) {
+ super(authorRole, content, modelId, innerContent, encoding, metadata);
+ if (geminiFunctionCalls == null) {
+ this.geminiFunctionCalls = Collections.emptyList();
+ } else {
+ this.geminiFunctionCalls = Collections.unmodifiableList(geminiFunctionCalls);
+ }
+ }
+
+ /**
+ * Gets the function calls.
+ *
+ * @return The function calls.
+ */
+ @Nonnull
+ public List getGeminiFunctionCalls() {
+ return Collections.unmodifiableList(geminiFunctionCalls);
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiFunctionCall.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiFunctionCall.java
new file mode 100644
index 00000000..fc64c830
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiFunctionCall.java
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.chatcompletion;
+
+import com.google.cloud.vertexai.api.FunctionCall;
+import com.microsoft.semantickernel.orchestration.FunctionResult;
+import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public class GeminiFunctionCall {
+ @Nonnull
+ private final FunctionCall functionCall;
+ @Nullable
+ private final FunctionResult> functionResult;
+ private final String pluginName;
+ private final String functionName;
+
+ @SuppressFBWarnings("EI_EXPOSE_REP2")
+ public GeminiFunctionCall(
+ @Nonnull FunctionCall functionCall,
+ @Nullable FunctionResult> functionResult) {
+ this.functionCall = functionCall;
+ this.functionResult = functionResult;
+
+ String[] name = functionCall.getName().split(ToolCallBehavior.FUNCTION_NAME_SEPARATOR);
+ this.pluginName = name[0];
+ this.functionName = name[1];
+ }
+
+ public String getPluginName() {
+ return pluginName;
+ }
+
+ public String getFunctionName() {
+ return functionName;
+ }
+
+ @SuppressFBWarnings("EI_EXPOSE_REP")
+ public FunctionCall getFunctionCall() {
+ return functionCall;
+ }
+
+ @Nullable
+ public FunctionResult> getFunctionResult() {
+ return functionResult;
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiRole.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiRole.java
new file mode 100644
index 00000000..74590723
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiRole.java
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.chatcompletion;
+
+public enum GeminiRole {
+ /**
+ * A user message is a message generated by the user.
+ */
+ USER("user"),
+ /**
+ * A model message is a message generated by the model.
+ */
+ MODEL("model");
+
+ private final String role;
+
+ private GeminiRole(String role) {
+ this.role = role;
+ }
+
+ @Override
+ public String toString() {
+ return role;
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiXMLPromptParser.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiXMLPromptParser.java
new file mode 100644
index 00000000..afde9a33
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/chatcompletion/GeminiXMLPromptParser.java
@@ -0,0 +1,141 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.chatcompletion;
+
+import com.azure.core.util.BinaryData;
+import com.google.cloud.vertexai.api.FunctionDeclaration;
+import com.google.cloud.vertexai.api.Schema;
+import com.microsoft.semantickernel.implementation.chatcompletion.ChatPromptParseVisitor;
+import com.microsoft.semantickernel.implementation.chatcompletion.ChatXMLPromptParser;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageTextContent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GeminiXMLPromptParser {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GeminiXMLPromptParser.class);
+
+ public static class GeminiParsedPrompt {
+
+ private final ChatHistory chatHistory;
+ private final List functions;
+
+ protected GeminiParsedPrompt(
+ ChatHistory parsedChatHistory,
+ @Nullable List parsedFunctions) {
+ this.chatHistory = parsedChatHistory;
+ if (parsedFunctions == null) {
+ parsedFunctions = new ArrayList<>();
+ }
+ this.functions = parsedFunctions;
+ }
+
+ public ChatHistory getChatHistory() {
+ return new ChatHistory(chatHistory.getMessages());
+ }
+
+ public List getFunctions() {
+ return Collections.unmodifiableList(functions);
+ }
+ }
+
+ private static AuthorRole getAuthorRole(String role) {
+ switch (role) {
+ case "user":
+ return AuthorRole.USER;
+ case "assistant":
+ return AuthorRole.ASSISTANT;
+ case "system":
+ return AuthorRole.SYSTEM;
+ case "tool":
+ return AuthorRole.TOOL;
+ default:
+ LOGGER.error("Unknown role: " + role);
+ return AuthorRole.USER;
+ }
+ }
+
+ private static class GeminiChatPromptParseVisitor
+ implements ChatPromptParseVisitor {
+
+ @Nullable
+ private GeminiParsedPrompt parsedRaw = null;
+ private final List functionDefinitions = new ArrayList<>();
+ private final ChatHistory chatHistory = new ChatHistory();
+
+ @Override
+ public ChatPromptParseVisitor addMessage(
+ String role,
+ String content) {
+ chatHistory.addMessage(
+ ChatMessageTextContent.builder()
+ .withContent(content)
+ .withAuthorRole(getAuthorRole(role))
+ .build());
+ return this;
+ }
+
+ @Override
+ public ChatPromptParseVisitor addFunction(
+ String name,
+ @Nullable String description,
+ @Nullable BinaryData parameters) {
+
+ // TODO: Build the parameters schema
+ Schema.Builder parametersBuilder = Schema.newBuilder();
+
+ FunctionDeclaration.Builder function = FunctionDeclaration.newBuilder()
+ .setName(name)
+ .setDescription(description)
+ .setParameters(parametersBuilder.build());
+
+ functionDefinitions.add(function.build());
+ return this;
+ }
+
+ @Override
+ public boolean areMessagesEmpty() {
+ return chatHistory.getMessages().isEmpty();
+ }
+
+ @Override
+ public ChatPromptParseVisitor fromRawPrompt(
+ String rawPrompt) {
+
+ ChatMessageContent> message = ChatMessageTextContent.userMessage(rawPrompt);
+
+ this.parsedRaw = new GeminiParsedPrompt(
+ new ChatHistory(Collections.singletonList(message)), null);
+
+ return this;
+ }
+
+ @Override
+ public GeminiParsedPrompt get() {
+ if (parsedRaw != null) {
+ return parsedRaw;
+ }
+
+ return new GeminiParsedPrompt(chatHistory, functionDefinitions);
+ }
+
+ @Override
+ public ChatPromptParseVisitor reset() {
+ return new GeminiChatPromptParseVisitor();
+ }
+ }
+
+ public static GeminiParsedPrompt parse(String rawPrompt) {
+ ChatPromptParseVisitor visitor = ChatXMLPromptParser.parse(
+ rawPrompt,
+ new GeminiChatPromptParseVisitor());
+
+ return visitor.get();
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/implementation/MonoConverter.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/implementation/MonoConverter.java
new file mode 100644
index 00000000..3209a03c
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/implementation/MonoConverter.java
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.implementation;
+
+import com.google.api.core.ApiFuture;
+import reactor.core.publisher.Mono;
+
+public class MonoConverter {
+ public static Mono fromApiFuture(ApiFuture apiFuture) {
+ return Mono.create(sink -> {
+ apiFuture.addListener(() -> {
+ try {
+ T result = apiFuture.get();
+ sink.success(result);
+ } catch (Exception e) {
+ sink.error(e);
+ }
+ }, runnable -> new Thread(runnable).start());
+ });
+ }
+}
diff --git a/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/textcompletion/GeminiTextGenerationService.java b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/textcompletion/GeminiTextGenerationService.java
new file mode 100644
index 00000000..4d7c2a25
--- /dev/null
+++ b/aiservices/google/src/main/java/com/microsoft/semantickernel/aiservices/google/textcompletion/GeminiTextGenerationService.java
@@ -0,0 +1,142 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.google.textcompletion;
+
+import com.google.cloud.vertexai.VertexAI;
+import com.google.cloud.vertexai.api.GenerateContentResponse;
+import com.google.cloud.vertexai.api.GenerationConfig;
+import com.google.cloud.vertexai.generativeai.GenerativeModel;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.google.GeminiService;
+import com.microsoft.semantickernel.aiservices.google.implementation.MonoConverter;
+import com.microsoft.semantickernel.exceptions.AIException;
+import com.microsoft.semantickernel.exceptions.SKCheckedException;
+import com.microsoft.semantickernel.exceptions.SKException;
+import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import com.microsoft.semantickernel.aiservices.google.GeminiServiceBuilder;
+import com.microsoft.semantickernel.services.textcompletion.StreamingTextContent;
+import com.microsoft.semantickernel.services.textcompletion.TextContent;
+import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.io.IOException;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class GeminiTextGenerationService extends GeminiService implements TextGenerationService {
+ private static final Logger LOGGER = LoggerFactory.getLogger(GeminiTextGenerationService.class);
+
+ public GeminiTextGenerationService(VertexAI client, String modelId) {
+ super(client, modelId);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Mono> getTextContentsAsync(
+ String prompt,
+ @Nullable PromptExecutionSettings executionSettings,
+ @Nullable Kernel kernel) {
+ return this.internalGetTextAsync(prompt, executionSettings);
+ }
+
+ @Override
+ public Flux getStreamingTextContentsAsync(
+ String prompt,
+ @Nullable PromptExecutionSettings executionSettings,
+ @Nullable Kernel kernel) {
+ return this
+ .internalGetTextAsync(prompt, executionSettings)
+ .flatMapMany(it -> Flux.fromStream(it.stream())
+ .map(StreamingTextContent::new));
+ }
+
+ private Mono> internalGetTextAsync(String prompt,
+ @Nullable PromptExecutionSettings executionSettings) {
+
+ try {
+ GenerativeModel model = getGenerativeModel(executionSettings);
+ return MonoConverter.fromApiFuture(model.generateContentAsync(prompt))
+ .doOnError(e -> LOGGER.error("Error generating text", e))
+ .flatMap(result -> {
+ List textContents = new ArrayList<>();
+
+ FunctionResultMetadata metadata = FunctionResultMetadata
+ .build(
+ UUID.randomUUID().toString(),
+ result.getUsageMetadata(),
+ OffsetDateTime.now());
+
+ result.getCandidatesList().forEach(
+ candidate -> {
+ candidate.getContent().getPartsList().forEach(part -> {
+ if (!part.getText().isEmpty()) {
+ textContents.add(
+ new TextContent(part.getText(), getModelId(), metadata));
+ }
+ });
+ });
+
+ return Mono.just(textContents);
+ });
+ } catch (SKCheckedException | IOException e) {
+ return Mono.error(new SKException("Error generating text", e));
+ }
+ }
+
+ private GenerativeModel getGenerativeModel(
+ @Nullable PromptExecutionSettings executionSettings) throws SKCheckedException {
+ GenerativeModel.Builder modelBuilder = new GenerativeModel.Builder()
+ .setModelName(getModelId())
+ .setVertexAi(getClient());
+
+ if (executionSettings != null) {
+ if (executionSettings.getResultsPerPrompt() < 1
+ || executionSettings.getResultsPerPrompt() > MAX_RESULTS_PER_PROMPT) {
+ throw SKCheckedException.build("Error building generative model.",
+ new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ String.format(
+ "Results per prompt must be in range between 1 and %d, inclusive.",
+ MAX_RESULTS_PER_PROMPT)));
+ }
+
+ GenerationConfig config = GenerationConfig.newBuilder()
+ .setMaxOutputTokens(executionSettings.getMaxTokens())
+ .setTemperature((float) executionSettings.getTemperature())
+ .setTopP((float) executionSettings.getTopP())
+ .setCandidateCount(executionSettings.getResultsPerPrompt())
+ .build();
+
+ modelBuilder.setGenerationConfig(config);
+ }
+
+ return modelBuilder.build();
+ }
+
+ public static class Builder extends
+ GeminiServiceBuilder {
+ @Override
+ public GeminiTextGenerationService build() {
+ if (this.client == null) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "VertexAI client must be provided");
+ }
+
+ if (this.modelId == null || modelId.isEmpty()) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "Gemini model id must be provided");
+ }
+
+ return new GeminiTextGenerationService(client, modelId);
+ }
+ }
+}
diff --git a/aiservices/huggingface/pom.xml b/aiservices/huggingface/pom.xml
new file mode 100644
index 00000000..f53983c9
--- /dev/null
+++ b/aiservices/huggingface/pom.xml
@@ -0,0 +1,66 @@
+
+
+
+ 4.0.0
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-parent
+ 1.2.0
+ ../../pom.xml
+
+
+ semantickernel-aiservices-huggingface
+ Semantic Kernel Huggingface Services
+ Huggingface services for Semantic Kernel
+
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-bom
+ ${project.version}
+ pom
+ import
+
+
+
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-api
+
+
+ com.azure
+ azure-core
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ compile
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ compile
+
+
+
+
+ javax.xml.stream
+ stax-api
+ provided
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/HuggingFaceClient.java b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/HuggingFaceClient.java
new file mode 100644
index 00000000..93fe64fd
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/HuggingFaceClient.java
@@ -0,0 +1,178 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.huggingface;
+
+import com.azure.core.credential.KeyCredential;
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpHeaderName;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.semantickernel.aiservices.huggingface.models.GeneratedTextItem;
+import com.microsoft.semantickernel.aiservices.huggingface.models.TextGenerationRequest;
+import com.microsoft.semantickernel.exceptions.SKException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import reactor.core.publisher.Mono;
+import javax.annotation.Nullable;
+
+public class HuggingFaceClient {
+
+ private final KeyCredential key;
+ private final String endpoint;
+ private final HttpClient httpClient;
+
+ public HuggingFaceClient(
+ KeyCredential key,
+ String endpoint,
+ HttpClient httpClient) {
+ this.key = key;
+ this.endpoint = endpoint;
+ this.httpClient = httpClient;
+ }
+
+ /*
+ * TODO: TGI
+ * public Mono getChatMessageContentsAsync(
+ * String modelId,
+ * ChatCompletionRequest chatCompletionRequest
+ * ) {
+ * try {
+ * String body = new ObjectMapper().writeValueAsString(chatCompletionRequest);
+ * return performRequest(modelId, body)
+ * .handle((response, sink) -> {
+ * ObjectMapper mapper = new ObjectMapper();
+ * JavaType type = mapper.getTypeFactory().
+ * constructCollectionType(List.class, GeneratedTextItem.class);
+ * try {
+ * sink.next(mapper.readValue(response, type));
+ * } catch (JsonProcessingException e) {
+ * sink.error(
+ * new SKException("Failed to deserialize response from Hugging Face",
+ * e));
+ * }
+ * });
+ * } catch (JsonProcessingException e) {
+ * return Mono.error(new SKException("Failed to serialize request body", e));
+ * }
+ * }
+ *
+ */
+
+ private static class GeneratedTextItemList {
+
+ private final List> generatedTextItems;
+
+ @JsonCreator
+ public GeneratedTextItemList(
+ List> generatedTextItems) {
+ this.generatedTextItems = generatedTextItems;
+ }
+
+ }
+
+ public Mono> getTextContentsAsync(
+ String modelId,
+ TextGenerationRequest textGenerationRequest) {
+ try {
+ String body = new ObjectMapper().writeValueAsString(textGenerationRequest);
+ return performRequest(modelId, body)
+ .handle((response, sink) -> {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JavaType type = mapper.getTypeFactory().constructCollectionType(List.class,
+ GeneratedTextItemList.class);
+ GeneratedTextItemList data = mapper.readValue(response,
+ GeneratedTextItemList.class);
+ sink.next(data.generatedTextItems.get(0));
+ } catch (Exception e) {
+ sink.error(
+ new SKException("Failed to deserialize response from Hugging Face",
+ e));
+ }
+ });
+ } catch (JsonProcessingException e) {
+ return Mono.error(new SKException("Failed to serialize request body", e));
+ }
+ }
+
+ private Mono performRequest(String modelId,
+ String body) {
+ HttpRequest request = new HttpRequest(HttpMethod.POST, endpoint)
+ .setHeader(HttpHeaderName.AUTHORIZATION, "Bearer " + key.getKey())
+ .setHeader(HttpHeaderName.CONTENT_TYPE, "application/json")
+ .setHeader(HttpHeaderName.fromString("azureml-model-deployment"), modelId);
+
+ request.setBody(body.getBytes(StandardCharsets.UTF_8));
+
+ Mono responseBody = httpClient
+ .send(request)
+ .onErrorResume(
+ e -> {
+ return Mono.error(
+ new SKException("Failed to send request to Hugging Face", e));
+ })
+ .flatMap(httpResponse -> {
+ if (httpResponse.getStatusCode() >= 400) {
+ return httpResponse.getBodyAsString()
+ .flatMap(errorBody -> {
+ return Mono.error(new SKException(
+ "Failed to get text content from Hugging Face. Status code: "
+ + httpResponse.getStatusCode() + " " + errorBody));
+ });
+ } else {
+ return Mono.just(httpResponse);
+ }
+ })
+ .flatMap(HttpResponse::getBodyAsString);
+ return responseBody;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ @Nullable
+ private KeyCredential key = null;
+ @Nullable
+ private String endpoint = null;
+ @Nullable
+ private HttpClient httpClient = null;
+
+ public HuggingFaceClient build() {
+ if (httpClient == null) {
+ httpClient = HttpClient.createDefault();
+ }
+ if (key == null) {
+ throw new SKException("Key credential is required");
+ }
+ if (endpoint == null) {
+ throw new SKException("Endpoint is required");
+ }
+ return new HuggingFaceClient(
+ key,
+ endpoint,
+ httpClient);
+ }
+
+ public Builder credential(KeyCredential key) {
+ this.key = key;
+ return this;
+ }
+
+ public Builder endpoint(String endpoint) {
+ this.endpoint = endpoint;
+ return this;
+ }
+
+ public Builder httpClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ return this;
+ }
+ }
+}
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/GeneratedTextItem.java b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/GeneratedTextItem.java
new file mode 100644
index 00000000..6f4125c6
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/GeneratedTextItem.java
@@ -0,0 +1,162 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.huggingface.models;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
+
+public class GeneratedTextItem {
+
+ @Nullable
+ @JsonProperty("generated_text")
+ private final String generatedText;
+
+ @Nullable
+ @JsonProperty("details")
+ private final TextGenerationDetails details;
+
+ @JsonCreator
+ public GeneratedTextItem(
+ @JsonProperty("generated_text") @Nullable String generatedText,
+ @JsonProperty("details") @Nullable TextGenerationDetails details) {
+ this.generatedText = generatedText;
+ this.details = details;
+ }
+
+ @Nullable
+ public String getGeneratedText() {
+ return generatedText;
+ }
+
+ @Nullable
+ public TextGenerationDetails getDetails() {
+ return details;
+ }
+
+ public static class TextGenerationDetails {
+
+ @Nullable
+ @JsonProperty("finish_reason")
+ private final String finishReason;
+
+ @JsonProperty("generated_tokens")
+ private final int generatedTokens;
+
+ @Nullable
+ @JsonProperty("seed")
+ private final Long seed;
+
+ @Nullable
+ @JsonProperty("prefill")
+ private final List prefill;
+
+ @Nullable
+ @JsonProperty("tokens")
+ private final List tokens;
+
+ @JsonCreator
+ public TextGenerationDetails(
+ @JsonProperty("finish_reason") @Nullable String finishReason,
+ @JsonProperty("generated_tokens") int generatedTokens,
+ @JsonProperty("seed") @Nullable Long seed,
+ @JsonProperty("prefill") @Nullable List prefill,
+ @JsonProperty("tokens") @Nullable List tokens) {
+ this.finishReason = finishReason;
+ this.generatedTokens = generatedTokens;
+ this.seed = seed;
+ if (prefill != null) {
+ this.prefill = new ArrayList<>(prefill);
+ } else {
+ this.prefill = null;
+ }
+ if (tokens != null) {
+ this.tokens = new ArrayList<>(tokens);
+ } else {
+ this.tokens = null;
+ }
+ }
+
+ @Nullable
+ public String getFinishReason() {
+ return finishReason;
+ }
+
+ public int getGeneratedTokens() {
+ return generatedTokens;
+ }
+
+ @Nullable
+ public Long getSeed() {
+ return seed;
+ }
+
+ @Nullable
+ public List getPrefill() {
+ return Collections.unmodifiableList(prefill);
+ }
+
+ @Nullable
+ public List getTokens() {
+ return Collections.unmodifiableList(tokens);
+ }
+ }
+
+ public static class TextGenerationPrefillToken {
+
+ @JsonProperty("id")
+ private final int id;
+
+ @Nullable
+ @JsonProperty("text")
+ private final String text;
+
+ @JsonProperty("logprob")
+ private final double logProb;
+
+ @JsonCreator
+ public TextGenerationPrefillToken(
+ @JsonProperty("id") int id,
+ @JsonProperty("text") @Nullable String text,
+ @JsonProperty("logprob") double logProb) {
+ this.id = id;
+ this.text = text;
+ this.logProb = logProb;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ @Nullable
+ public String getText() {
+ return text;
+ }
+
+ public double getLogProb() {
+ return logProb;
+ }
+ }
+
+ public static class TextGenerationToken extends TextGenerationPrefillToken {
+
+ @JsonProperty("special")
+ private final boolean special;
+
+ @JsonCreator
+ public TextGenerationToken(
+ @JsonProperty("special") boolean special,
+ @JsonProperty("id") int id,
+ @JsonProperty("text") @Nullable String text,
+ @JsonProperty("logprob") double logProb) {
+ super(id, text, logProb);
+ this.special = special;
+ }
+
+ public boolean isSpecial() {
+ return special;
+ }
+ }
+}
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/TextGenerationRequest.java b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/TextGenerationRequest.java
new file mode 100644
index 00000000..fd0b6077
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/TextGenerationRequest.java
@@ -0,0 +1,260 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.huggingface.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.microsoft.semantickernel.aiservices.huggingface.services.HuggingFacePromptExecutionSettings;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import javax.annotation.Nullable;
+import java.util.Arrays;
+import java.util.List;
+
+@JsonInclude(Include.NON_NULL)
+public class TextGenerationRequest {
+
+ ///
+ /// The input string to generate text for.
+ ///
+ @Nullable
+ @JsonProperty("inputs")
+ private final List inputs;
+
+ ///
+ /// Enable streaming
+ ///
+ @JsonProperty("stream")
+ private final boolean stream;
+
+ ///
+ /// Parameters used by the model for generation.
+ ///
+
+ @Nullable
+ @JsonProperty("parameters")
+ private final HuggingFaceTextParameters parameters;
+
+ ///
+ /// Options used by the model for generation.
+ ///
+ @Nullable
+ @JsonProperty("options")
+ private final HuggingFaceTextOptions options;
+
+ public TextGenerationRequest(
+ @Nullable String inputs,
+ boolean stream,
+ @Nullable HuggingFaceTextParameters parameters,
+ @Nullable HuggingFaceTextOptions options) {
+ this.inputs = Arrays.asList(inputs);
+ this.stream = stream;
+ this.parameters = parameters;
+ this.options = options;
+ }
+
+ public static TextGenerationRequest fromPromptAndExecutionSettings(String prompt,
+ HuggingFacePromptExecutionSettings executionSettings) {
+ return new TextGenerationRequest(
+ prompt,
+ false,
+ new HuggingFaceTextParameters(
+ executionSettings.getTopK(),
+ executionSettings.getTopP(),
+ executionSettings.getTemperature(),
+ executionSettings.getRepetitionPenalty(),
+ executionSettings.getMaxTokens(),
+ executionSettings.getMaxTime(),
+ true,
+ null,
+ null,
+ executionSettings.getDetails()),
+ new HuggingFaceTextOptions());
+ }
+
+ public static class HuggingFaceTextParameters {
+
+ ///
+ /// (Default: None). Number to define the top tokens considered within the sample operation to create new text.
+ ///
+ @Nullable
+ @JsonProperty("top_k")
+ private final Integer topK;
+
+ ///
+ /// (Default: None). Define the tokens that are within the sample operation of text generation.
+ /// Add tokens in the sample for more probable to least probable until the sum of the probabilities
+ /// is greater than top_p.
+ ///
+ @Nullable
+ @JsonProperty("top_p")
+ private final Double topP;
+
+ ///
+ /// (Default: 1.0). Range (0.0-100.0). The temperature of the sampling operation.
+ /// 1 means regular sampling, 0 means always take the highest score,
+ /// 100.0 is getting closer to uniform probability.
+ ///
+ @Nullable
+ @JsonProperty("temperature")
+ private final Double temperature;
+
+ ///
+ /// (Default: None). (0.0-100.0). The more a token is used within generation
+ /// the more it is penalized to not be picked in successive generation passes.
+ ///
+ @Nullable
+ @JsonProperty("repetition_penalty")
+ private final Double repetitionPenalty;
+
+ ///
+ /// (Default: None). Range (0-250). The amount of new tokens to be generated,
+ /// this does not include the input length it is a estimate of the size of generated text you want.
+ /// Each new tokens slows down the request, so look for balance between response times
+ /// and length of text generated.
+ ///
+ @Nullable
+ @JsonProperty("max_new_tokens")
+ private final Integer maxNewTokens;
+
+ ///
+ /// (Default: None). Range (0-120.0). The amount of time in seconds that the query should take maximum.
+ /// Network can cause some overhead so it will be a soft limit.
+ /// Use that in combination with max_new_tokens for best results.
+ ///
+ @Nullable
+ @JsonProperty("max_time")
+ private final Double maxTime;
+
+ ///
+ /// (Default: True). If set to False, the return results will not contain the original query making it easier for prompting.
+ ///
+ @JsonProperty("return_full_text")
+ private final boolean returnFullText;
+
+ ///
+ /// (Default: 1). The number of proposition you want to be returned.
+ ///
+ @Nullable
+ @JsonProperty("num_return_sequences")
+ private final Integer numReturnSequences;
+
+ ///
+ /// (Optional: True). Whether or not to use sampling, use greedy decoding otherwise.
+ ///
+ @Nullable
+ @JsonProperty("do_sample")
+ private final Boolean doSample;
+
+ ///
+ /// (Optional: True) Whether or not to include the details of the generation.
+ ///
+ ///
+ /// Disabling this won't provide information about token usage.
+ ///
+ @Nullable
+ @JsonProperty("details")
+ private final Boolean details;
+
+ public HuggingFaceTextParameters(
+ @JsonProperty("top_k") @Nullable Integer topK,
+ @JsonProperty("top_p") @Nullable Double topP,
+ @JsonProperty("temperature") @Nullable Double temperature,
+ @JsonProperty("repetition_penalty") @Nullable Double repetitionPenalty,
+ @JsonProperty("max_new_tokens") @Nullable Integer maxNewTokens,
+ @JsonProperty("max_time") @Nullable Double maxTime,
+ @JsonProperty("return_full_text") boolean returnFullText,
+ @JsonProperty("num_return_sequences") @Nullable Integer numReturnSequences,
+ @JsonProperty("do_sample") @Nullable Boolean doSample,
+ @JsonProperty("details") @Nullable Boolean details) {
+ this.topK = topK;
+ this.topP = topP;
+ this.temperature = temperature;
+ this.repetitionPenalty = repetitionPenalty;
+ this.maxNewTokens = maxNewTokens;
+ this.maxTime = maxTime;
+ this.returnFullText = returnFullText;
+ this.numReturnSequences = numReturnSequences;
+ this.doSample = doSample;
+ this.details = details;
+ }
+
+ @Nullable
+ public Integer getTopK() {
+ return topK;
+ }
+
+ @Nullable
+ public Double getTopP() {
+ return topP;
+ }
+
+ @Nullable
+ public Double getTemperature() {
+ return temperature;
+ }
+
+ @Nullable
+ public Double getRepetitionPenalty() {
+ return repetitionPenalty;
+ }
+
+ @Nullable
+ public Integer getMaxNewTokens() {
+ return maxNewTokens;
+ }
+
+ @Nullable
+ public Double getMaxTime() {
+ return maxTime;
+ }
+
+ public boolean isReturnFullText() {
+ return returnFullText;
+ }
+
+ @Nullable
+ public Integer getNumReturnSequences() {
+ return numReturnSequences;
+ }
+
+ @Nullable
+ public Boolean getDoSample() {
+ return doSample;
+ }
+
+ @Nullable
+ public Boolean getDetails() {
+ return details;
+ }
+ }
+
+ @SuppressFBWarnings("SS_SHOULD_BE_STATIC")
+ public static class HuggingFaceTextOptions {
+
+ ///
+ /// (Default: true). There is a cache layer on the inference API to speedup requests we have already seen.
+ /// Most models can use those results as is as models are deterministic (meaning the results will be the same anyway).
+ /// However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being
+ /// used resulting in a real new query.
+ ///
+ @JsonProperty("use_cache")
+ private final boolean useCache = true;
+
+ ///
+ /// (Default: false) If the model is not ready, wait for it instead of receiving 503.
+ /// It limits the number of requests required to get your inference done.
+ /// It is advised to only set this flag to true after receiving a 503 error as it will limit hanging in your application to known places.
+ ///
+ @JsonProperty("wait_for_model")
+ private final boolean waitForModel = false;
+
+ public boolean isUseCache() {
+ return useCache;
+ }
+
+ public boolean isWaitForModel() {
+ return waitForModel;
+ }
+ }
+}
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/ChatCompletionRequest.java.ignore b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/ChatCompletionRequest.java.ignore
new file mode 100644
index 00000000..99972819
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/ChatCompletionRequest.java.ignore
@@ -0,0 +1,201 @@
+package com.microsoft.semantickernel.aiservices.huggingface.models;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import javax.annotation.Nullable;
+
+// TODO Support TGI
+public class ChatCompletionRequest {
+
+
+ ///
+ /// This is the default name when using TGI and will be ignored as the TGI will only target the current activated model.
+ ///
+ public static final String TextGenerationInferenceDefaultModel = "tgi";
+
+
+ ///
+ /// Model name to use for generation.
+ ///
+ ///
+ /// When using TGI this parameter will be ignored.
+ ///
+ @Nullable
+ public final String model;
+
+ ///
+ /// Indicates whether to get the response as stream or not.
+ ///
+ public final boolean stream;
+
+ @Nullable
+ public final List messages;
+
+ ///
+ /// Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each
+ /// output token returned in the content of message.
+ ///
+ @Nullable
+ public final Boolean logprobs;
+
+ ///
+ /// An integer between 0 and 5 specifying the number of most likely tokens to return at each token position, each with
+ /// an associated log probability. logprobs must be set to true if this parameter is used.
+ ///
+ @Nullable
+ public final Integer topLogProbs;
+
+ ///
+ /// The maximum number of tokens that can be generated in the chat completion.
+ ///
+ @Nullable
+ public final Integer maxTokens;
+
+ ///
+ /// 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
+ ///
+
+ @Nullable
+ public final Float presencePenalty;
+ ///
+ /// Up to 4 sequences where the API will stop generating further tokens.
+ ///
+ @Nullable
+ public final List stop;
+
+ ///
+ /// The seed to use for generating a similar output.
+ ///
+ @Nullable
+ public final Long seed;
+
+ ///
+ /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while
+ /// lower values like 0.2 will make it more focused and deterministic.
+ ///
+ /// We generally recommend altering this or `top_p` but not both.
+ ///
+ @Nullable
+ public final Float temperature;
+
+ ///
+ /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the
+ /// tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.
+ ///
+ @Nullable
+ public final Float topP;
+
+ public ChatCompletionRequest(
+ @JsonProperty("model") String model,
+ @JsonProperty("stream") boolean stream,
+ @JsonProperty("messages") List messages,
+ @JsonProperty("logprobs") Boolean logprobs,
+
+ @Nullable
+ @JsonProperty("top_logprobs") Integer topLogProbs,
+
+ @Nullable
+ @JsonProperty("max_tokens") Integer maxTokens,
+
+ @Nullable
+ @JsonProperty("presence_penalty") Float presencePenalty,
+ @Nullable
+ @JsonProperty("stop") List stop,
+
+ @Nullable
+ @JsonProperty("seed") Long seed,
+ @Nullable
+ @JsonProperty("temperature") Float temperature,
+ @Nullable
+ @JsonProperty("top_p")
+ Float topP
+ ) {
+
+ this.model = model;
+ this.stream = stream;
+ this.messages = messages;
+ this.logprobs = logprobs;
+ this.topLogProbs = topLogProbs;
+ this.maxTokens = maxTokens;
+ this.presencePenalty = presencePenalty;
+ this.stop = stop;
+ this.seed = seed;
+ this.temperature = temperature;
+ this.topP = topP;
+ }
+
+ public static class ChatMessageToolCall {
+
+ @Nullable
+ private final String id;
+
+ @Nullable
+ private final String type;
+
+ private final ChatMessageFunction function;
+
+ public ChatMessageToolCall(
+ @Nullable
+ @JsonProperty("id") String id,
+ @Nullable
+ @JsonProperty("type") String type,
+ @Nullable
+ @JsonProperty("function") ChatMessageFunction function
+ ) {
+ this.id = id;
+ this.type = type;
+ this.function = function;
+ }
+ }
+
+ public static class ChatMessageFunction {
+
+ @Nullable
+ public final String description;
+ @Nullable
+ public final String name;
+ @Nullable
+ public final String parameters;
+
+ public ChatMessageFunction(
+ @JsonProperty("description") String description,
+ @JsonProperty("name") String name,
+ @JsonProperty("parameters") String parameters
+ ) {
+ this.description = description;
+ this.name = name;
+ this.parameters = parameters;
+ }
+ }
+
+ public static class ChatMessage {
+
+ @Nullable
+ public final String role;
+ @Nullable
+ public final String content;
+ @Nullable
+ public final String name;
+ @Nullable
+ public final List toolCalls;
+
+
+ public ChatMessage(
+ @Nullable
+ @JsonProperty("role") String role,
+ @Nullable
+ @JsonProperty("content") String content,
+ @Nullable
+ @JsonProperty("name") String name,
+ @Nullable
+ @JsonProperty("tool_calls") List toolCalls
+ ) {
+ this.role = role;
+ this.content = content;
+ this.name = name;
+ this.toolCalls = toolCalls;
+ }
+
+ }
+}
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/HuggingFaceChatCompletionService.java.ignore b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/HuggingFaceChatCompletionService.java.ignore
new file mode 100644
index 00000000..f6f05a9e
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/HuggingFaceChatCompletionService.java.ignore
@@ -0,0 +1,181 @@
+package com.microsoft.semantickernel.aiservices.huggingface.services;
+
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.huggingface.HuggingFaceClient;
+import com.microsoft.semantickernel.aiservices.huggingface.models.ChatCompletionRequest;
+import com.microsoft.semantickernel.aiservices.huggingface.models.HuggingFaceXMLPromptParser;
+import com.microsoft.semantickernel.aiservices.huggingface.models.HuggingFaceXMLPromptParser.HuggingFaceParsedPrompt;
+import com.microsoft.semantickernel.orchestration.InvocationContext;
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+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;
+
+// TODO Support TGI
+public class HuggingFaceChatCompletionService implements ChatCompletionService {
+
+ private final String modelId;
+ private final String serviceId;
+ private final HuggingFaceClient client;
+
+ public HuggingFaceChatCompletionService(
+ String modelId,
+ String serviceId,
+ HuggingFaceClient client) {
+ this.modelId = modelId;
+ this.serviceId = serviceId;
+ this.client = client;
+ }
+
+ public Mono>> getChatMessageContentsAsync(
+ ChatHistory chatHistory,
+ @Nullable Kernel kernel,
+ @Nullable HuggingFacePromptExecutionSettings executionSettings) {
+
+ String model = modelId;
+ if (executionSettings.getModelId() != null && !executionSettings.getModelId().isEmpty()) {
+ model = executionSettings.getModelId();
+ }
+
+ ChatCompletionRequest request = new ChatCompletionRequest(
+ model,
+ false,
+ chatHistory
+ .getMessages()
+ .stream()
+ .map(
+ message -> {
+ return new ChatCompletionRequest.ChatMessage(
+ message.getAuthorRole().name(),
+ message.getContent(),
+ null,
+ null
+ );
+ }
+ )
+ .collect(Collectors.toList()),
+ executionSettings.getLogprobs(),
+ executionSettings.getTopLogProbs(),
+ executionSettings.getMaxTokens(),
+ new Float(executionSettings.getPresencePenalty()),
+ executionSettings.getStopSequences(),
+ executionSettings.getSeed(),
+ new Float(executionSettings.getTemperature()),
+ new Float(executionSettings.getTopP())
+ );
+
+ return client
+ .getChatMessageContentsAsync(modelId, request)
+ .map(result -> {
+ return Collections.singletonList(new ChatMessageContent<>(
+ AuthorRole.SYSTEM,
+ result)
+ );
+ });
+ }
+
+ @Override
+ public Mono>> getChatMessageContentsAsync(
+ ChatHistory chatHistory,
+ @Nullable Kernel kernel,
+ @Nullable InvocationContext invocationContext) {
+
+ HuggingFacePromptExecutionSettings executionSettings;
+ if (invocationContext != null && invocationContext.getPromptExecutionSettings() != null) {
+ executionSettings = HuggingFacePromptExecutionSettings.fromExecutionSettings(
+ invocationContext.getPromptExecutionSettings());
+ } else {
+ executionSettings = new HuggingFacePromptExecutionSettings(
+ PromptExecutionSettings.builder().build());
+ }
+
+ return getChatMessageContentsAsync(chatHistory, kernel, executionSettings);
+
+ }
+
+ @Override
+ public Mono>> getChatMessageContentsAsync(
+ String prompt,
+ @Nullable Kernel kernel,
+ @Nullable InvocationContext invocationContext) {
+ HuggingFaceParsedPrompt parsed = HuggingFaceXMLPromptParser.parse(prompt);
+
+ ChatHistory history = new ChatHistory();
+ parsed.getChatRequestMessages()
+ .forEach(message -> {
+ history.addMessage(AuthorRole.valueOf(message.role.toUpperCase(Locale.ROOT)),
+ message.content);
+ });
+
+ return getChatMessageContentsAsync(history, kernel, invocationContext);
+
+ }
+
+ @Nullable
+ @Override
+ public String getModelId() {
+ return modelId;
+ }
+
+ @Nullable
+ @Override
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ @Nullable
+ private String modelId;
+ @Nullable
+ private HuggingFaceClient client;
+ @Nullable
+ private String serviceId;
+
+ /**
+ * Sets the model ID for the service
+ *
+ * @param modelId The model ID
+ * @return The builder
+ */
+ public Builder withModelId(String modelId) {
+ this.modelId = modelId;
+ return this;
+ }
+
+ /**
+ * Sets the service ID for the service
+ *
+ * @param serviceId The service ID
+ * @return The builder
+ */
+ public Builder withServiceId(String serviceId) {
+ this.serviceId = serviceId;
+ return this;
+ }
+
+ public Builder withHuggingFaceClient(HuggingFaceClient client) {
+ this.client = client;
+ return this;
+ }
+
+ public ChatCompletionService build() {
+ return new HuggingFaceChatCompletionService(
+ this.modelId,
+ this.serviceId,
+ this.client);
+ }
+ }
+
+}
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/HuggingFaceXMLPromptParser.java.ignore b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/HuggingFaceXMLPromptParser.java.ignore
new file mode 100644
index 00000000..6e647485
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/models/chat/HuggingFaceXMLPromptParser.java.ignore
@@ -0,0 +1,138 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.huggingface.models;
+
+import com.azure.core.util.BinaryData;
+import com.microsoft.semantickernel.aiservices.huggingface.models.ChatCompletionRequest.ChatMessage;
+import com.microsoft.semantickernel.aiservices.huggingface.models.ChatCompletionRequest.ChatMessageFunction;
+import com.microsoft.semantickernel.aiservices.huggingface.models.ChatCompletionRequest.ChatMessageToolCall;
+import com.microsoft.semantickernel.services.chatcompletion.ChatPromptParseVisitor;
+import com.microsoft.semantickernel.services.chatcompletion.ChatXMLPromptParser;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// TODO Support TGI
+public class HuggingFaceXMLPromptParser {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(HuggingFaceXMLPromptParser.class);
+
+ public static class HuggingFaceParsedPrompt {
+
+ private final List chatRequestMessages;
+ private final List functions;
+
+ protected HuggingFaceParsedPrompt(
+ List parsedMessages,
+ @Nullable List parsedFunctions
+ ) {
+ this.chatRequestMessages = parsedMessages;
+ if (parsedFunctions == null) {
+ parsedFunctions = new ArrayList<>();
+ }
+ this.functions = parsedFunctions;
+ }
+
+ public List getChatRequestMessages() {
+ return chatRequestMessages;
+ }
+
+ public List getFunctions() {
+ return functions;
+ }
+ }
+
+ private static class HuggingFaceChatPromptParseVisitor implements
+ ChatPromptParseVisitor {
+
+ private HuggingFaceParsedPrompt parsedRaw;
+ private final List functionDefinitions = new ArrayList<>();
+ private final List messages = new ArrayList<>();
+
+ @Override
+ public ChatPromptParseVisitor addMessage(
+ String role,
+ String content) {
+ messages.add(new ChatMessage(
+ role,
+ content,
+ null,
+ null));
+ return this;
+ }
+
+ @Override
+ public ChatPromptParseVisitor addFunction(
+ String name,
+ @Nullable
+ String description,
+ @Nullable
+ BinaryData parameters) {
+
+ String paramString = null;
+ if (parameters != null) {
+ paramString = parameters.toString();
+ }
+
+ ChatMessageToolCall function = new ChatMessageToolCall(
+ name,
+ null,
+ new ChatMessageFunction(
+ description,
+ name,
+ paramString
+ )
+ );
+
+ functionDefinitions.add(function);
+
+ return this;
+ }
+
+ @Override
+ public boolean areMessagesEmpty() {
+ return messages.isEmpty();
+ }
+
+ @Override
+ public ChatPromptParseVisitor fromRawPrompt(
+ String rawPrompt) {
+
+ ChatMessage message = new ChatMessage(
+ "user",
+ rawPrompt,
+ null,
+ null
+ );
+
+ this.parsedRaw = new HuggingFaceParsedPrompt(Collections.singletonList(message),
+ null);
+
+ return this;
+ }
+
+ @Override
+ public HuggingFaceParsedPrompt get() {
+ if (parsedRaw != null) {
+ return parsedRaw;
+ }
+
+ return new HuggingFaceParsedPrompt(messages, functionDefinitions);
+ }
+
+ @Override
+ public ChatPromptParseVisitor reset() {
+ return new HuggingFaceChatPromptParseVisitor();
+ }
+ }
+
+ public static HuggingFaceParsedPrompt parse(String rawPrompt) {
+ ChatPromptParseVisitor visitor = ChatXMLPromptParser.parse(
+ rawPrompt,
+ new HuggingFaceChatPromptParseVisitor());
+
+ return visitor.get();
+ }
+}
\ No newline at end of file
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/services/HuggingFacePromptExecutionSettings.java b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/services/HuggingFacePromptExecutionSettings.java
new file mode 100644
index 00000000..ed3a4df5
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/services/HuggingFacePromptExecutionSettings.java
@@ -0,0 +1,194 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.huggingface.services;
+
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import javax.annotation.Nullable;
+
+public class HuggingFacePromptExecutionSettings extends PromptExecutionSettings {
+
+ @Nullable
+ private final Integer topK;
+ @Nullable
+ private final Double repetitionPenalty;
+ @Nullable
+ private final Double maxTime;
+ @Nullable
+ private final Boolean details;
+ @Nullable
+ private final Boolean logProbs;
+ @Nullable
+ private final Integer topLogProbs;
+ @Nullable
+ private final Long seed;
+
+ public HuggingFacePromptExecutionSettings(PromptExecutionSettings copy) {
+ super(
+ copy.getServiceId(),
+ copy.getModelId(),
+ copy.getTemperature(),
+ copy.getTopP(),
+ copy.getPresencePenalty(),
+ copy.getFrequencyPenalty(),
+ copy.getMaxTokens(),
+ copy.getResultsPerPrompt(),
+ copy.getBestOf(),
+ copy.getUser(),
+ copy.getStopSequences(),
+ copy.getTokenSelectionBiases(),
+ copy.getResponseFormat() == null ? null : copy.getResponseFormat().toString());
+ this.topK = null;
+ this.repetitionPenalty = null;
+ this.maxTime = null;
+ this.details = null;
+ this.logProbs = null;
+ this.topLogProbs = null;
+ this.seed = null;
+ }
+
+ /**
+ * Create a new instance of PromptExecutionSettings.
+ *
+ * @param serviceId The id of the AI service to use for prompt execution.
+ * @param modelId The id of the model to use for prompt execution.
+ * @param temperature The temperature setting for prompt execution.
+ * @param topP The topP setting for prompt execution.
+ * @param presencePenalty The presence penalty setting for prompt execution.
+ * @param frequencyPenalty The frequency penalty setting for prompt execution.
+ * @param maxTokens The maximum number of tokens to generate in the output.
+ * @param resultsPerPrompt The number of results to generate for each prompt.
+ * @param bestOf The best of setting for prompt execution.
+ * @param user The user to associate with the prompt execution.
+ * @param stopSequences The stop sequences to use for prompt execution.
+ * @param tokenSelectionBiases The token selection biases to use for prompt execution.
+ * @param responseFormat The response format to use for prompt execution
+ */
+ public HuggingFacePromptExecutionSettings(
+ String serviceId,
+ String modelId,
+ Double temperature,
+ Double topP,
+ Double presencePenalty,
+ Double frequencyPenalty,
+ Integer maxTokens,
+ Integer resultsPerPrompt,
+ Integer bestOf,
+ String user,
+ @Nullable List stopSequences,
+ @Nullable Map tokenSelectionBiases,
+ @Nullable String responseFormat,
+ @Nullable Integer topK,
+ @Nullable Double repetitionPenalty,
+ @Nullable Double maxTime,
+ @Nullable Boolean details,
+ @Nullable Boolean logProbs,
+ @Nullable Integer topLogProbs,
+ @Nullable Long seed) {
+ super(
+ serviceId, modelId, temperature, topP, presencePenalty, frequencyPenalty, maxTokens,
+ resultsPerPrompt, bestOf, user, stopSequences, tokenSelectionBiases, responseFormat);
+
+ this.topK = topK;
+ this.repetitionPenalty = repetitionPenalty;
+ this.maxTime = maxTime;
+ this.details = details;
+ this.logProbs = logProbs;
+ this.topLogProbs = topLogProbs;
+ this.seed = seed;
+ }
+
+ public static HuggingFacePromptExecutionSettings fromExecutionSettings(
+ PromptExecutionSettings promptExecutionSettings) {
+ if (promptExecutionSettings instanceof HuggingFacePromptExecutionSettings) {
+ return (HuggingFacePromptExecutionSettings) promptExecutionSettings;
+ }
+
+ return new HuggingFacePromptExecutionSettings(
+ promptExecutionSettings.getServiceId(),
+ promptExecutionSettings.getModelId(),
+ promptExecutionSettings.getTemperature(),
+ promptExecutionSettings.getTopP(),
+ promptExecutionSettings.getPresencePenalty(),
+ promptExecutionSettings.getFrequencyPenalty(),
+ promptExecutionSettings.getMaxTokens(),
+ promptExecutionSettings.getResultsPerPrompt(),
+ promptExecutionSettings.getBestOf(),
+ promptExecutionSettings.getUser(),
+ promptExecutionSettings.getStopSequences(),
+ promptExecutionSettings.getTokenSelectionBiases(),
+ promptExecutionSettings.getResponseFormat() != null
+ ? promptExecutionSettings.getResponseFormat().toString()
+ : null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null);
+ }
+
+ @Nullable
+ public Integer getTopK() {
+ return topK;
+ }
+
+ @Nullable
+ public Double getRepetitionPenalty() {
+ return repetitionPenalty;
+ }
+
+ @Nullable
+ public Double getMaxTime() {
+ return maxTime;
+ }
+
+ @Nullable
+ public Boolean getDetails() {
+ return details;
+ }
+
+ @Nullable
+ public Boolean getLogprobs() {
+ return logProbs;
+ }
+
+ @Nullable
+ public Integer getTopLogProbs() {
+ return topLogProbs;
+ }
+
+ @Nullable
+ public Long getSeed() {
+ return seed;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || !(o instanceof HuggingFacePromptExecutionSettings)) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ HuggingFacePromptExecutionSettings that = (HuggingFacePromptExecutionSettings) o;
+ return Objects.equals(topK, that.topK) &&
+ Objects.equals(repetitionPenalty, that.repetitionPenalty) &&
+ Objects.equals(maxTime, that.maxTime) &&
+ Objects.equals(details, that.details) &&
+ Objects.equals(logProbs, that.logProbs) &&
+ Objects.equals(topLogProbs, that.topLogProbs) &&
+ Objects.equals(seed, that.seed);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), topK, repetitionPenalty, maxTime, details, logProbs,
+ topLogProbs, seed);
+ }
+}
diff --git a/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/services/HuggingFaceTextGenerationService.java b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/services/HuggingFaceTextGenerationService.java
new file mode 100644
index 00000000..96e05ff9
--- /dev/null
+++ b/aiservices/huggingface/src/main/java/com/microsoft/semantickernel/aiservices/huggingface/services/HuggingFaceTextGenerationService.java
@@ -0,0 +1,183 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.huggingface.services;
+
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.huggingface.HuggingFaceClient;
+import com.microsoft.semantickernel.aiservices.huggingface.models.TextGenerationRequest;
+import com.microsoft.semantickernel.aiservices.huggingface.models.TextGenerationRequest.HuggingFaceTextOptions;
+import com.microsoft.semantickernel.aiservices.huggingface.models.TextGenerationRequest.HuggingFaceTextParameters;
+import com.microsoft.semantickernel.exceptions.SKException;
+import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import com.microsoft.semantickernel.services.textcompletion.StreamingTextContent;
+import com.microsoft.semantickernel.services.textcompletion.TextContent;
+import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class HuggingFaceTextGenerationService implements TextGenerationService {
+
+ private final String modelId;
+ private final String serviceId;
+ private final HuggingFaceClient client;
+
+ public HuggingFaceTextGenerationService(
+ String modelId,
+ String serviceId,
+ HuggingFaceClient client) {
+ this.modelId = modelId;
+ this.serviceId = serviceId;
+ this.client = client;
+ }
+
+ public Mono> getTextContentsAsync(
+ String prompt,
+ @Nullable HuggingFacePromptExecutionSettings huggingFacePromptExecutionSettings,
+ @Nullable Kernel kernel) {
+
+ HuggingFaceTextParameters textParameters = getHuggingFaceTextParameters(
+ huggingFacePromptExecutionSettings);
+
+ TextGenerationRequest textGenerationRequest = new TextGenerationRequest(
+ prompt,
+ false,
+ textParameters,
+ new HuggingFaceTextOptions());
+
+ return client
+ .getTextContentsAsync(modelId, textGenerationRequest)
+ .map(result -> result
+ .stream()
+ .map(item -> new TextContent(
+ item.getGeneratedText() != null ? item.getGeneratedText() : "",
+ modelId,
+ FunctionResultMetadata.build(UUID.randomUUID().toString())))
+ .collect(Collectors.toList()));
+ }
+
+ @Override
+ public Mono> getTextContentsAsync(
+ String prompt,
+ @Nullable PromptExecutionSettings executionSettings,
+ @Nullable Kernel kernel) {
+
+ HuggingFacePromptExecutionSettings huggingFacePromptExecutionSettings = null;
+
+ if (executionSettings != null) {
+ huggingFacePromptExecutionSettings = HuggingFacePromptExecutionSettings
+ .fromExecutionSettings(
+ executionSettings);
+ }
+
+ return getTextContentsAsync(
+ prompt,
+ huggingFacePromptExecutionSettings,
+ kernel);
+
+ }
+
+ @Override
+ public Flux getStreamingTextContentsAsync(String prompt,
+ @Nullable PromptExecutionSettings executionSettings, @Nullable Kernel kernel) {
+ throw new SKException("Streaming text content is not supported");
+ }
+
+ private static @Nullable HuggingFaceTextParameters getHuggingFaceTextParameters(
+ @Nullable HuggingFacePromptExecutionSettings executionSettings) {
+ HuggingFaceTextParameters textParameters = null;
+ if (executionSettings != null) {
+ textParameters = new HuggingFaceTextParameters(
+ executionSettings.getTopK(),
+ executionSettings.getTopP(),
+ executionSettings.getTemperature(),
+ executionSettings.getRepetitionPenalty(),
+ executionSettings.getMaxTokens(),
+ executionSettings.getMaxTime(),
+ true,
+ executionSettings.getResultsPerPrompt(),
+ null,
+ executionSettings.getDetails());
+ }
+ return textParameters;
+ }
+
+ @Nullable
+ @Override
+ public String getModelId() {
+ return modelId;
+ }
+
+ @Nullable
+ @Override
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ @Nullable
+ protected String modelId;
+ @Nullable
+ protected HuggingFaceClient client;
+ @Nullable
+ protected String serviceId;
+
+ /**
+ * Sets the model ID for the service
+ *
+ * @param modelId The model ID
+ * @return The builder
+ */
+ public Builder withModelId(String modelId) {
+ this.modelId = modelId;
+ return this;
+ }
+
+ /**
+ * Sets the service ID for the service
+ *
+ * @param serviceId The service ID
+ * @return The builder
+ */
+ public Builder withServiceId(String serviceId) {
+ this.serviceId = serviceId;
+ return this;
+ }
+
+ public Builder withHuggingFaceClient(HuggingFaceClient client) {
+ this.client = client;
+ return this;
+ }
+
+ public HuggingFaceTextGenerationService build() {
+
+ if (this.modelId == null) {
+ throw new SKException(
+ "Model ID is required to build HuggingFaceTextGenerationService");
+ }
+
+ if (this.serviceId == null) {
+ throw new SKException(
+ "Service ID is required to build HuggingFaceTextGenerationService");
+ }
+
+ if (this.client == null) {
+ throw new SKException(
+ "HuggingFaceClient is required to build HuggingFaceTextGenerationService");
+ }
+
+ return new HuggingFaceTextGenerationService(
+ this.modelId,
+ this.serviceId,
+ this.client);
+ }
+ }
+}
diff --git a/java/aiservices/openai/pom.xml b/aiservices/openai/pom.xml
similarity index 76%
rename from java/aiservices/openai/pom.xml
rename to aiservices/openai/pom.xml
index 1ffd9f24..a7b12c09 100644
--- a/java/aiservices/openai/pom.xml
+++ b/aiservices/openai/pom.xml
@@ -6,7 +6,7 @@
com.microsoft.semantic-kernelsemantickernel-parent
- 1.1.5
+ 1.2.0../../pom.xml
@@ -40,6 +40,21 @@
stax-apiprovided
+
+ io.opentelemetry
+ opentelemetry-sdk
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/OpenAiService.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/OpenAiService.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/OpenAiService.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/OpenAiService.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiAudioToTextService.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiAudioToTextService.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiAudioToTextService.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiAudioToTextService.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiTextToAudioService.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiTextToAudioService.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiTextToAudioService.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/audio/OpenAiTextToAudioService.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java
similarity index 89%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java
index e30351a7..6bdb4f1c 100644
--- a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java
+++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatCompletion.java
@@ -11,12 +11,17 @@
import com.azure.ai.openai.models.ChatCompletionsTextResponseFormat;
import com.azure.ai.openai.models.ChatCompletionsToolCall;
import com.azure.ai.openai.models.ChatCompletionsToolDefinition;
+import com.azure.ai.openai.models.ChatMessageImageContentItem;
+import com.azure.ai.openai.models.ChatMessageImageDetailLevel;
+import com.azure.ai.openai.models.ChatMessageImageUrl;
import com.azure.ai.openai.models.ChatRequestAssistantMessage;
+import com.azure.ai.openai.models.ChatRequestFunctionMessage;
import com.azure.ai.openai.models.ChatRequestMessage;
import com.azure.ai.openai.models.ChatRequestSystemMessage;
import com.azure.ai.openai.models.ChatRequestToolMessage;
import com.azure.ai.openai.models.ChatRequestUserMessage;
import com.azure.ai.openai.models.ChatResponseMessage;
+import com.azure.ai.openai.models.CompletionsUsage;
import com.azure.ai.openai.models.FunctionCall;
import com.azure.core.util.BinaryData;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -38,6 +43,7 @@
import com.microsoft.semantickernel.hooks.PreChatCompletionEvent;
import com.microsoft.semantickernel.hooks.PreToolCallEvent;
import com.microsoft.semantickernel.implementation.CollectionUtil;
+import com.microsoft.semantickernel.implementation.telemetry.SemanticKernelTelemetry;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.orchestration.FunctionResultMetadata;
import com.microsoft.semantickernel.orchestration.InvocationContext;
@@ -50,6 +56,10 @@
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageContentType;
+import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageImageContent;
+import com.microsoft.semantickernel.services.openai.OpenAiServiceBuilder;
+import io.opentelemetry.api.trace.Span;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -124,7 +134,7 @@ public Mono>> getChatMessageContentsAsync(
.returnMode() == InvocationReturnMode.LAST_MESSAGE_ONLY) {
chatHistoryResult = new ChatHistory(
Collections.singletonList(
- CollectionUtil.getLastOrNull(chatHistory.getMessages())));
+ CollectionUtil.getLastOrNull(chatHistoryResult.getMessages())));
}
return Mono.just(chatHistoryResult.getMessages());
@@ -139,7 +149,7 @@ public Mono>> getChatMessageContentsAsync(
String prompt,
@Nullable Kernel kernel,
@Nullable InvocationContext invocationContext) {
- ParsedPrompt parsedPrompt = XMLPromptParser.parse(prompt);
+ ParsedPrompt parsedPrompt = OpenAiXMLPromptParser.parse(prompt);
ChatMessages messages = new ChatMessages(parsedPrompt.getChatRequestMessages());
@@ -218,6 +228,54 @@ public ChatMessages addChatMessage(List chatMessageCon
newMessages,
tmpChatMessageContent);
}
+
+ /**
+ * Checks that the two messages have a similar history
+ *
+ * @param messages The messages to merge in
+ * @return The merged chat messages
+ */
+ boolean assertCommonHistory(List messages) {
+ int index = 0;
+ while (index < messages.size() && index < this.allMessages.size()) {
+ ChatRequestMessage a = messages.get(index);
+ ChatRequestMessage b = this.allMessages.get(index);
+
+ boolean matches = false;
+ if (a instanceof ChatRequestAssistantMessage
+ && b instanceof ChatRequestAssistantMessage) {
+ matches = Objects.equals(((ChatRequestAssistantMessage) a).getContent(),
+ ((ChatRequestAssistantMessage) b).getContent());
+ } else if (a instanceof ChatRequestSystemMessage
+ && b instanceof ChatRequestSystemMessage) {
+ matches = Objects.equals(((ChatRequestSystemMessage) a).getContent(),
+ ((ChatRequestSystemMessage) b).getContent());
+ } else if (a instanceof ChatRequestUserMessage
+ && b instanceof ChatRequestUserMessage) {
+ matches = Objects.equals(((ChatRequestUserMessage) a).getContent(),
+ ((ChatRequestUserMessage) b).getContent());
+ } else if (a instanceof ChatRequestFunctionMessage
+ && b instanceof ChatRequestFunctionMessage) {
+ matches = Objects.equals(((ChatRequestFunctionMessage) a).getContent(),
+ ((ChatRequestFunctionMessage) b).getContent());
+ } else if (a instanceof ChatRequestToolMessage
+ && b instanceof ChatRequestToolMessage) {
+ matches = Objects.equals(((ChatRequestToolMessage) a).getContent(),
+ ((ChatRequestToolMessage) b).getContent());
+ }
+
+ if (!matches) {
+ LOGGER.warn("Messages do not match at index: " + index
+ + " you might be merging unrelated message histories");
+ return false;
+ }
+
+ index++;
+ }
+
+ return true;
+
+ }
}
private Mono internalChatMessageContentsAsync(
@@ -261,17 +319,28 @@ private Mono internalChatMessageContentsAsync(
invocationContext)))
.getOptions();
+ Span span = SemanticKernelTelemetry.startChatCompletionSpan(
+ getModelId(),
+ SemanticKernelTelemetry.OPEN_AI_PROVIDER,
+ options.getMaxTokens(),
+ options.getTemperature(),
+ options.getTopP());
return getClient()
.getChatCompletionsWithResponse(getDeploymentName(), options,
OpenAIRequestSettings.getRequestOptions())
.flatMap(completionsResult -> {
if (completionsResult.getStatusCode() >= 400) {
+ SemanticKernelTelemetry.endSpanWithError(span);
return Mono.error(new AIException(ErrorCodes.SERVICE_ERROR,
"Request failed: " + completionsResult.getStatusCode()));
}
+ SemanticKernelTelemetry.endSpanWithUsage(span,
+ completionsResult.getValue().getUsage());
+
return Mono.just(completionsResult.getValue());
})
.flatMap(completions -> {
+
List responseMessages = completions
.getChoices()
.stream()
@@ -334,7 +403,10 @@ private Mono internalChatMessageContentsAsync(
if (autoInvokeAttempts > 0) {
ChatMessages currentMessages = messages;
if (e instanceof FunctionInvocationError) {
- currentMessages = currentMessages.addAll(
+ currentMessages.assertCommonHistory(
+ ((FunctionInvocationError) e).getMessages());
+
+ currentMessages = new ChatMessages(
((FunctionInvocationError) e).getMessages());
}
return internalChatMessageContentsAsync(
@@ -510,7 +582,7 @@ private OpenAIFunctionToolCall extractOpenAIFunctionToolCall(
private Mono> getChatMessageContentsAsync(
ChatCompletions completions) {
- FunctionResultMetadata completionMetadata = FunctionResultMetadata.build(
+ FunctionResultMetadata completionMetadata = FunctionResultMetadata.build(
completions.getId(),
completions.getUsage(),
completions.getCreatedAt());
@@ -621,11 +693,8 @@ private List getToolCalls(
throw SKException.build("Failed to parse tool arguments", e);
}
} else {
- return new OpenAIFunctionToolCall(
- call.getId(),
- null,
- null,
- null);
+ throw new SKException(
+ "Unknown tool call type: " + call.getClass().getSimpleName());
}
})
.collect(Collectors.toList());
@@ -671,7 +740,7 @@ private static ChatCompletionsOptions getCompletionsOptions(
chatRequestMessages = chatRequestMessages
.stream()
- .map(XMLPromptParser::unescapeRequest)
+ .map(OpenAiXMLPromptParser::unescapeRequest)
.collect(Collectors.toList());
ChatCompletionsOptions options = new ChatCompletionsOptions(chatRequestMessages)
@@ -869,6 +938,10 @@ private static ChatRequestMessage getChatRequestMessage(
AuthorRole authorRole = message.getAuthorRole();
String content = message.getContent();
+ if (message.getContentType() == ChatMessageContentType.IMAGE_URL && content != null) {
+ return formImageMessage(message, content);
+ }
+
switch (authorRole) {
case ASSISTANT:
return formAssistantMessage(message, content);
@@ -892,7 +965,19 @@ private static ChatRequestMessage getChatRequestMessage(
LOGGER.debug("Unexpected author role: {}", authorRole);
throw new SKException("Unexpected author role: " + authorRole);
}
+ }
+
+ private static ChatRequestUserMessage formImageMessage(ChatMessageContent> message,
+ String content) {
+ ChatMessageImageUrl imageUrl = new ChatMessageImageUrl(content);
+ if (message instanceof ChatMessageImageContent) {
+ ChatMessageImageDetailLevel detail = ChatMessageImageDetailLevel.fromString(
+ ((ChatMessageImageContent>) message).getDetail().toString());
+ imageUrl.setDetail(detail);
+ }
+ return new ChatRequestUserMessage(
+ Collections.singletonList(new ChatMessageImageContentItem(imageUrl)));
}
private static ChatRequestAssistantMessage formAssistantMessage(
@@ -959,7 +1044,7 @@ static ChatRequestMessage getChatRequestMessage(
/**
* Builder for creating a new instance of {@link OpenAIChatCompletion}.
*/
- public static class Builder extends ChatCompletionService.Builder {
+ public static class Builder extends OpenAiServiceBuilder {
@Override
public OpenAIChatCompletion build() {
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatMessageContent.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatMessageContent.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatMessageContent.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatMessageContent.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatResponse.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatResponse.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatResponse.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIChatResponse.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunction.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAIFunctionToolCall.java
diff --git a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiXMLPromptParser.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiXMLPromptParser.java
new file mode 100644
index 00000000..4088f72f
--- /dev/null
+++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiXMLPromptParser.java
@@ -0,0 +1,157 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.openai.chatcompletion;
+
+import com.azure.ai.openai.models.ChatRequestAssistantMessage;
+import com.azure.ai.openai.models.ChatRequestFunctionMessage;
+import com.azure.ai.openai.models.ChatRequestMessage;
+import com.azure.ai.openai.models.ChatRequestSystemMessage;
+import com.azure.ai.openai.models.ChatRequestToolMessage;
+import com.azure.ai.openai.models.ChatRequestUserMessage;
+import com.azure.ai.openai.models.FunctionDefinition;
+import com.azure.core.util.BinaryData;
+import com.microsoft.semantickernel.exceptions.SKException;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.implementation.chatcompletion.ChatPromptParseVisitor;
+import com.microsoft.semantickernel.implementation.chatcompletion.ChatXMLPromptParser;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.UUID;
+import javax.annotation.Nullable;
+import org.apache.commons.text.StringEscapeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class OpenAiXMLPromptParser {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(OpenAiXMLPromptParser.class);
+
+ private static class OpenAiChatPromptParseVisitor implements
+ ChatPromptParseVisitor {
+
+ @Nullable
+ private ParsedPrompt parsedRaw = null;
+ private final List functionDefinitions = new ArrayList<>();
+ private final List messages = new ArrayList<>();
+
+ @Override
+ public ChatPromptParseVisitor addMessage(String role,
+ String content) {
+ messages.add(getChatRequestMessage(role, content));
+ return this;
+ }
+
+ @Override
+ public ChatPromptParseVisitor addFunction(
+ String name,
+ @Nullable String description,
+ @Nullable BinaryData parameters) {
+ FunctionDefinition function = new FunctionDefinition(name);
+
+ if (description != null) {
+ function.setDescription(description);
+ }
+
+ if (parameters != null) {
+ function.setParameters(parameters);
+ }
+
+ functionDefinitions.add(function);
+
+ return this;
+ }
+
+ @Override
+ public boolean areMessagesEmpty() {
+ return messages.isEmpty();
+ }
+
+ @Override
+ public ChatPromptParseVisitor fromRawPrompt(String rawPrompt) {
+ ChatRequestUserMessage message = new ChatRequestUserMessage(rawPrompt);
+
+ if (message.getName() == null) {
+ message.setName(UUID.randomUUID().toString());
+ }
+
+ this.parsedRaw = new ParsedPrompt(Collections.singletonList(message), null);
+ return this;
+ }
+
+ @Override
+ public ParsedPrompt get() {
+ if (parsedRaw != null) {
+ return parsedRaw;
+ }
+
+ return new ParsedPrompt(messages, functionDefinitions);
+ }
+
+ @Override
+ public ChatPromptParseVisitor reset() {
+ return new OpenAiChatPromptParseVisitor();
+ }
+ }
+
+ public static ParsedPrompt parse(String rawPrompt) {
+ ChatPromptParseVisitor visitor = ChatXMLPromptParser.parse(rawPrompt,
+ new OpenAiChatPromptParseVisitor());
+
+ return visitor.get();
+
+ }
+
+ private static ChatRequestMessage getChatRequestMessage(
+ String role,
+ String content) {
+ try {
+ AuthorRole authorRole = AuthorRole.valueOf(role.toUpperCase(Locale.ROOT));
+ return OpenAIChatCompletion.getChatRequestMessage(authorRole, content);
+ } catch (IllegalArgumentException e) {
+ LOGGER.debug("Unknown author role: " + role);
+ throw new SKException("Unknown author role: " + role);
+ }
+ }
+
+ public static ChatRequestMessage unescapeRequest(ChatRequestMessage message) {
+ if (message instanceof ChatRequestUserMessage) {
+ ChatRequestUserMessage chatRequestMessage = (ChatRequestUserMessage) message;
+ String content = StringEscapeUtils.unescapeXml(
+ chatRequestMessage.getContent().toString());
+
+ return new ChatRequestUserMessage(content)
+ .setName(chatRequestMessage.getName());
+ } else if (message instanceof ChatRequestSystemMessage) {
+ ChatRequestSystemMessage chatRequestMessage = (ChatRequestSystemMessage) message;
+ String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
+
+ return new ChatRequestSystemMessage(content)
+ .setName(chatRequestMessage.getName());
+ } else if (message instanceof ChatRequestAssistantMessage) {
+ ChatRequestAssistantMessage chatRequestMessage = (ChatRequestAssistantMessage) message;
+ String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
+
+ return new ChatRequestAssistantMessage(content)
+ .setToolCalls(chatRequestMessage.getToolCalls())
+ .setFunctionCall(chatRequestMessage.getFunctionCall())
+ .setName(chatRequestMessage.getName());
+ } else if (message instanceof ChatRequestFunctionMessage) {
+ ChatRequestFunctionMessage chatRequestMessage = (ChatRequestFunctionMessage) message;
+ String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
+
+ return new ChatRequestFunctionMessage(
+ chatRequestMessage.getName(),
+ content);
+ } else if (message instanceof ChatRequestToolMessage) {
+ ChatRequestToolMessage chatRequestMessage = (ChatRequestToolMessage) message;
+ String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
+
+ return new ChatRequestToolMessage(
+ content,
+ chatRequestMessage.getToolCallId());
+ }
+
+ throw new SKException("Unknown message type: " + message.getClass().getSimpleName());
+ }
+}
\ No newline at end of file
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/ParsedPrompt.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/ParsedPrompt.java
similarity index 100%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/ParsedPrompt.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/ParsedPrompt.java
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/implementation/OpenAIRequestSettings.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/implementation/OpenAIRequestSettings.java
similarity index 77%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/implementation/OpenAIRequestSettings.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/implementation/OpenAIRequestSettings.java
index eefceaf1..8da85ed9 100644
--- a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/implementation/OpenAIRequestSettings.java
+++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/implementation/OpenAIRequestSettings.java
@@ -2,7 +2,9 @@
package com.microsoft.semantickernel.aiservices.openai.implementation;
import com.azure.core.http.HttpHeaderName;
+import com.azure.core.http.policy.UserAgentPolicy;
import com.azure.core.http.rest.RequestOptions;
+import com.azure.core.util.Context;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
@@ -18,15 +20,19 @@ public final class OpenAIRequestSettings {
private static final String SEMANTIC_KERNEL_VERSION_PROPERTY_NAME = "semantic-kernel.version";
private static final String SEMANTIC_KERNEL_VERSION_PROPERTIES_FILE = "semantic-kernel-version.properties";
- private static final String version;
+ private static final String useragent;
+
+ private static final String header;
static {
- version = loadVersion();
+ String version = loadVersion();
+ useragent = "semantic-kernel-java/" + version;
+ header = "java/" + version;
}
private static String loadVersion() {
- String version = "Java/unknown";
+ String version = "unknown";
try (InputStream settingsFile = OpenAIRequestSettings.class.getResourceAsStream(
SEMANTIC_KERNEL_VERSION_PROPERTIES_FILE)) {
@@ -36,7 +42,7 @@ private static String loadVersion() {
if (props.containsKey(SEMANTIC_KERNEL_VERSION_PROPERTY_NAME)) {
String skVersion = props.getProperty(SEMANTIC_KERNEL_VERSION_PROPERTY_NAME);
if (skVersion != null && !skVersion.isEmpty()) {
- return "Java/" + skVersion;
+ return skVersion;
}
}
} catch (IOException e) {
@@ -53,6 +59,8 @@ private static String loadVersion() {
*/
public static RequestOptions getRequestOptions() {
return new RequestOptions()
- .setHeader(HttpHeaderName.fromString("Semantic-Kernel-Version"), version);
+ .setHeader(HttpHeaderName.fromString("Semantic-Kernel-Version"), header)
+ .setContext(
+ new Context(UserAgentPolicy.APPEND_USER_AGENT_CONTEXT_KEY, useragent));
}
}
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textcompletion/OpenAITextGenerationService.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textcompletion/OpenAITextGenerationService.java
similarity index 90%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textcompletion/OpenAITextGenerationService.java
rename to aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textcompletion/OpenAITextGenerationService.java
index 15179d81..57e3dd1f 100644
--- a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textcompletion/OpenAITextGenerationService.java
+++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textcompletion/OpenAITextGenerationService.java
@@ -3,6 +3,7 @@
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.models.CompletionsOptions;
+import com.azure.ai.openai.models.CompletionsUsage;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.aiservices.openai.OpenAiService;
import com.microsoft.semantickernel.aiservices.openai.implementation.OpenAIRequestSettings;
@@ -13,6 +14,8 @@
import com.microsoft.semantickernel.services.textcompletion.StreamingTextContent;
import com.microsoft.semantickernel.services.textcompletion.TextContent;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
+import com.microsoft.semantickernel.implementation.telemetry.SemanticKernelTelemetry;
+import io.opentelemetry.api.trace.Span;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -80,18 +83,27 @@ protected Mono> internalCompleteTextAsync(
CompletionsOptions completionsOptions = getCompletionsOptions(text, requestSettings);
+ Span span = SemanticKernelTelemetry.startTextCompletionSpan(
+ getModelId(),
+ SemanticKernelTelemetry.OPEN_AI_PROVIDER,
+ completionsOptions.getMaxTokens(),
+ completionsOptions.getTemperature(),
+ completionsOptions.getTopP());
return getClient()
.getCompletionsWithResponse(getDeploymentName(), completionsOptions,
OpenAIRequestSettings.getRequestOptions())
.flatMap(completionsResult -> {
if (completionsResult.getStatusCode() >= 400) {
+ SemanticKernelTelemetry.endSpanWithError(span);
return Mono.error(new AIException(ErrorCodes.SERVICE_ERROR,
"Request failed: " + completionsResult.getStatusCode()));
}
+ SemanticKernelTelemetry.endSpanWithUsage(span,
+ completionsResult.getValue().getUsage());
return Mono.just(completionsResult.getValue());
})
.map(completions -> {
- FunctionResultMetadata metadata = FunctionResultMetadata.build(
+ FunctionResultMetadata metadata = FunctionResultMetadata.build(
completions.getId(),
completions.getUsage(),
completions.getCreatedAt());
diff --git a/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textembedding/OpenAITextEmbeddingGenerationService.java b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textembedding/OpenAITextEmbeddingGenerationService.java
new file mode 100644
index 00000000..a46540c0
--- /dev/null
+++ b/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/textembedding/OpenAITextEmbeddingGenerationService.java
@@ -0,0 +1,125 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.openai.textembedding;
+
+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.aiservices.openai.OpenAiService;
+import com.microsoft.semantickernel.exceptions.AIException;
+import com.microsoft.semantickernel.services.openai.OpenAiServiceBuilder;
+import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
+import com.microsoft.semantickernel.services.textembedding.Embedding;
+import com.microsoft.semantickernel.services.textembedding.TextEmbeddingGenerationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An OpenAI implementation of a {@link TextEmbeddingGenerationService}.
+ *
+ */
+public class OpenAITextEmbeddingGenerationService extends OpenAiService
+ implements TextEmbeddingGenerationService {
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(OpenAITextEmbeddingGenerationService.class);
+ private static final int DEFAULT_DIMENSIONS = 1536;
+ private final int dimensions;
+
+ /**
+ * Creates a new {@link OpenAITextEmbeddingGenerationService}.
+ *
+ * @param client OpenAI client
+ * @param deploymentName deployment name
+ * @param modelId OpenAI model id
+ * @param serviceId Service id
+ */
+ public OpenAITextEmbeddingGenerationService(
+ OpenAIAsyncClient client,
+ String deploymentName,
+ String modelId,
+ @Nullable String serviceId,
+ int dimensions) {
+ super(client, serviceId, modelId, deploymentName);
+ this.dimensions = dimensions;
+ }
+
+ /**
+ * Creates a builder for creating a {@link OpenAITextEmbeddingGenerationService}.
+ *
+ * @return A new {@link OpenAITextEmbeddingGenerationService} builder.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Generates embeddings for the given data.
+ *
+ * @param data The data to generate embeddings for.
+ * @return A Mono that completes with the embeddings.
+ */
+ @Override
+ public Mono> generateEmbeddingsAsync(List data) {
+ return this.internalGenerateTextEmbeddingsAsync(data);
+ }
+
+ protected Mono> internalGenerateTextEmbeddingsAsync(List data) {
+ EmbeddingsOptions options = new EmbeddingsOptions(data)
+ .setModel(getModelId())
+ .setDimensions(dimensions)
+ .setInputType("string");
+
+ return getClient()
+ .getEmbeddings(getModelId(), options)
+ .flatMapIterable(Embeddings::getData)
+ .mapNotNull(EmbeddingItem::getEmbedding)
+ .map(ArrayList::new)
+ .mapNotNull(Embedding::new)
+ .collectList();
+ }
+
+ /**
+ * A builder for creating a {@link OpenAITextEmbeddingGenerationService}.
+ */
+ public static class Builder extends
+ OpenAiServiceBuilder {
+ private int dimensions = DEFAULT_DIMENSIONS;
+
+ /**
+ * Sets the dimensions for the embeddings.
+ *
+ * @param dimensions The dimensions for the embeddings.
+ * @return The builder.
+ */
+ public Builder withDimensions(int dimensions) {
+ this.dimensions = dimensions;
+ return this;
+ }
+
+ @Override
+ public OpenAITextEmbeddingGenerationService build() {
+ if (this.client == null) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "OpenAI client must be provided");
+ }
+
+ if (this.modelId == null || modelId.isEmpty()) {
+ throw new AIException(AIException.ErrorCodes.INVALID_REQUEST,
+ "OpenAI model id must be provided");
+ }
+
+ if (deploymentName == null) {
+ LOGGER.debug("Deployment name is not provided, using model id as deployment name");
+ deploymentName = modelId;
+ }
+
+ return new OpenAITextEmbeddingGenerationService(client, deploymentName, modelId,
+ serviceId, dimensions);
+ }
+ }
+}
diff --git a/java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.AudioToTextService$Builder b/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.AudioToTextService$Builder
similarity index 100%
rename from java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.AudioToTextService$Builder
rename to aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.AudioToTextService$Builder
diff --git a/java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.TextToAudioService$Builder b/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.TextToAudioService$Builder
similarity index 100%
rename from java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.TextToAudioService$Builder
rename to aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.audio.TextToAudioService$Builder
diff --git a/java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService$Builder b/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService$Builder
similarity index 100%
rename from java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService$Builder
rename to aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService$Builder
diff --git a/java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.textcompletion.TextGenerationService$Builder b/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.textcompletion.TextGenerationService$Builder
similarity index 100%
rename from java/aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.textcompletion.TextGenerationService$Builder
rename to aiservices/openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.services.textcompletion.TextGenerationService$Builder
diff --git a/java/aiservices/openai/src/main/resources/com/microsoft/semantickernel/aiservices/openai/implementation/semantic-kernel-version.properties b/aiservices/openai/src/main/resources/com/microsoft/semantickernel/aiservices/openai/implementation/semantic-kernel-version.properties
similarity index 100%
rename from java/aiservices/openai/src/main/resources/com/microsoft/semantickernel/aiservices/openai/implementation/semantic-kernel-version.properties
rename to aiservices/openai/src/main/resources/com/microsoft/semantickernel/aiservices/openai/implementation/semantic-kernel-version.properties
diff --git a/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java
new file mode 100644
index 00000000..c8bde155
--- /dev/null
+++ b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/OtelCaptureTest.java
@@ -0,0 +1,177 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.aiservices.openai;
+
+import com.azure.ai.openai.OpenAIAsyncClient;
+import com.azure.ai.openai.models.ChatCompletions;
+import com.azure.ai.openai.models.ChatCompletionsOptions;
+import com.azure.ai.openai.models.Completions;
+import com.azure.ai.openai.models.CompletionsOptions;
+import com.azure.ai.openai.models.CompletionsUsage;
+import com.azure.core.http.rest.Response;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
+import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService;
+import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.trace.SdkTracerProvider;
+import io.opentelemetry.sdk.trace.data.SpanData;
+import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
+import io.opentelemetry.sdk.trace.export.SpanExporter;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import reactor.core.publisher.Mono;
+
+public class OtelCaptureTest {
+
+ private static OpenTelemetrySdk otel;
+ private static ArrayList spans = new ArrayList<>();
+
+ @BeforeEach
+ public void clearSpans() {
+ spans.clear();
+ }
+
+ @BeforeAll
+ public static void setup() {
+
+ SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
+ .addSpanProcessor(SimpleSpanProcessor.builder(new SpanExporter() {
+ @Override
+ public CompletableResultCode export(Collection collection) {
+ spans.addAll(collection);
+ return new CompletableResultCode();
+ }
+
+ @Override
+ public CompletableResultCode flush() {
+ return new CompletableResultCode();
+ }
+
+ @Override
+ public CompletableResultCode shutdown() {
+ return new CompletableResultCode();
+ }
+ })
+ .build())
+ .build();
+
+ GlobalOpenTelemetry.resetForTest();
+
+ otel = OpenTelemetrySdk.builder()
+ .setTracerProvider(tracerProvider)
+ .buildAndRegisterGlobal();
+ }
+
+ @AfterAll
+ public static void shutdown() {
+ otel.shutdown();
+ }
+
+ @Test
+ public void otelTextCaptureTest() {
+
+ OpenAIAsyncClient openAIAsyncClient = Mockito.mock(OpenAIAsyncClient.class);
+
+ CompletionsUsage completionsUsage = Mockito.mock(CompletionsUsage.class);
+ Mockito.when(completionsUsage.getCompletionTokens()).thenReturn(22);
+ Mockito.when(completionsUsage.getPromptTokens()).thenReturn(55);
+
+ Completions completions = Mockito.mock(Completions.class);
+ Mockito.when(completions.getUsage()).thenReturn(completionsUsage);
+
+ Response response = Mockito.mock(Response.class);
+ Mockito.when(response.getStatusCode()).thenReturn(200);
+ Mockito.when(response.getValue()).thenReturn(completions);
+
+ Mockito.when(openAIAsyncClient.getCompletionsWithResponse(
+ Mockito.any(),
+ Mockito.any(),
+ Mockito.any())).thenAnswer(invocation -> Mono.just(response));
+
+ TextGenerationService client = OpenAITextGenerationService.builder()
+ .withOpenAIAsyncClient(openAIAsyncClient)
+ .withModelId("a-model")
+ .build();
+
+ try {
+ client.getTextContentsAsync(
+ "foo",
+ null,
+ null).block();
+ } catch (Exception e) {
+ // Expect to fail
+ }
+
+ Assertions.assertFalse(spans.isEmpty());
+ Assertions.assertEquals("a-model",
+ spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.request.model")));
+ Assertions.assertEquals("text.completions",
+ spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.operation.name")));
+ Assertions.assertEquals("openai",
+ spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.system")));
+ Assertions.assertEquals(22,
+ spans.get(0).getAttributes()
+ .get(AttributeKey.longKey("gen_ai.response.completion_tokens")));
+ Assertions.assertEquals(55,
+ spans.get(0).getAttributes()
+ .get(AttributeKey.longKey("gen_ai.response.prompt_tokens")));
+
+ }
+
+ @Test
+ public void otelChatCaptureTest() {
+ OpenAIAsyncClient openAIAsyncClient = Mockito.mock(OpenAIAsyncClient.class);
+
+ CompletionsUsage completionsUsage = Mockito.mock(CompletionsUsage.class);
+ Mockito.when(completionsUsage.getCompletionTokens()).thenReturn(21);
+ Mockito.when(completionsUsage.getPromptTokens()).thenReturn(42);
+
+ ChatCompletions chatCompletions = Mockito.mock(ChatCompletions.class);
+ Mockito.when(chatCompletions.getUsage()).thenReturn(completionsUsage);
+
+ Response response = Mockito.mock(Response.class);
+ Mockito.when(response.getStatusCode()).thenReturn(200);
+ Mockito.when(response.getValue()).thenReturn(chatCompletions);
+
+ Mockito.when(openAIAsyncClient.getChatCompletionsWithResponse(
+ Mockito.any(),
+ Mockito.any(),
+ Mockito.any())).thenAnswer(invocation -> Mono.just(response));
+
+ OpenAIChatCompletion client = OpenAIChatCompletion.builder()
+ .withOpenAIAsyncClient(openAIAsyncClient)
+ .withModelId("a-model")
+ .build();
+
+ try {
+ client.getChatMessageContentsAsync(
+ "foo",
+ null,
+ null).block();
+ } catch (Exception e) {
+ // Expect to fail
+ }
+
+ Assertions.assertFalse(spans.isEmpty());
+ Assertions.assertEquals("a-model",
+ spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.request.model")));
+ Assertions.assertEquals("chat.completions",
+ spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.operation.name")));
+ Assertions.assertEquals("openai",
+ spans.get(0).getAttributes().get(AttributeKey.stringKey("gen_ai.system")));
+ Assertions.assertEquals(21,
+ spans.get(0).getAttributes()
+ .get(AttributeKey.longKey("gen_ai.response.completion_tokens")));
+ Assertions.assertEquals(42,
+ spans.get(0).getAttributes()
+ .get(AttributeKey.longKey("gen_ai.response.prompt_tokens")));
+ }
+}
diff --git a/java/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java
similarity index 99%
rename from java/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java
rename to aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java
index 21593219..5a25e1ae 100644
--- a/java/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java
+++ b/aiservices/openai/src/test/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/OpenAiChatCompletionTest.java
@@ -107,7 +107,6 @@ public ChatCompletions getValue() {
return new ObjectMapper()
.readValue(String.format(message, "Snuggles"),
ChatCompletions.class);
-
} catch (Exception e) {
throw new RuntimeException(e);
}
diff --git a/java/aiservices/openai/src/test/resources/com/microsoft/semantickernel/aiservices/openai/chatcompletion/chatCompletion.txt b/aiservices/openai/src/test/resources/com/microsoft/semantickernel/aiservices/openai/chatcompletion/chatCompletion.txt
similarity index 100%
rename from java/aiservices/openai/src/test/resources/com/microsoft/semantickernel/aiservices/openai/chatcompletion/chatCompletion.txt
rename to aiservices/openai/src/test/resources/com/microsoft/semantickernel/aiservices/openai/chatcompletion/chatCompletion.txt
diff --git a/java/api-test/integration-tests/pom.xml b/api-test/integration-tests/pom.xml
similarity index 93%
rename from java/api-test/integration-tests/pom.xml
rename to api-test/integration-tests/pom.xml
index 5ab14e89..48f5b608 100644
--- a/java/api-test/integration-tests/pom.xml
+++ b/api-test/integration-tests/pom.xml
@@ -6,7 +6,7 @@
com.microsoft.semantic-kernelapi-test
- 1.1.5
+ 1.2.0../pom.xml
@@ -56,6 +56,11 @@
semantickernel-apitest
+
+ com.microsoft.semantic-kernel
+ semantickernel-experimental
+ test
+ org.xerial
@@ -84,13 +89,18 @@
mysqltest
+
+ com.redis
+ testcontainers-redis
+ 2.2.2
+ test
+ org.wiremockwiremock3.3.1test
-
@@ -174,7 +184,7 @@
foohttps://localhost:8443/
- ../../../
+ ../../
diff --git a/java/api-test/integration-tests/scripts/generateCert.sh b/api-test/integration-tests/scripts/generateCert.sh
similarity index 100%
rename from java/api-test/integration-tests/scripts/generateCert.sh
rename to api-test/integration-tests/scripts/generateCert.sh
diff --git a/java/api-test/integration-tests/scripts/recordMappings.sh b/api-test/integration-tests/scripts/recordMappings.sh
similarity index 100%
rename from java/api-test/integration-tests/scripts/recordMappings.sh
rename to api-test/integration-tests/scripts/recordMappings.sh
diff --git a/java/api-test/integration-tests/scripts/runWiremocks.sh b/api-test/integration-tests/scripts/runWiremocks.sh
similarity index 100%
rename from java/api-test/integration-tests/scripts/runWiremocks.sh
rename to api-test/integration-tests/scripts/runWiremocks.sh
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example01NativeFunctionsTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example01NativeFunctionsTest.java
similarity index 100%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example01NativeFunctionsTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example01NativeFunctionsTest.java
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java
similarity index 100%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example03_ArgumentsTest.java
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java
similarity index 87%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java
index 135a927f..f74268b2 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/Example05_InlineFunctionDefinitionTest.java
@@ -6,6 +6,7 @@
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
@@ -27,13 +28,13 @@ public void main(WireMockRuntimeInfo wmRuntimeInfo) {
.endpoint("http://localhost:" + wmRuntimeInfo.getHttpPort())
.buildAsyncClient();
- TextGenerationService textGenerationService = TextGenerationService.builder()
+ OpenAIChatCompletion chatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
- .withModelId("text-davinci-003")
+ .withModelId("gpt-35-turbo")
.build();
Kernel kernel = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(OpenAIChatCompletion.class, chatCompletion)
.build();
System.out.println("======== Inline Function Definition ========");
@@ -63,7 +64,7 @@ public void main(WireMockRuntimeInfo wmRuntimeInfo) {
.build())
.build();
- WireMockUtil.mockCompletionResponse("I missed the F1 final race", "a-response");
+ WireMockUtil.mockChatCompletionResponse("I missed the F1 final race", "a-response");
var result = kernel.invokeAsync(excuseFunction)
.withArguments(
@@ -74,7 +75,7 @@ public void main(WireMockRuntimeInfo wmRuntimeInfo) {
Assertions.assertEquals("a-response", result.getResult());
- WireMockUtil.mockCompletionResponse("sorry I forgot your birthday", "a-response-2");
+ WireMockUtil.mockChatCompletionResponse("sorry I forgot your birthday", "a-response-2");
result = kernel.invokeAsync(excuseFunction)
.withArguments(
@@ -85,7 +86,7 @@ public void main(WireMockRuntimeInfo wmRuntimeInfo) {
Assertions.assertEquals("a-response-2", result.getResult());
- WireMockUtil.mockCompletionResponse("Translate this date ", "a-response-3");
+ WireMockUtil.mockChatCompletionResponse("Translate this date ", "a-response-3");
var date = DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZoneOffset.UTC)
.format(Instant.ofEpochSecond(1));
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java
similarity index 100%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ImportingMultiplePluginsTest.java
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java
similarity index 98%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java
index d53db894..16b9cada 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/KernelHooksTest.java
@@ -29,7 +29,7 @@ private static Builder getKernelBuilder(WireMockRuntimeInfo wmRuntimeInfo) {
.buildAsyncClient();
ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
- .withModelId("text-davinci-003")
+ .withModelId("gpt-35-turbo")
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java
similarity index 94%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java
index 319940da..39b11182 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/RenderingTest.java
@@ -210,12 +210,12 @@ public List WithListReturn() {
@DefineKernelFunction(name = "WithListReturn2", returnType = "java.util.List")
public List WithListReturn2() {
- return List.of(1, 2, 3);
+ return List.of(4, 5, 6);
}
@DefineKernelFunction(name = "WithListReturn3", returnType = "java.util.List")
public Mono> WithListReturn3() {
- return Mono.just(List.of(1, 2, 3));
+ return Mono.just(List.of(7, 8, 9));
}
@DefineKernelFunction(name = "WithListReturn4", returnType = "java.util.List")
@@ -239,15 +239,11 @@ public void canHandleIterableReturnFromFunction() {
.build())
.block();
- Assertions.assertTrue(
- wm.getAllServeEvents().get(0).getRequest().getBodyAsString().equals(
- "{\"messages\":["
- + "{\"role\":\"user\",\"content\":\"[]\"},"
- + "{\"role\":\"user\",\"content\":\"[1, 2, 3]\"},"
- + "{\"role\":\"user\",\"content\":\"[1, 2, 3]\"},"
- + "{\"role\":\"user\",\"content\":\"[1, 2, 3]\"},"
- + "{\"role\":\"user\",\"content\":\"[]\"}"
- + "],\"model\":\"gpt-35-turbo-2\"}"));
+ String requestBody = wm.getAllServeEvents().get(0).getRequest().getBodyAsString();
+ Assertions.assertTrue(requestBody.contains("{\"role\":\"user\",\"content\":\"[]"));
+ Assertions.assertTrue(requestBody.contains("{\"role\":\"user\",\"content\":\"[1, 2, 3]"));
+ Assertions.assertTrue(requestBody.contains("{\"role\":\"user\",\"content\":\"[4, 5, 6]"));
+ Assertions.assertTrue(requestBody.contains("{\"role\":\"user\",\"content\":\"[7, 8, 9]"));
}
private Kernel buildTextKernel() {
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ToolCallBehaviourTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ToolCallBehaviourTest.java
similarity index 97%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ToolCallBehaviourTest.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ToolCallBehaviourTest.java
index 78328308..852f5578 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ToolCallBehaviourTest.java
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/ToolCallBehaviourTest.java
@@ -13,6 +13,7 @@
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.github.tomakehurst.wiremock.matching.ContainsPattern;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatMessageContent;
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIFunctionToolCall;
import com.microsoft.semantickernel.implementation.CollectionUtil;
@@ -26,6 +27,7 @@
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageTextContent;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -73,9 +75,7 @@ public void nonAutoInvokedIsNotCalled() throws NoSuchMethodException {
ChatHistory messages = new ChatHistory();
messages.addMessage(
- new ChatMessageContent<>(
- AuthorRole.USER,
- "Call A function"));
+ ChatMessageTextContent.userMessage("Call A function"));
List> result = chatCompletionService
.getChatMessageContentsAsync(
@@ -124,9 +124,7 @@ public void toolIsInvoked() throws NoSuchMethodException {
ChatHistory messages = new ChatHistory();
messages.addMessage(
- new ChatMessageContent<>(
- AuthorRole.USER,
- "Call A function"));
+ ChatMessageTextContent.userMessage("Call A function"));
List> result = chatCompletionService
.getChatMessageContentsAsync(
@@ -275,7 +273,7 @@ private ChatCompletionService getChatCompletionService() {
.endpoint("http://localhost:" + wm.port() + "/")
.buildAsyncClient();
- return ChatCompletionService.builder()
+ return OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId("gpt-35-turbo-2")
.build();
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WireMockUtil.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WireMockUtil.java
similarity index 97%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WireMockUtil.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WireMockUtil.java
index 5bf39de8..93adcd81 100644
--- a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WireMockUtil.java
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WireMockUtil.java
@@ -116,7 +116,7 @@ public static void mockChatCompletionResponse(
WireMock.reset();
WireMock.stubFor(WireMock
.post(new UrlPathPattern(
- new RegexPattern("/openai/deployments/text-davinci-003/chat/completions"), true))
+ new RegexPattern("/openai/deployments/gpt-35-turbo/chat/completions"), true))
.withRequestBody(WireMock.matching(".*" + regexMatcher + ".*"))
.willReturn(WireMock.ok()
.withBody(body)));
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockExamplesIT.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockExamplesIT.java
similarity index 100%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockExamplesIT.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockExamplesIT.java
diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockRecord.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockRecord.java
similarity index 100%
rename from java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockRecord.java
rename to api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/WiremockRecord.java
diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/Hotel.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/Hotel.java
new file mode 100644
index 00000000..e43842fc
--- /dev/null
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/Hotel.java
@@ -0,0 +1,59 @@
+package com.microsoft.semantickernel.tests.connectors.memory;
+
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordDataAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordKeyAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordVectorAttribute;
+
+import java.util.List;
+
+public class Hotel {
+ @VectorStoreRecordKeyAttribute
+ private final String id;
+ @VectorStoreRecordDataAttribute
+ private final String name;
+ @VectorStoreRecordDataAttribute
+ private final int code;
+ @VectorStoreRecordDataAttribute(hasEmbedding = true, embeddingFieldName = "descriptionEmbedding")
+ private final String description;
+ @VectorStoreRecordVectorAttribute(dimensions = 3)
+ private final List descriptionEmbedding;
+ @VectorStoreRecordDataAttribute
+ private final double rating;
+
+ public Hotel() {
+ this(null, null, 0, null, null, 0.0);
+ }
+
+ public Hotel(String id, String name, int code, String description, List descriptionEmbedding, double rating) {
+ this.id = id;
+ this.name = name;
+ this.code = code;
+ this.description = description;
+ this.descriptionEmbedding = descriptionEmbedding;
+ this.rating = rating;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getDescriptionEmbedding() {
+ return descriptionEmbedding;
+ }
+
+ public double getRating() {
+ return rating;
+ }
+}
diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/redis/RedisVectorStoreRecordCollectionTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/redis/RedisVectorStoreRecordCollectionTest.java
new file mode 100644
index 00000000..db3b6d6c
--- /dev/null
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/redis/RedisVectorStoreRecordCollectionTest.java
@@ -0,0 +1,305 @@
+package com.microsoft.semantickernel.tests.connectors.memory.redis;
+
+import com.microsoft.semantickernel.connectors.data.redis.RedisVectorStoreRecordCollection;
+import com.microsoft.semantickernel.connectors.data.redis.RedisVectorStoreRecordCollectionOptions;
+import com.microsoft.semantickernel.data.recorddefinition.VectorStoreRecordDataField;
+import com.microsoft.semantickernel.data.recorddefinition.VectorStoreRecordDefinition;
+import com.microsoft.semantickernel.data.recorddefinition.VectorStoreRecordField;
+import com.microsoft.semantickernel.data.recorddefinition.VectorStoreRecordKeyField;
+import com.microsoft.semantickernel.data.recorddefinition.VectorStoreRecordVectorField;
+import com.microsoft.semantickernel.data.recordoptions.GetRecordOptions;
+import com.microsoft.semantickernel.tests.connectors.memory.Hotel;
+import com.redis.testcontainers.RedisContainer;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import redis.clients.jedis.JedisPooled;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.assertNull;
+
+@Testcontainers
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class RedisVectorStoreRecordCollectionTest {
+
+ @Container private static final RedisContainer redisContainer = new RedisContainer("redis/redis-stack:latest");
+
+ private static final Map> optionsMap = new HashMap<>();
+
+ public enum RecordCollectionOptions {
+ DEFAULT, WITH_CUSTOM_DEFINITION
+ }
+
+ @BeforeAll
+ static void setup() {
+ optionsMap.put(RecordCollectionOptions.DEFAULT, RedisVectorStoreRecordCollectionOptions.builder()
+ .withRecordClass(Hotel.class)
+ .build());
+
+ List fields = new ArrayList<>();
+ fields.add(VectorStoreRecordKeyField.builder()
+ .withName("id")
+ .build());
+ fields.add(VectorStoreRecordDataField.builder()
+ .withName("name")
+ .withFieldType(String.class)
+ .build());
+ fields.add(VectorStoreRecordDataField.builder()
+ .withName("code")
+ .withFieldType(Integer.class)
+ .build());
+ fields.add(VectorStoreRecordDataField.builder()
+ .withName("description")
+ .withFieldType(String.class)
+ .withHasEmbedding(true)
+ .withEmbeddingFieldName("descriptionEmbedding")
+ .build());
+ fields.add(VectorStoreRecordVectorField.builder()
+ .withName("descriptionEmbedding")
+ .withDimensions(768)
+ .build());
+ fields.add(VectorStoreRecordDataField.builder()
+ .withName("rating")
+ .withFieldType(Double.class)
+ .build());
+ VectorStoreRecordDefinition recordDefinition = VectorStoreRecordDefinition.fromFields(fields);
+
+ optionsMap.put(RecordCollectionOptions.WITH_CUSTOM_DEFINITION, RedisVectorStoreRecordCollectionOptions.builder()
+ .withRecordClass(Hotel.class)
+ .withRecordDefinition(recordDefinition)
+ .build());
+ }
+
+ private RedisVectorStoreRecordCollection buildrecordCollection(@Nonnull RedisVectorStoreRecordCollectionOptions options, @Nonnull String collectionName) {
+ return new RedisVectorStoreRecordCollection<>(new JedisPooled(redisContainer.getRedisURI()), collectionName, RedisVectorStoreRecordCollectionOptions.builder()
+ .withRecordClass(options.getRecordClass())
+ .withVectorStoreRecordMapper(options.getVectorStoreRecordMapper())
+ .withRecordDefinition(options.getRecordDefinition())
+ .withPrefixCollectionName(options.isPrefixCollectionName())
+ .build());
+ }
+
+ private List getHotels() {
+ return List.of(
+ new Hotel("id_1", "Hotel 1", 1, "Hotel 1 description", Arrays.asList(1.0f, 2.0f, 3.0f), 4.0),
+ new Hotel("id_2", "Hotel 2", 2, "Hotel 2 description", Arrays.asList(1.0f, 2.0f, 3.0f), 3.0),
+ new Hotel("id_3", "Hotel 3", 3, "Hotel 3 description", Arrays.asList(1.0f, 2.0f, 3.0f), 5.0),
+ new Hotel("id_4", "Hotel 4", 4, "Hotel 4 description", Arrays.asList(1.0f, 2.0f, 3.0f), 4.0),
+ new Hotel("id_5", "Hotel 5", 5, "Hotel 5 description", Arrays.asList(1.0f, 2.0f, 3.0f), 5.0)
+ );
+ }
+
+ @Order(1)
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void buildrecordCollection(RecordCollectionOptions options) {
+ assertNotNull(buildrecordCollection(optionsMap.get(options), options.name()));
+ }
+
+ @Order(2)
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void createCollectionAsync(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ assertEquals(false, recordCollection.collectionExistsAsync().block());
+ recordCollection.createCollectionAsync().block();
+ assertEquals(true, recordCollection.collectionExistsAsync().block());
+ }
+
+ @Test
+ public void deleteCollectionAsync() {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(RecordCollectionOptions.DEFAULT), "deleteCollectionAsync");
+
+ assertEquals(false, recordCollection.collectionExistsAsync().block());
+ recordCollection.createCollectionAsync().block();
+ recordCollection.deleteCollectionAsync().block();
+ assertEquals(false, recordCollection.collectionExistsAsync().block());
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void upsertAndGetRecordAsync(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ for (Hotel hotel : hotels) {
+ recordCollection.upsertAsync(hotel, null).block();
+ }
+
+ for (Hotel hotel : hotels) {
+ Hotel retrievedHotel = recordCollection.getAsync(hotel.getId(), null).block();
+ assertNotNull(retrievedHotel);
+ assertEquals(hotel.getId(), retrievedHotel.getId());
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void getBatchAsync(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ for (Hotel hotel : hotels) {
+ recordCollection.upsertAsync(hotel, null).block();
+ }
+
+ List ids = new ArrayList<>();
+ hotels.forEach(hotel -> ids.add(hotel.getId()));
+
+ List retrievedHotels = recordCollection.getBatchAsync(ids, null).block();
+
+ assertNotNull(retrievedHotels);
+ assertEquals(hotels.size(), retrievedHotels.size());
+ for (int i = 0; i < hotels.size(); i++) {
+ assertEquals(hotels.get(i).getId(), retrievedHotels.get(i).getId());
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void upsertBatchAsync(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ List keys = recordCollection.upsertBatchAsync(hotels, null).block();
+ assertNotNull(keys);
+
+ List retrievedHotels = (List) recordCollection.getBatchAsync(keys, null).block();
+
+ assertNotNull(retrievedHotels);
+ assertEquals(hotels.size(), retrievedHotels.size());
+ for (int i = 0; i < hotels.size(); i++) {
+ assertEquals(hotels.get(i).getId(), retrievedHotels.get(i).getId());
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void deleteAsync(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ recordCollection.upsertBatchAsync(hotels, null).block();
+
+ for (Hotel hotel : hotels) {
+ recordCollection.deleteAsync(hotel.getId(), null).block();
+ Hotel retrievedHotel = recordCollection.getAsync(hotel.getId(), null).block();
+ assertNull(retrievedHotel);
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void deleteBatchAsync(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ recordCollection.upsertBatchAsync(hotels, null).block();
+
+ List ids = new ArrayList<>();
+ hotels.forEach(hotel -> ids.add(hotel.getId()));
+
+ recordCollection.deleteBatchAsync(ids, null).block();
+
+ for (String id : ids) {
+ Hotel retrievedHotel = recordCollection.getAsync(id, null).block();
+ assertNull(retrievedHotel);
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void getAsyncWithVectors(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ recordCollection.upsertBatchAsync(hotels, null).block();
+
+ for (Hotel hotel : hotels) {
+ Hotel retrievedHotel = recordCollection.getAsync(hotel.getId(), null).block();
+ assertNotNull(retrievedHotel);
+ assertNotNull(retrievedHotel.getDescriptionEmbedding());
+ assertEquals(hotel.getId(), retrievedHotel.getId());
+ assertEquals(hotel.getDescription(), retrievedHotel.getDescription());
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void getBatchAsyncWithVectors(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ recordCollection.upsertBatchAsync(hotels, null).block();
+
+ List ids = new ArrayList<>();
+ hotels.forEach(hotel -> ids.add(hotel.getId()));
+
+ List retrievedHotels = recordCollection.getBatchAsync(ids, null).block();
+
+ assertNotNull(retrievedHotels);
+ assertEquals(hotels.size(), retrievedHotels.size());
+ for (int i = 0; i < hotels.size(); i++) {
+ assertEquals(hotels.get(i).getId(), retrievedHotels.get(i).getId());
+ assertEquals(hotels.get(i).getDescription(), retrievedHotels.get(i).getDescription());
+ assertNotNull(retrievedHotels.get(i).getDescriptionEmbedding());
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void getAsyncWithNoVectors(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ recordCollection.upsertBatchAsync(hotels, null).block();
+
+ GetRecordOptions getRecordOptions = GetRecordOptions.builder().includeVectors(false).build();
+ for (Hotel hotel : hotels) {
+ Hotel retrievedHotel = recordCollection.getAsync(hotel.getId(), getRecordOptions).block();
+ assertNotNull(retrievedHotel);
+ assertNull(retrievedHotel.getDescriptionEmbedding());
+ assertEquals(hotel.getId(), retrievedHotel.getId());
+ assertEquals(hotel.getDescription(), retrievedHotel.getDescription());
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(RecordCollectionOptions.class)
+ public void getBatchAsyncWithNoVectors(RecordCollectionOptions options) {
+ RedisVectorStoreRecordCollection recordCollection = buildrecordCollection(optionsMap.get(options), options.name());
+
+ List hotels = getHotels();
+ recordCollection.upsertBatchAsync(hotels, null).block();
+
+ GetRecordOptions getRecordOptions = GetRecordOptions.builder().includeVectors(false).build();
+ List ids = new ArrayList<>();
+ hotels.forEach(hotel -> ids.add(hotel.getId()));
+
+ List retrievedHotels = recordCollection.getBatchAsync(ids, getRecordOptions).block();
+
+ assertNotNull(retrievedHotels);
+ assertEquals(hotels.size(), retrievedHotels.size());
+ for (int i = 0; i < hotels.size(); i++) {
+ assertEquals(hotels.get(i).getId(), retrievedHotels.get(i).getId());
+ assertEquals(hotels.get(i).getDescription(), retrievedHotels.get(i).getDescription());
+ assertNull(retrievedHotels.get(i).getDescriptionEmbedding());
+ }
+ }
+}
diff --git a/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/redis/RedisVectorStoreTest.java b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/redis/RedisVectorStoreTest.java
new file mode 100644
index 00000000..96341053
--- /dev/null
+++ b/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/tests/connectors/memory/redis/RedisVectorStoreTest.java
@@ -0,0 +1,48 @@
+package com.microsoft.semantickernel.tests.connectors.memory.redis;
+
+import com.microsoft.semantickernel.connectors.data.redis.RedisVectorStore;
+import com.microsoft.semantickernel.connectors.data.redis.RedisVectorStoreOptions;
+import com.microsoft.semantickernel.data.recorddefinition.VectorStoreRecordDefinition;
+import com.microsoft.semantickernel.tests.connectors.memory.Hotel;
+import com.redis.testcontainers.RedisContainer;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import redis.clients.jedis.JedisPooled;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@Testcontainers
+public class RedisVectorStoreTest {
+ @Container
+ private static final RedisContainer redisContainer = new RedisContainer("redis/redis-stack:latest");
+ private static JedisPooled jedis;
+
+ @BeforeAll
+ public static void setUp() {
+ jedis = new JedisPooled(redisContainer.getRedisURI());
+ }
+
+ @Test
+ public void getCollectionNamesAsync() {
+ RedisVectorStore vectorStore = new RedisVectorStore(jedis, new RedisVectorStoreOptions());
+ List collectionNames = Arrays.asList("collection1", "collection2", "collection3");
+
+ for (String collectionName : collectionNames) {
+ vectorStore.getCollection(collectionName, Hotel.class, null).createCollectionAsync().block();
+ }
+
+ List retrievedCollectionNames = vectorStore.getCollectionNamesAsync().block();
+ assertNotNull(retrievedCollectionNames);
+ assertEquals(collectionNames.size(), retrievedCollectionNames.size());
+ for (String collectionName : collectionNames) {
+ assertTrue(retrievedCollectionNames.contains(collectionName));
+ }
+ }
+}
diff --git a/java/api-test/integration-tests/src/test/resources/log4j2.xml b/api-test/integration-tests/src/test/resources/log4j2.xml
similarity index 100%
rename from java/api-test/integration-tests/src/test/resources/log4j2.xml
rename to api-test/integration-tests/src/test/resources/log4j2.xml
diff --git a/java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-12b6744e-443f-4fe7-82e2-55cc41195ff1.json b/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-12b6744e-443f-4fe7-82e2-55cc41195ff1.json
similarity index 100%
rename from java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-12b6744e-443f-4fe7-82e2-55cc41195ff1.json
rename to api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-12b6744e-443f-4fe7-82e2-55cc41195ff1.json
diff --git a/java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-71b07779-49a8-44e5-a60b-ee5b0a3ad697.json b/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-71b07779-49a8-44e5-a60b-ee5b0a3ad697.json
similarity index 100%
rename from java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-71b07779-49a8-44e5-a60b-ee5b0a3ad697.json
rename to api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo-2_chat_completions-71b07779-49a8-44e5-a60b-ee5b0a3ad697.json
diff --git a/java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo_chat_completions-0c8046c5-74ad-4836-8aa9-09da60f367a2.json b/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo_chat_completions-0c8046c5-74ad-4836-8aa9-09da60f367a2.json
similarity index 100%
rename from java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo_chat_completions-0c8046c5-74ad-4836-8aa9-09da60f367a2.json
rename to api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_gpt-35-turbo_chat_completions-0c8046c5-74ad-4836-8aa9-09da60f367a2.json
diff --git a/java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_text-davinci-003_completions-0215b128-4822-4368-ac3d-2f580a221f00.json b/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_text-davinci-003_completions-0215b128-4822-4368-ac3d-2f580a221f00.json
similarity index 100%
rename from java/api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_text-davinci-003_completions-0215b128-4822-4368-ac3d-2f580a221f00.json
rename to api-test/integration-tests/src/test/resources/wiremock/mappings/deployments_text-davinci-003_completions-0215b128-4822-4368-ac3d-2f580a221f00.json
diff --git a/java/api-test/pom.xml b/api-test/pom.xml
similarity index 98%
rename from java/api-test/pom.xml
rename to api-test/pom.xml
index 83f5f2f4..7b49dd77 100644
--- a/java/api-test/pom.xml
+++ b/api-test/pom.xml
@@ -6,7 +6,7 @@
com.microsoft.semantic-kernelsemantickernel-parent
- 1.1.5
+ 1.2.0../pom.xml
diff --git a/java/api-test/spotbugs-exclude.xml b/api-test/spotbugs-exclude.xml
similarity index 100%
rename from java/api-test/spotbugs-exclude.xml
rename to api-test/spotbugs-exclude.xml
diff --git a/java/connectors/semantickernel-connectors-memory-redis/pom.xml b/connectors/semantickernel-connectors-memory-redis/pom.xml
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/pom.xml
rename to connectors/semantickernel-connectors-memory-redis/pom.xml
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/JsonMemoryRecord.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/JsonMemoryRecord.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/JsonMemoryRecord.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/JsonMemoryRecord.java
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisException.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisException.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisException.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisException.java
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisIndexSchemaParams.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisIndexSchemaParams.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisIndexSchemaParams.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisIndexSchemaParams.java
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryRecord.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryRecord.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryRecord.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryRecord.java
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryStore.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryStore.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryStore.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisMemoryStore.java
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorDistanceMetric.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorDistanceMetric.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorDistanceMetric.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorDistanceMetric.java
diff --git a/java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorType.java b/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorType.java
similarity index 100%
rename from java/connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorType.java
rename to connectors/semantickernel-connectors-memory-redis/src/main/java/com/microsoft/semantickernel/connectors/memory/redis/RedisVectorType.java
diff --git a/java/connectors/semantickernel-connectors-web-bing/pom.xml b/connectors/semantickernel-connectors-web-bing/pom.xml
similarity index 100%
rename from java/connectors/semantickernel-connectors-web-bing/pom.xml
rename to connectors/semantickernel-connectors-web-bing/pom.xml
diff --git a/java/eclipse-formatter.xml b/eclipse-formatter.xml
similarity index 100%
rename from java/eclipse-formatter.xml
rename to eclipse-formatter.xml
diff --git a/java/CHANGELOG.md b/java/CHANGELOG.md
deleted file mode 100644
index d0c864ad..00000000
--- a/java/CHANGELOG.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# 1.1.5
-
-- Fix bug with removing new lines on function parameters on Windows
-- Fix bug forming serializing arguments to tool calls
-
-# 1.1.3
-
-- Fix bug appending plugin name to tool calls
-- Improve exception handling in OpenAIChatCompletion
-
-# 1.1.2
-
-- Upgrade azure-identity to 1.12.1
-- Remove fixed netty version in bom
-
-# 1.1.1
-
-- Upgrade azure-ai-openai to 1.0.0-beta.8
-
-# 1.1.0
-
-### Breaking Changes
-
-- `ChatHistory` no longer has a default message, see below for more details.
-
-### Api Changes
- - Allow setting deployment name in addition to modelId on AI services.
- - Remove default message of "Assistant is a large language model" from ChatHistory
- - **This is a breaking change if you were relying on the default message in your code**
- - Add InvocationReturnMode and rework OpenAi chat completion to allow configuring what data is returned from Chat requests
-
-### Other
-- Reorganize example projects and documentation structure.
-- Number of sample updates and bug fixes.
\ No newline at end of file
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/AzureOpenAIConnectionPropertiesTest.java b/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/AzureOpenAIConnectionPropertiesTest.java
deleted file mode 100644
index 76870b8f..00000000
--- a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/AzureOpenAIConnectionPropertiesTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.microsoft.semantickernel.azureopenai;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import com.microsoft.semantickernel.starter.AzureOpenAIConnectionProperties;
-import com.microsoft.semantickernel.starter.SemanticKernelAutoConfiguration;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.test.context.ActiveProfiles;
-
-@ActiveProfiles("test")
-public class AzureOpenAIConnectionPropertiesTest {
-
- ApplicationContextRunner contextRunner =
- new ApplicationContextRunner()
- .withPropertyValues(
- // @formatter:off
- "client.azureopenai.key=TEST_KEY",
- "client.azureopenai.endpoint=TEST_ENDPOINT",
- "client.azureopenai.deploymentname=TEST_DEPLOYMENT_NAME"
-
- // @formatter:on
- )
- .withConfiguration(
- AutoConfigurations.of(SemanticKernelAutoConfiguration.class));
-
- @Test
- public void ConnectionPropertiesTest() {
- contextRunner.run(
- context -> {
- AzureOpenAIConnectionProperties props =
- context.getBean(AzureOpenAIConnectionProperties.class);
- assertNotNull(props.getEndpoint());
- assertNotNull(props.getKey());
- assertNotNull(props.getDeploymentName());
- });
- }
-}
diff --git a/java/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java b/java/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java
deleted file mode 100644
index a1634078..00000000
--- a/java/semantickernel-api/src/test/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethodTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.semanticfunctions;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import com.microsoft.semantickernel.Kernel;
-import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
-import com.microsoft.semantickernel.orchestration.FunctionResult;
-import com.microsoft.semantickernel.plugin.KernelPlugin;
-import com.microsoft.semantickernel.plugin.KernelPluginFactory;
-import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
-import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import reactor.core.publisher.Mono;
-
-public class KernelFunctionFromMethodTest {
-
- public KernelFunctionFromMethodTest() {
- }
-
- public static class ExamplePlugin {
-
- @DefineKernelFunction(name = "sqrt", description = "Take the square root of a number")
- public static double sqrt(
- @KernelFunctionParameter(name = "number1", description = "The number to take a square root of", type = double.class) double number1) {
- return Math.sqrt(number1);
- }
- }
-
- @Test
- void typeConversionOnMethodCall() {
- KernelPlugin plugin = KernelPluginFactory.createFromObject(
- new ExamplePlugin(), "ExamplePlugin");
-
- Kernel kernel = Kernel.builder().build();
-
- FunctionResult result = plugin
- .get("sqrt")
- .invokeAsync(kernel)
- .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(String.class))
- .withArguments(
- KernelFunctionArguments.builder()
- .withVariable("number1", "12.0")
- .build())
- .block();
-
- Assertions.assertEquals("3.4641016151377544", result.getResult());
- }
-
- @Test
- void testCreate() throws Exception {
- Method method = String.class.getMethod("concat", String.class);
- String pluginName = "test-plugin";
- String functionName = "concat";
- String description = "concatenate two strings";
- List parameters = Collections.singletonList(InputVariable.build(
- "string1", String.class, "first string to concatenate", null, null, true));
- OutputVariable returnParameter = new OutputVariable<>(
- "concatenated strings", String.class);
- KernelFunction> result = KernelFunctionFromMethod.create(method, "test", pluginName,
- functionName, description, parameters, returnParameter);
- assertEquals(functionName, result.getName());
- assertEquals(pluginName, result.getPluginName());
- assertEquals(description, result.getDescription());
- assertEquals(parameters, result.getMetadata().getParameters());
- assertEquals(returnParameter, result.getMetadata().getOutputVariableType());
- }
-
- /**
- * Test of builder method, of class KernelFunctionFromMethod.
- */
- @Test
- void testBuilder() {
- String pluginName = null;
- String functionName = "concat";
- String description = "concatenate two strings";
- List parameters = Collections
- .singletonList(new InputVariable("string1",
- "java.lang.String", "first string to concatenate", null, true, null));
- OutputVariable> returnParameter = new OutputVariable<>("java.lang.String",
- "concatenated strings");
- KernelFunction result = new KernelFunctionFromPrompt.Builder()
- .withName(functionName)
- .withDescription(description)
- .withInputParameters(parameters)
- .withOutputVariable(returnParameter)
- .withPromptTemplate((kernel, args, context) -> Mono.empty())
- .build();
- assertEquals(functionName, result.getName());
- assertEquals(pluginName, result.getPluginName());
- assertEquals(description, result.getDescription());
- // TODO: This assert fails because getParameters is a List>, not an List
- // This feels like it's broken. Until this is fixed, we can compare the types
- // assertEquals(parameters, result.getMetadata().getParameters());
- assertEquals(parameters.size(), result.getMetadata().getParameters().size());
- for (int i = 0; i < parameters.size(); i++) {
- assertEquals(parameters.get(i).getDescription(),
- result.getMetadata().getParameters().get(i).getDescription());
- assertEquals(parameters.get(i).getName(),
- result.getMetadata().getParameters().get(i).getName());
- assertEquals(parameters.get(i).getType(),
- result.getMetadata().getParameters().get(i).getType());
- assertEquals(parameters.get(i).isRequired(),
- result.getMetadata().getParameters().get(i).isRequired());
- }
- assertEquals(returnParameter, result.getMetadata().getOutputVariableType());
- assertEquals(returnParameter.getType(),
- result.getMetadata().getOutputVariableType().getType());
- assertEquals(returnParameter.getDescription(),
- result.getMetadata().getOutputVariableType().getDescription());
- }
-
- /**
- * Test of invokeAsync method, of class KernelFunctionFromMethod.
- */
- @Test
- @Disabled("TODO: needs mocked http server")
- void testInvokeAsync() {
- }
-
-}
\ No newline at end of file
diff --git a/java/mvnw b/mvnw
similarity index 100%
rename from java/mvnw
rename to mvnw
diff --git a/java/mvnw.cmd b/mvnw.cmd
similarity index 100%
rename from java/mvnw.cmd
rename to mvnw.cmd
diff --git a/java/pom.xml b/pom.xml
similarity index 96%
rename from java/pom.xml
rename to pom.xml
index 267fedbb..313a7869 100644
--- a/java/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.microsoft.semantic-kernelsemantickernel-parent
- 1.1.5
+ 1.2.0pomhttps://www.github.com/microsoft/semantic-kernel
@@ -68,9 +68,12 @@
semantickernel-bom
- aiservices/openai
-
semantickernel-api
+ semantickernel-experimental
+
+ aiservices/openai
+ aiservices/google
+ aiservices/huggingface
@@ -649,7 +652,7 @@
4.30
- eclipse-formatter.xml
+ ./eclipse-formatter.xml
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+
+ true
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 17
+ 17
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ run-sample
+
+ java
+
+
+
+
+ com.microsoft.semantickernel.samples.syntaxexamples.${sample}
+
+
+
+
+
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/connectors/web/bing/BingConnector.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/connectors/web/bing/BingConnector.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/connectors/web/bing/BingConnector.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/connectors/web/bing/BingConnector.java
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java
new file mode 100644
index 00000000..08fb2697
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/App.java
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.demos.lights;
+
+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.google.gson.Gson;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
+import com.microsoft.semantickernel.orchestration.InvocationContext;
+import com.microsoft.semantickernel.orchestration.InvocationContext.Builder;
+import com.microsoft.semantickernel.orchestration.InvocationReturnMode;
+import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
+import com.microsoft.semantickernel.plugin.KernelPlugin;
+import com.microsoft.semantickernel.plugin.KernelPluginFactory;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import java.util.List;
+import java.util.Scanner;
+
+public class App {
+
+ private static final String CLIENT_KEY = System.getenv("CLIENT_KEY");
+ private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY");
+
+ // Only required if AZURE_CLIENT_KEY is set
+ private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
+ private static final String MODEL_ID = System.getenv()
+ .getOrDefault("MODEL_ID", "gpt-4o");
+
+ public static void main(String[] args) throws Exception {
+
+ OpenAIAsyncClient client;
+
+ if (AZURE_CLIENT_KEY != null) {
+ client = new OpenAIClientBuilder()
+ .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
+ .endpoint(CLIENT_ENDPOINT)
+ .buildAsyncClient();
+
+ } else {
+ client = new OpenAIClientBuilder()
+ .credential(new KeyCredential(CLIENT_KEY))
+ .buildAsyncClient();
+ }
+
+ // Create your AI service client
+ ChatCompletionService chatService = OpenAIChatCompletion.builder()
+ .withModelId(MODEL_ID)
+ .withOpenAIAsyncClient(client)
+ .build();
+ // Create a plugin (the LightsPlugin class is defined separately)
+ KernelPlugin lightPlugin = KernelPluginFactory.createFromObject(new LightsPlugin(),
+ "LightsPlugin");
+
+ // Create a kernel with Azure OpenAI chat completion and plugin
+ Kernel.Builder builder = Kernel.builder();
+ builder.withAIService(ChatCompletionService.class, chatService);
+ builder.withPlugin(lightPlugin);
+ // Build the kernel
+ Kernel kernel = builder.build();
+
+ ChatCompletionService chatCompletionService = kernel.getService(
+ ChatCompletionService.class);
+
+ ContextVariableTypes
+ .addGlobalConverter(ContextVariableTypeConverter.builder(LightModel.class)
+ .toPromptString(new Gson()::toJson)
+ .build());
+
+ // Enable planning
+ InvocationContext invocationContext = new Builder()
+ .withReturnMode(InvocationReturnMode.LAST_MESSAGE_ONLY)
+ .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true))
+ .withContextVariableConverter(ContextVariableTypeConverter.builder(LightModel.class)
+ .toPromptString(new Gson()::toJson)
+ .build())
+ .build();
+
+ // Create a history to store the conversation
+ ChatHistory history = new ChatHistory();
+ // Initiate a back-and-forth chat
+ Scanner scanner = new Scanner(System.in);
+ String userInput;
+ do {
+ // Collect user input
+ System.out.print("User > ");
+ userInput = scanner.nextLine();
+ // Add user input
+ history.addUserMessage(userInput);
+ List> results = chatCompletionService.getChatMessageContentsAsync(
+ history, kernel, invocationContext).block();
+ for (ChatMessageContent> result : results) {
+ // Print the results
+ if (result.getAuthorRole() == AuthorRole.ASSISTANT && result.getContent() != null) {
+ System.out.println("Assistant > " + result);
+ }
+ // Add the message from the agent to the chat history
+ history.addMessage(result);
+ }
+ } while (userInput != null && !userInput.isEmpty());
+ }
+}
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java
new file mode 100644
index 00000000..072763a9
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightModel.java
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.demos.lights;
+
+public class LightModel {
+
+ private int id;
+ private String name;
+ private Boolean isOn;
+
+ public LightModel(int id, String name, Boolean isOn) {
+ this.id = id;
+ this.name = name;
+ this.isOn = isOn;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Boolean getIsOn() {
+ return isOn;
+ }
+
+ public void setIsOn(Boolean isOn) {
+ this.isOn = isOn;
+ }
+}
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java
new file mode 100644
index 00000000..55d70b02
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/demos/lights/LightsPlugin.java
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.demos.lights;
+
+import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
+import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class LightsPlugin {
+
+ // Mock data for the lights
+ private final List lights = new ArrayList<>();
+
+ public LightsPlugin() {
+ lights.add(new LightModel(1, "Table Lamp", false));
+ lights.add(new LightModel(2, "Porch light", false));
+ lights.add(new LightModel(3, "Chandelier", true));
+ }
+
+ @DefineKernelFunction(name = "get_lights", description = "Gets a list of lights and their current state")
+ public List getLights() {
+ System.out.println("Getting lights");
+ return lights;
+ }
+
+ @DefineKernelFunction(name = "change_state", description = "Changes the state of the light")
+ public LightModel changeState(
+ @KernelFunctionParameter(name = "id", description = "The ID of the light to change") int id,
+ @KernelFunctionParameter(name = "isOn", description = "The new state of the light") boolean isOn) {
+ System.out.println("Changing light " + id + " " + isOn);
+ Optional light = lights.stream()
+ .filter(l -> l.getId() == id)
+ .findFirst();
+
+ if (light.isEmpty()) {
+ throw new IllegalArgumentException("Light not found");
+ }
+ light.get().setIsOn(isOn);
+
+ return light.get();
+ }
+}
\ No newline at end of file
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/TimePlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/TimePlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/TimePlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/TimePlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/text/TextPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/text/TextPlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/text/TextPlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/text/TextPlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/SearchUrlPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/SearchUrlPlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/SearchUrlPlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/SearchUrlPlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/WebSearchEnginePlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/WebSearchEnginePlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/WebSearchEnginePlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/plugins/web/WebSearchEnginePlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example11_WebSearchQueries.java
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java
new file mode 100644
index 00000000..a388c130
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example20_HuggingFace.java
@@ -0,0 +1,95 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples;
+
+import com.azure.core.credential.AzureKeyCredential;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.huggingface.HuggingFaceClient;
+import com.microsoft.semantickernel.aiservices.huggingface.services.HuggingFaceTextGenerationService;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
+import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
+
+public class Example20_HuggingFace {
+
+ private static final String HUGGINGFACE_CLIENT_KEY = System.getenv("HUGGINGFACE_CLIENT_KEY");
+ private static final String HUGGINGFACE_CLIENT_ENDPOINT = System.getenv(
+ "HUGGINGFACE_CLIENT_ENDPOINT");
+
+ public static void main(String[] args) {
+ //runConversationApiExampleAsync();
+ runInferenceApiExampleAsync();
+ }
+
+ public static void runInferenceApiExampleAsync() {
+ System.out.println("\n======== HuggingFace Inference API example ========\n");
+
+ HuggingFaceClient client = HuggingFaceClient.builder()
+ .credential(new AzureKeyCredential(HUGGINGFACE_CLIENT_KEY))
+ .endpoint(HUGGINGFACE_CLIENT_ENDPOINT)
+ .build();
+
+ var chatCompletion = HuggingFaceTextGenerationService.builder()
+ .withModelId("gpt2-24")
+ .withHuggingFaceClient(client)
+ .build();
+
+ Kernel kernel = Kernel.builder()
+ .withAIService(TextGenerationService.class, chatCompletion)
+ .build();
+
+ var questionAnswerFunction = KernelFunctionFromPrompt.builder()
+ .withTemplate("Question: {{$input}}; Answer:")
+ .build();
+
+ var result = kernel.invokeAsync(questionAnswerFunction)
+ .withArguments(
+ KernelFunctionArguments.builder()
+ .withVariable("input", "What is New York?")
+ .build())
+ .withResultType(String.class)
+ .block();
+
+ System.out.println(result.getResult());
+ }
+
+ /*
+ *
+ * public static void runConversationApiExampleAsync() {
+ * System.out.println("\n======== HuggingFace Inference API example ========\n");
+ *
+ * HuggingFaceClient client = HuggingFaceClient.builder()
+ * .credential(new AzureKeyCredential(HUGGINGFACE_CLIENT_KEY))
+ * .endpoint(HUGGINGFACE_CLIENT_ENDPOINT)
+ * .build();
+ *
+ * var chatCompletion = HuggingFaceChatCompletionService.builder()
+ * .withModelId("msft-dialogpt-medium-13")
+ * .withHuggingFaceClient(client)
+ * .build();
+ *
+ * Kernel kernel = Kernel.builder()
+ * .withAIService(ChatCompletionService.class, chatCompletion)
+ * .build();
+ *
+ * var questionAnswerFunction = KernelFunctionFromPrompt.builder()
+ * .withTemplate("""
+ * Assistant is a large language model that answers questions.
+ * What is your question?
+ * {{$input}}
+ * """)
+ * .build();
+ *
+ * var result = kernel.invokeAsync(questionAnswerFunction)
+ * .withArguments(
+ * KernelFunctionArguments.builder()
+ * .withVariable("input", "What is New York?")
+ * .build()
+ * )
+ * .withResultType(String.class)
+ * .block();
+ *
+ * System.out.println(result.getResult());
+ * }
+ *
+ */
+}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example42_KernelBuilder.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example42_KernelBuilder.java
similarity index 87%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example42_KernelBuilder.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example42_KernelBuilder.java
index cc35a564..b95da431 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example42_KernelBuilder.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example42_KernelBuilder.java
@@ -7,6 +7,7 @@
import com.azure.core.credential.KeyCredential;
import com.azure.core.http.HttpClient;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
@@ -26,7 +27,7 @@ public static void main(String[] args) {
Kernel kernel1 = Kernel.builder()
.withAIService(ChatCompletionService.class,
- ChatCompletionService.builder()
+ OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId("gpt-35-turbo-2")
.build())
@@ -42,13 +43,13 @@ public static void main(String[] args) {
.credential(new KeyCredential("a-key"))
.buildAsyncClient();
- TextGenerationService textGenerationService = TextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
+ .withModelId("gpt-35-turbo")
.withOpenAIAsyncClient(client2)
- .withModelId("text-davinci-003")
.build();
Kernel kernel2 = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.build();
/////////////////////////////////////////////////////////
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java
similarity index 95%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java
index 9d2f371c..9dc86a68 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example43_GetModelResult.java
@@ -3,6 +3,7 @@
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
+import com.azure.ai.openai.models.CompletionsUsage;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
@@ -68,9 +69,9 @@ public static void main(String[] args) {
// Display results
System.out.println(result.getResult());
System.out.println(
- "Usage: " + result
+ "Usage: " + ((CompletionsUsage) result
.getMetadata()
- .getUsage().getTotalTokens());
+ .getUsage()).getTotalTokens());
System.out.println();
}
}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example49_LogitBias.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example49_LogitBias.java
similarity index 96%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example49_LogitBias.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example49_LogitBias.java
index 6dcda1c2..e3a8ce22 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example49_LogitBias.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example49_LogitBias.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.InvocationContext;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
@@ -43,7 +44,7 @@ public static void main(String[] args) {
.buildAsyncClient();
}
- ChatCompletionService openAIChatCompletion = ChatCompletionService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId("gpt-35-turbo-2")
.build();
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example55_TextChunker.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example55_TextChunker.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example55_TextChunker.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example55_TextChunker.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java
similarity index 98%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java
index ce5ae6cd..0203f66c 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example57_KernelHooks.java
@@ -6,6 +6,7 @@
import com.azure.ai.openai.models.ChatCompletionsOptions;
import com.azure.ai.openai.models.ChatRequestMessage;
import com.azure.ai.openai.models.ChatRequestSystemMessage;
+import com.azure.ai.openai.models.CompletionsUsage;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
@@ -111,11 +112,12 @@ private static void getUsageAsync(Kernel kernel) {
FunctionInvokedHook postExecutionHandler = event -> {
System.out.println(
- event.getFunction().getName() + " : Post Execution Handler - Usage: " + event
- .getResult()
- .getMetadata()
- .getUsage()
- .getTotalTokens());
+ event.getFunction().getName() + " : Post Execution Handler - Usage: "
+ + ((CompletionsUsage) event
+ .getResult()
+ .getMetadata()
+ .getUsage())
+ .getTotalTokens());
return event;
};
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java
similarity index 97%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java
index 3ab911b7..8348ee51 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example61_MultipleLLMs.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
@@ -42,7 +43,7 @@ public static void main(String[] args) {
}
System.out.println("======== Using Chat GPT model for text generation ========");
- var openAIChatCompletion = ChatCompletionService.builder()
+ var openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withServiceId("AzureOpenAIChat")
.withModelId("gpt-35-turbo-2")
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java
similarity index 96%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java
index be296705..afa5b2e3 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example62_CustomAIServiceSelector.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
@@ -46,7 +47,7 @@ public static void main(String[] args) {
// Build a kernel with multiple chat completion services
- var openAIChatCompletion = ChatCompletionService.builder()
+ var openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withServiceId("AzureOpenAIChat")
.withModelId("gpt-35-turbo-2")
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example67_KernelStreaming.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example67_KernelStreaming.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example67_KernelStreaming.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example67_KernelStreaming.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example69_MutableKernelPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example69_MutableKernelPlugin.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example69_MutableKernelPlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example69_MutableKernelPlugin.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java
similarity index 86%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java
index 3a4d3726..a5b19fe8 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java
@@ -14,7 +14,10 @@
import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example05_InlineFunctionDefinition;
import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example09_FunctionTypes;
import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example27_PromptFunctionsUsingChatGPT;
+import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example59_OpenAIFunctionCalling;
import com.microsoft.semantickernel.samples.syntaxexamples.functions.Example60_AdvancedMethodFunctions;
+import com.microsoft.semantickernel.samples.syntaxexamples.java.KernelFunctionYaml_Example;
+import com.microsoft.semantickernel.samples.syntaxexamples.memory.AzureAISearch_DataStorage;
import com.microsoft.semantickernel.samples.syntaxexamples.plugins.Example10_DescribeAllPluginsAndFunctions;
import com.microsoft.semantickernel.samples.syntaxexamples.plugins.Example13_ConversationSummaryPlugin;
import com.microsoft.semantickernel.samples.syntaxexamples.template.Example06_TemplateLanguage;
@@ -28,13 +31,14 @@
* Run all the syntax examples.
*
* Refer to the
+ * "https://github.com/microsoft/semantic-kernel-java/blob/main/samples/semantickernel-concepts/semantickernel-syntax-examples/README.md">
* README for configuring your environment to run the examples.
*/
public class RunAll {
public static void main(String[] args) {
List mains = Arrays.asList(
+ AzureAISearch_DataStorage::main,
Example01_NativeFunctions::main,
Example03_Arguments::main,
Example05_InlineFunctionDefinition::main,
@@ -42,15 +46,13 @@ public static void main(String[] args) {
Example08_RetryHandler::main,
Example09_FunctionTypes::main,
Example10_DescribeAllPluginsAndFunctions::main,
- //Example11_WebSearchQueries::main,
Example13_ConversationSummaryPlugin::main,
Example17_ChatGPT::main,
- //Example26_AADAuth::main,
-
Example27_PromptFunctionsUsingChatGPT::main,
Example30_ChatWithPrompts::main,
Example33_Chat::main,
Example41_HttpClientUsage::main,
+ Example42_KernelBuilder::main,
Example43_GetModelResult::main,
Example44_MultiChatCompletion::main,
Example49_LogitBias::main,
@@ -58,12 +60,13 @@ public static void main(String[] args) {
Example56_TemplateMethodFunctionsWithMultipleArguments::main,
Example57_KernelHooks::main,
Example58_ConfigureExecutionSettings::main,
+ Example59_OpenAIFunctionCalling::main,
Example60_AdvancedMethodFunctions::main,
- Example61_MultipleLLMs::main,
Example62_CustomAIServiceSelector::main,
Example63_ChatCompletionPrompts::main,
Example64_MultiplePromptTemplates::main,
- Example69_MutableKernelPlugin::main);
+ Example69_MutableKernelPlugin::main,
+ KernelFunctionYaml_Example::main);
Scanner scanner = new Scanner(System.in);
mains.forEach(mainMethod -> {
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/audio/Example82_Audio.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/audio/Example82_Audio.java
similarity index 97%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/audio/Example82_Audio.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/audio/Example82_Audio.java
index e41a9a97..beeebd08 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/audio/Example82_Audio.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/audio/Example82_Audio.java
@@ -22,8 +22,6 @@ public class Example82_Audio {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
- private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "gpt-35-turbo");
private static final String TextToAudioModel = "tts-1";
private static final String AudioToTextModel = "whisper-1";
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example17_ChatGPT.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example17_ChatGPT.java
similarity index 96%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example17_ChatGPT.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example17_ChatGPT.java
index 6bdcd6e6..afd68fa7 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example17_ChatGPT.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example17_ChatGPT.java
@@ -5,6 +5,8 @@
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
+import com.azure.core.util.serializer.JsonSerializerProvider;
+import com.azure.core.util.serializer.JsonSerializerProviders;
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
@@ -20,7 +22,6 @@ public class Example17_ChatGPT {
.getOrDefault("MODEL_ID", "gpt-35-turbo");
public static void main(String[] args) {
-
System.out.println("======== Open AI - ChatGPT ========");
OpenAIAsyncClient client;
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java
similarity index 97%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java
index 3a7b7dcd..1357cc47 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example30_ChatWithPrompts.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.implementation.EmbeddedResourceLoader;
import com.microsoft.semantickernel.plugin.KernelPlugin;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
@@ -46,7 +47,7 @@ public static void main(String[] args) throws FileNotFoundException, ServiceNotF
.buildAsyncClient();
}
- ChatCompletionService openAIChatCompletion = ChatCompletionService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example33_Chat.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example33_Chat.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example33_Chat.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example33_Chat.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example44_MultiChatCompletion.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example44_MultiChatCompletion.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example44_MultiChatCompletion.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example44_MultiChatCompletion.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example63_ChatCompletionPrompts.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example63_ChatCompletionPrompts.java
similarity index 93%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example63_ChatCompletionPrompts.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example63_ChatCompletionPrompts.java
index 166f1565..88fa9db0 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example63_ChatCompletionPrompts.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example63_ChatCompletionPrompts.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import java.util.concurrent.CountDownLatch;
@@ -36,7 +37,7 @@ public static void main(String[] args) throws InterruptedException {
.buildAsyncClient();
}
- ChatCompletionService openAIChatCompletion = ChatCompletionService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example96_GeminiChatCompletion.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example96_GeminiChatCompletion.java
new file mode 100644
index 00000000..8b3aac3a
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example96_GeminiChatCompletion.java
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples.chatcompletion;
+
+import com.google.cloud.vertexai.VertexAI;
+import com.microsoft.semantickernel.aiservices.google.chatcompletion.GeminiChatCompletion;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+
+public class Example96_GeminiChatCompletion {
+ private static final String PROJECT_ID = System.getenv("PROJECT_ID");
+ private static final String LOCATION = System.getenv("LOCATION");
+ private static final String MODEL_ID = System.getenv("GEMINI_MODEL_ID");
+
+ public static void main(String[] args) {
+ // Authenticate with Google Cloud running:
+ // gcloud config set project PROJECT_ID
+ // gcloud auth login ACCOUNT
+ //
+ // Or if you want to use an API key follow:
+ // https://cloud.google.com/docs/authentication/api-keys#using-with-client-libs
+
+ VertexAI client = new VertexAI(PROJECT_ID, LOCATION);
+
+ ChatCompletionService geminiChat = GeminiChatCompletion.builder()
+ .withVertexAIClient(client)
+ .withModelId(MODEL_ID)
+ .build();
+
+ System.out.println("Chat content:");
+ System.out.println("------------------------");
+
+ ChatHistory chatHistory = new ChatHistory();
+
+ // First user message
+ chatHistory.addUserMessage("Hi, I'm looking for book suggestions");
+ messageOutput(chatHistory);
+
+ reply(geminiChat, chatHistory);
+ messageOutput(chatHistory);
+
+ chatHistory.addUserMessage(
+ "I love history and philosophy, I'd like to learn something new about Greece, any suggestion");
+ messageOutput(chatHistory);
+
+ reply(geminiChat, chatHistory);
+ messageOutput(chatHistory);
+ }
+
+ private static void messageOutput(ChatHistory chatHistory) {
+ var message = chatHistory.getLastMessage().get();
+ System.out.println(message.getAuthorRole() + ": " + message.getContent());
+ System.out.println("------------------------");
+ }
+
+ private static void reply(ChatCompletionService geminiChat, ChatHistory chatHistory) {
+ var reply = geminiChat.getChatMessageContentsAsync(chatHistory, null, null)
+ .block();
+
+ StringBuilder message = new StringBuilder();
+ reply.forEach(chatMessageContent -> message.append(chatMessageContent.getContent()));
+ chatHistory.addAssistantMessage(message.toString());
+ }
+}
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example_ChatWithVision.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example_ChatWithVision.java
new file mode 100644
index 00000000..2c1acbc9
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/Example_ChatWithVision.java
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples.chatcompletion;
+
+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.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
+import com.microsoft.semantickernel.implementation.CollectionUtil;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageImageContent;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class Example_ChatWithVision {
+
+ private static final String CLIENT_KEY = System.getenv("CLIENT_KEY");
+ private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY");
+
+ // Only required if AZURE_CLIENT_KEY is set
+ private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
+
+ // NOTE THAT vision is GPT4 only
+ private static final String MODEL_ID = System.getenv()
+ .getOrDefault("MODEL_ID", "gpt-4o");
+
+ public static void main(String[] args) throws MalformedURLException {
+ System.out.println("======== Open AI - Chat with Vision ========");
+
+ OpenAIAsyncClient client;
+
+ if (AZURE_CLIENT_KEY != null) {
+ client = new OpenAIClientBuilder()
+ .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
+ .endpoint(CLIENT_ENDPOINT)
+ .buildAsyncClient();
+
+ } else {
+ client = new OpenAIClientBuilder()
+ .credential(new KeyCredential(CLIENT_KEY))
+ .buildAsyncClient();
+ }
+
+ ChatCompletionService chatGPT = OpenAIChatCompletion.builder()
+ .withModelId(MODEL_ID)
+ .withOpenAIAsyncClient(client)
+ .build();
+
+ describeUrl(chatGPT);
+ describeImage(chatGPT);
+ }
+
+ private static void describeImage(ChatCompletionService chatGPT) throws MalformedURLException {
+
+ try (InputStream duke = Example_ChatWithVision.class.getResourceAsStream("duke.png")) {
+ byte[] image = duke.readAllBytes();
+
+ ChatHistory chatHistory = new ChatHistory(
+ "You look at images and answer questions about them");
+
+ // First user message
+ chatHistory.addUserMessage(
+ "This image is a cartoon drawing of the Java Duke character riding a dinosaur. What type of dinosaur is it?");
+ chatHistory.addMessage(
+ ChatMessageImageContent.builder()
+ .withImage("png", image)
+ .build());
+
+ var reply = chatGPT.getChatMessageContentsAsync(chatHistory, null, null);
+
+ String message = reply
+ .mapNotNull(CollectionUtil::getLastOrNull)
+ .map(ChatMessageContent::getContent)
+ .block();
+
+ System.out.println("\n------------------------");
+ System.out.print(message);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void describeUrl(ChatCompletionService chatGPT) throws MalformedURLException {
+ ChatHistory chatHistory = new ChatHistory("You look at images and describe them");
+
+ // First user message
+ chatHistory.addUserMessage("Describe the following image");
+ chatHistory.addMessage(
+ ChatMessageImageContent.builder()
+ .withImageUrl(new URL("https://cr.openjdk.org/~jeff/Duke/jpg/Welcome.jpg"))
+ .build());
+
+ var reply = chatGPT.getChatMessageContentsAsync(chatHistory, null, null);
+
+ String message = reply
+ .mapNotNull(CollectionUtil::getLastOrNull)
+ .map(ChatMessageContent::getContent)
+ .block();
+
+ System.out.println("\n------------------------");
+ System.out.print(message);
+ }
+
+}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example08_RetryHandler.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example08_RetryHandler.java
similarity index 84%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example08_RetryHandler.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example08_RetryHandler.java
index 37a490e6..508d3db4 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example08_RetryHandler.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example08_RetryHandler.java
@@ -7,16 +7,18 @@
import com.azure.core.http.policy.ExponentialBackoffOptions;
import com.azure.core.http.policy.RetryOptions;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
import java.time.Duration;
public class Example08_RetryHandler {
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
public static void main(String[] args) throws ConfigurationException {
// Create a Kernel with the HttpClient
@@ -31,13 +33,13 @@ public static void main(String[] args) throws ConfigurationException {
.credential(new AzureKeyCredential("BAD KEY"))
.buildAsyncClient();
- TextGenerationService textGenerationService = TextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
Kernel kernel = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.build();
String question = "How popular is the Polly library?";
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example26_AADAuth.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example26_AADAuth.java
similarity index 91%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example26_AADAuth.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example26_AADAuth.java
index 34662657..5e885795 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example26_AADAuth.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example26_AADAuth.java
@@ -6,6 +6,7 @@
import com.azure.identity.DeviceCodeCredential;
import com.azure.identity.DeviceCodeCredentialBuilder;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
@@ -26,7 +27,7 @@ public static void main(String[] args) throws ConfigurationException {
.endpoint(CLIENT_ENDPOINT)
.buildAsyncClient();
- ChatCompletionService chatService = ChatCompletionService.builder()
+ ChatCompletionService chatService = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example41_HttpClientUsage.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example41_HttpClientUsage.java
similarity index 84%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example41_HttpClientUsage.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example41_HttpClientUsage.java
index bc7c218c..763f0a6c 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example41_HttpClientUsage.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example41_HttpClientUsage.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.http.HttpClient;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
@@ -27,7 +28,7 @@ private static void useDefaultHttpClient() {
var kernel = Kernel.builder()
.withAIService(ChatCompletionService.class,
- ChatCompletionService.builder()
+ OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId("gpt-35-turbo-2")
.build())
@@ -46,13 +47,13 @@ private static void useCustomHttpClient() {
.credential(new AzureKeyCredential("BAD KEY"))
.buildAsyncClient();
- TextGenerationService textGenerationService = TextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
- .withModelId("text-davinci-003")
+ .withModelId("gpt-35-turbo")
.build();
Kernel kernel = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.build();
}
}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example58_ConfigureExecutionSettings.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example58_ConfigureExecutionSettings.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example58_ConfigureExecutionSettings.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/configuration/Example58_ConfigureExecutionSettings.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example01_NativeFunctions.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example01_NativeFunctions.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example01_NativeFunctions.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example01_NativeFunctions.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example03_Arguments.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java
similarity index 91%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java
index 7aa6e18b..7ecf9a0d 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example05_InlineFunctionDefinition.java
@@ -6,12 +6,14 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
import java.time.Instant;
import java.time.ZoneOffset;
@@ -25,7 +27,7 @@ public class Example05_InlineFunctionDefinition {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
public static void main(String[] args) throws ConfigurationException {
@@ -42,13 +44,13 @@ public static void main(String[] args) throws ConfigurationException {
.buildAsyncClient();
}
- TextGenerationService textGenerationService = TextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
Kernel kernel = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.build();
System.out.println("======== Inline Function Definition ========");
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java
similarity index 98%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java
index b10900d1..c6c1fdff 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example09_FunctionTypes.java
@@ -8,6 +8,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService;
import com.microsoft.semantickernel.contextvariables.ContextVariable;
import com.microsoft.semantickernel.contextvariables.ContextVariableType;
@@ -19,6 +20,7 @@
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
import java.nio.file.Path;
import java.time.Instant;
@@ -42,7 +44,7 @@ public class Example09_FunctionTypes {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
public static void main(String[] args) throws InterruptedException {
@@ -61,7 +63,7 @@ public static void main(String[] args) throws InterruptedException {
.buildAsyncClient();
}
- TextGenerationService textGenerationService = OpenAITextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
@@ -73,7 +75,7 @@ public static void main(String[] args) throws InterruptedException {
KernelPlugin summarize = KernelPluginFactory
.importPluginFromDirectory(
Path.of(PLUGIN_DIR,
- "java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins"),
+ "samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins"),
"SummarizePlugin",
null);
@@ -86,7 +88,7 @@ public static void main(String[] args) throws InterruptedException {
Example09_FunctionTypes.class);
Kernel kernel = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.withPlugin(plugin)
.withPlugin(summarize)
.withPlugin(examplePlugin)
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java
similarity index 93%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java
index 0dae3c7e..f72ec237 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example27_PromptFunctionsUsingChatGPT.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
@@ -38,7 +39,7 @@ public static void main(String[] args) {
}
System.out.println("======== Using Chat GPT model for text generation ========");
- ChatCompletionService openAIChatCompletion = ChatCompletionService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example59_OpenAIFunctionCalling.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example60_AdvancedMethodFunctions.java
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java
new file mode 100644
index 00000000..0dd425f6
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/functions/Example98_GeminiFunctionCalling.java
@@ -0,0 +1,169 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples.functions;
+
+import com.google.cloud.vertexai.VertexAI;
+import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.google.chatcompletion.GeminiChatCompletion;
+import com.microsoft.semantickernel.aiservices.google.chatcompletion.GeminiChatMessageContent;
+import com.microsoft.semantickernel.aiservices.google.chatcompletion.GeminiFunctionCall;
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
+import com.microsoft.semantickernel.orchestration.FunctionResult;
+import com.microsoft.semantickernel.orchestration.InvocationContext;
+import com.microsoft.semantickernel.orchestration.InvocationReturnMode;
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
+import com.microsoft.semantickernel.plugin.KernelPluginFactory;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
+import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
+import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
+import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Example98_GeminiFunctionCalling {
+ private static final String PROJECT_ID = System.getenv("PROJECT_ID");
+ private static final String LOCATION = System.getenv("LOCATION");
+ private static final String MODEL_ID = System.getenv("GEMINI_MODEL_ID");
+
+ // Define functions that can be called by the model
+ public static class HelperFunctions {
+
+ @DefineKernelFunction(name = "currentUtcTime", description = "Retrieves the current time in UTC.")
+ public String currentUtcTime() {
+ return ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME);
+ }
+
+ @DefineKernelFunction(name = "getWeatherForCity", description = "Gets the current weather for the specified city")
+ public String getWeatherForCity(
+ @KernelFunctionParameter(name = "cityName", description = "Name of the city") String cityName) {
+ switch (cityName) {
+ case "Thrapston":
+ return "80 and sunny";
+ case "Boston":
+ return "61 and rainy";
+ case "London":
+ return "55 and cloudy";
+ case "Miami":
+ return "80 and sunny";
+ case "Paris":
+ return "60 and rainy";
+ case "Tokyo":
+ return "50 and sunny";
+ case "Sydney":
+ return "75 and sunny";
+ case "Tel Aviv":
+ return "80 and sunny";
+ default:
+ return "31 and snowing";
+ }
+ }
+
+ public static void main(String[] args) throws NoSuchMethodException {
+ System.out.println("======== Gemini - Function calling ========");
+
+ VertexAI client = new VertexAI(PROJECT_ID, LOCATION);
+
+ ChatCompletionService chat = GeminiChatCompletion.builder()
+ .withModelId(MODEL_ID)
+ .withVertexAIClient(client)
+ .build();
+
+ var plugin = KernelPluginFactory.createFromObject(new HelperFunctions(),
+ "HelperFunctions");
+
+ var kernel = Kernel.builder()
+ .withAIService(ChatCompletionService.class, chat)
+ .withPlugin(plugin)
+ .build();
+
+ System.out.println("======== Example 1: Use automated function calling ========");
+
+ var function = KernelFunctionFromPrompt.builder()
+ .withTemplate(
+ "Given the current time of day and weather, what is the likely color of the sky in Boston?")
+ .withDefaultExecutionSettings(
+ PromptExecutionSettings.builder()
+ .withTemperature(0.4)
+ .withTopP(1)
+ .withMaxTokens(100)
+ .build())
+ .build();
+
+ var result = kernel
+ .invokeAsync(function)
+ .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true))
+ .withResultType(ContextVariableTypes.getGlobalVariableTypeForClass(String.class))
+ .block();
+
+ System.out.println(result.getResult());
+
+ System.out.println("======== Example 2: Use manual function calling ========");
+
+ var chatHistory = new ChatHistory();
+ chatHistory.addUserMessage(
+ "Given the current time of day and weather, what is the likely color of the sky in Boston?");
+
+ while (true) {
+ var message = (GeminiChatMessageContent>) chat.getChatMessageContentsAsync(
+ chatHistory,
+ kernel,
+ InvocationContext.builder()
+ .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(false))
+ .withReturnMode(InvocationReturnMode.LAST_MESSAGE_ONLY)
+ .build())
+ .block().get(0);
+
+ // Add the assistant's response to the chat history
+ chatHistory.addMessage(message);
+ if (message.getContent() != null && !message.getContent().isEmpty()) {
+ System.out.println(message.getContent());
+ }
+
+ // Process the functions calls or break if there are no more functions to call
+ if (message.getGeminiFunctionCalls().isEmpty()) {
+ break;
+ }
+
+ List functionResponses = new ArrayList<>();
+ for (var geminiFunction : message.getGeminiFunctionCalls()) {
+
+ String content = null;
+ try {
+ // getFunction will throw an exception if the function is not found
+ var fn = kernel.getFunction(geminiFunction.getPluginName(),
+ geminiFunction.getFunctionName());
+
+ var arguments = KernelFunctionArguments.builder();
+ geminiFunction.getFunctionCall().getArgs().getFieldsMap()
+ .forEach((key, value) -> {
+ arguments.withVariable(key, value.getStringValue());
+ });
+
+ // Invoke the function and add the result to the list of function responses
+ FunctionResult> functionResult = fn
+ .invokeAsync(kernel, arguments.build(), null, null).block();
+
+ functionResponses.add(new GeminiFunctionCall(
+ geminiFunction.getFunctionCall(), functionResult));
+ } catch (IllegalArgumentException e) {
+ content = "Unable to find function. Please try again!";
+ }
+ }
+
+ // Add the function responses to the chat history
+ ChatMessageContent> functionResponsesMessage = new GeminiChatMessageContent<>(
+ AuthorRole.USER,
+ "", null, null, null, null, functionResponses);
+
+ chatHistory.addMessage(functionResponsesMessage);
+ }
+ }
+ }
+}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsHandlebars_Example.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java
similarity index 89%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java
index 4b0cb3c7..ceb9983e 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/FunctionsWithinPrompts_Example.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
import com.microsoft.semantickernel.plugin.KernelPlugin;
@@ -13,10 +14,9 @@
import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionFromPrompt;
-import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
-import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import com.microsoft.semantickernel.services.chatcompletion.message.ChatMessageTextContent;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
@@ -51,7 +51,7 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio
.buildAsyncClient();
}
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
@@ -70,18 +70,16 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio
List fewShotExamples = Arrays.asList(
new ChatHistory(
Arrays.asList(
- new ChatMessageContent(AuthorRole.USER,
+ ChatMessageTextContent.userMessage(
"Can you send a very quick approval to the marketing team?"),
- new ChatMessageContent(AuthorRole.SYSTEM, "Intent:"),
- new ChatMessageContent(AuthorRole.ASSISTANT,
- "ContinueConversation"))),
+ ChatMessageTextContent.systemMessage("Intent:"),
+ ChatMessageTextContent.assistantMessage("ContinueConversation"))),
new ChatHistory(
Arrays.asList(
- new ChatMessageContent(AuthorRole.USER,
- "Thats all"),
- new ChatMessageContent(AuthorRole.SYSTEM, "Intent:"),
- new ChatMessageContent(AuthorRole.ASSISTANT, "EndConversation"))));
+ ChatMessageTextContent.userMessage("Thats all"),
+ ChatMessageTextContent.systemMessage("Intent:"),
+ ChatMessageTextContent.assistantMessage("EndConversation"))));
// Create handlebars template for intent
//
@@ -135,12 +133,12 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio
/*
* Renders to:
- *
+ *
* Instructions: What is the intent of this request?
* Do not explain the reasoning, just reply back with the intent. If you are unsure,
* reply with .
* Choices: ContinueConversation,EndConversation.
- *
+ *
* Can you send a very quick approval to the marketing
* team?
* Intent:
@@ -148,7 +146,7 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio
* Can you send the full update to the marketing team?
* Intent:
* EndConversation
- *
+ *
* Can you send an approval to the marketing team?
* Intent:
*/
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java
similarity index 89%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java
index 05e12e10..900513c8 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/java/KernelFunctionYaml_Example.java
@@ -7,12 +7,14 @@
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.Kernel.Builder;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.implementation.EmbeddedResourceLoader;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionYaml;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
import java.io.IOException;
@@ -24,7 +26,7 @@ public class KernelFunctionYaml_Example {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
public static void main(String[] args) throws ConfigurationException, IOException {
@@ -41,13 +43,13 @@ public static void main(String[] args) throws ConfigurationException, IOExceptio
.buildAsyncClient();
}
- TextGenerationService textGenerationService = TextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
Builder kernelBuilder = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService);
+ .withAIService(ChatCompletionService.class, openAIChatCompletion);
semanticKernelTemplate(kernelBuilder.build());
handlebarsTemplate(kernelBuilder.build());
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/AzureAISearch_DataStorage.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/AzureAISearch_DataStorage.java
new file mode 100644
index 00000000..92316385
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/AzureAISearch_DataStorage.java
@@ -0,0 +1,188 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples.memory;
+
+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.azure.core.util.MetricsOptions;
+import com.azure.core.util.TracingOptions;
+import com.azure.search.documents.indexes.SearchIndexAsyncClient;
+import com.azure.search.documents.indexes.SearchIndexClientBuilder;
+import com.microsoft.semantickernel.aiservices.openai.textembedding.OpenAITextEmbeddingGenerationService;
+import com.microsoft.semantickernel.connectors.data.azureaisearch.AzureAISearchVectorStore;
+import com.microsoft.semantickernel.connectors.data.azureaisearch.AzureAISearchVectorStoreOptions;
+import com.microsoft.semantickernel.connectors.data.azureaisearch.AzureAISearchVectorStoreRecordCollection;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordDataAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordKeyAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordVectorAttribute;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class AzureAISearch_DataStorage {
+ private static final String CLIENT_KEY = System.getenv("CLIENT_KEY");
+ private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY");
+
+ // Only required if AZURE_CLIENT_KEY is set
+ private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
+
+ //////////////////////////////////////////////////////////////
+ // Azure AI Search configuration
+ //////////////////////////////////////////////////////////////
+ private static final String AZURE_AI_SEARCH_ENDPOINT = System.getenv("AZURE_AISEARCH_ENDPOINT");
+ private static final String AZURE_AISEARCH_KEY = System.getenv("AZURE_AISEARCH_KEY");
+ private static final String MODEL_ID = System.getenv()
+ .getOrDefault("EMBEDDING_MODEL_ID", "text-embedding-3-large");
+ private static final int EMBEDDING_DIMENSIONS = 1536;
+
+ static class GitHubFile {
+ @VectorStoreRecordKeyAttribute()
+ private final String id;
+ @VectorStoreRecordDataAttribute(hasEmbedding = true, embeddingFieldName = "embedding")
+ private final String description;
+ @VectorStoreRecordDataAttribute
+ private final String link;
+ @VectorStoreRecordVectorAttribute(dimensions = EMBEDDING_DIMENSIONS, indexKind = "Hnsw")
+ private final List embedding;
+
+ public GitHubFile() {
+ this(null, null, null, Collections.emptyList());
+ }
+
+ public GitHubFile(
+ String id,
+ String description,
+ String link,
+ List embedding) {
+ this.id = id;
+ this.description = description;
+ this.link = link;
+ this.embedding = embedding;
+ }
+
+ static String encodeId(String realId) {
+ byte[] bytes = Base64.getUrlEncoder().encode(realId.getBytes(StandardCharsets.UTF_8));
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println("==============================================================");
+ System.out.println("========== Azure AI Search Vector Store Example ==============");
+ System.out.println("==============================================================");
+
+ OpenAIAsyncClient client;
+
+ if (AZURE_CLIENT_KEY != null) {
+ client = new OpenAIClientBuilder()
+ .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
+ .endpoint(CLIENT_ENDPOINT)
+ .buildAsyncClient();
+
+ } else {
+ client = new OpenAIClientBuilder()
+ .credential(new KeyCredential(CLIENT_KEY))
+ .buildAsyncClient();
+ }
+
+ var embeddingGeneration = OpenAITextEmbeddingGenerationService.builder()
+ .withOpenAIAsyncClient(client)
+ .withModelId(MODEL_ID)
+ .withDimensions(EMBEDDING_DIMENSIONS)
+ .build();
+
+ var searchClient = new SearchIndexClientBuilder()
+ .endpoint(AZURE_AI_SEARCH_ENDPOINT)
+ .credential(new AzureKeyCredential(AZURE_AISEARCH_KEY))
+ .clientOptions(clientOptions())
+ .buildAsyncClient();
+
+ dataStorageWithAzureAISearch(searchClient, embeddingGeneration);
+ }
+
+ public static void dataStorageWithAzureAISearch(
+ SearchIndexAsyncClient searchClient,
+ OpenAITextEmbeddingGenerationService embeddingGeneration) {
+
+ // Create a new Azure AI Search vector store
+ var azureAISearchVectorStore = AzureAISearchVectorStore.builder()
+ .withClient(searchClient)
+ .withOptions(new AzureAISearchVectorStoreOptions())
+ .build();
+
+ String collectionName = "skgithubfiles";
+ var collection = azureAISearchVectorStore.getCollection(collectionName, GitHubFile.class,
+ null);
+
+ // Create collection if it does not exist and store data
+ collection
+ .createCollectionIfNotExistsAsync()
+ .then(storeData(collection, embeddingGeneration, sampleData()))
+ .block();
+
+ // Query the Azure AI Search client for results
+ // This might take a few seconds to return the best result
+ var result = searchClient.getSearchAsyncClient(collectionName)
+ .search("How to get started with the Semantic Kernel?")
+ .blockFirst();
+
+ GitHubFile gitHubFile = result.getDocument(GitHubFile.class);
+ System.out.println("Best result: " + gitHubFile.description + ". Link: " + gitHubFile.link);
+ }
+
+ private static Mono> storeData(
+ AzureAISearchVectorStoreRecordCollection recordStore,
+ OpenAITextEmbeddingGenerationService embeddingGeneration,
+ Map data) {
+
+ return Flux.fromIterable(data.entrySet())
+ .flatMap(entry -> {
+ System.out.println("Save '" + entry.getKey() + "' to memory.");
+
+ return embeddingGeneration
+ .generateEmbeddingsAsync(Collections.singletonList(entry.getValue()))
+ .flatMap(embeddings -> {
+ GitHubFile gitHubFile = new GitHubFile(
+ GitHubFile.encodeId(entry.getKey()),
+ entry.getValue(),
+ entry.getKey(),
+ embeddings.get(0).getVector());
+ return recordStore.upsertAsync(gitHubFile, null);
+ });
+ })
+ .collectList();
+ }
+
+ private static Map sampleData() {
+ return Arrays.stream(new String[][] {
+ { "https://github.com/microsoft/semantic-kernel/blob/main/README.md",
+ "README: Installation, getting started with Semantic Kernel, 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/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]));
+ }
+
+ private static ClientOptions clientOptions() {
+ return new ClientOptions()
+ .setTracingOptions(new TracingOptions())
+ .setMetricsOptions(new MetricsOptions())
+ .setApplicationId("Semantic-Kernel");
+ }
+}
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/InMemory_DataStorage.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/InMemory_DataStorage.java
new file mode 100644
index 00000000..b189081b
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/InMemory_DataStorage.java
@@ -0,0 +1,166 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples.memory;
+
+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.azure.core.util.MetricsOptions;
+import com.azure.core.util.TracingOptions;
+import com.azure.search.documents.indexes.SearchIndexAsyncClient;
+import com.azure.search.documents.indexes.SearchIndexClientBuilder;
+import com.microsoft.semantickernel.aiservices.openai.textembedding.OpenAITextEmbeddingGenerationService;
+import com.microsoft.semantickernel.connectors.data.azureaisearch.AzureAISearchVectorStore;
+import com.microsoft.semantickernel.connectors.data.azureaisearch.AzureAISearchVectorStoreOptions;
+import com.microsoft.semantickernel.connectors.data.azureaisearch.AzureAISearchVectorStoreRecordCollection;
+import com.microsoft.semantickernel.data.VolatileVectorStore;
+import com.microsoft.semantickernel.data.VolatileVectorStoreRecordCollection;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordDataAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordKeyAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordVectorAttribute;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class InMemory_DataStorage {
+ private static final String CLIENT_KEY = System.getenv("CLIENT_KEY");
+ private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY");
+
+ // Only required if AZURE_CLIENT_KEY is set
+ private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
+
+ // Embedding model configuration
+ private static final String MODEL_ID = System.getenv()
+ .getOrDefault("EMBEDDING_MODEL_ID", "text-embedding-3-large");
+ private static final int EMBEDDING_DIMENSIONS = 1536;
+
+ static class GitHubFile {
+ @VectorStoreRecordKeyAttribute()
+ private final String id;
+ @VectorStoreRecordDataAttribute(hasEmbedding = true, embeddingFieldName = "embedding")
+ private final String description;
+ @VectorStoreRecordDataAttribute
+ private final String link;
+ @VectorStoreRecordVectorAttribute(dimensions = EMBEDDING_DIMENSIONS, indexKind = "Hnsw")
+ private final List embedding;
+
+ public GitHubFile(
+ String id,
+ String description,
+ String link,
+ List embedding) {
+ this.id = id;
+ this.description = description;
+ this.link = link;
+ this.embedding = embedding;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ static String encodeId(String realId) {
+ byte[] bytes = Base64.getUrlEncoder().encode(realId.getBytes(StandardCharsets.UTF_8));
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println("===================================================================");
+ System.out.println("========== Volatile (In memory) Vector Store Example ==============");
+ System.out.println("===================================================================");
+
+ OpenAIAsyncClient client;
+
+ if (AZURE_CLIENT_KEY != null) {
+ client = new OpenAIClientBuilder()
+ .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
+ .endpoint(CLIENT_ENDPOINT)
+ .buildAsyncClient();
+
+ } else {
+ client = new OpenAIClientBuilder()
+ .credential(new KeyCredential(CLIENT_KEY))
+ .buildAsyncClient();
+ }
+
+ var embeddingGeneration = OpenAITextEmbeddingGenerationService.builder()
+ .withOpenAIAsyncClient(client)
+ .withModelId(MODEL_ID)
+ .withDimensions(EMBEDDING_DIMENSIONS)
+ .build();
+
+ inMemoryDataStorage(embeddingGeneration);
+ }
+
+ public static void inMemoryDataStorage(OpenAITextEmbeddingGenerationService embeddingGeneration) {
+ // Create a new Volatile vector store
+ var volatileVectorStore = new VolatileVectorStore();
+
+ String collectionName = "skgithubfiles";
+ var collection = volatileVectorStore.getCollection(collectionName, GitHubFile.class, null);
+
+ // Create collection if it does not exist and store data
+ List ids = collection
+ .createCollectionIfNotExistsAsync()
+ .then(storeData(collection, embeddingGeneration, sampleData()))
+ .block();
+
+ // Retrieve all records from the collection
+ List data = collection.getBatchAsync(ids, null).block();
+
+ data.forEach(gitHubFile -> System.out.println("Retrieved: " + gitHubFile.getDescription()));
+ }
+
+ private static Mono> storeData(
+ VolatileVectorStoreRecordCollection recordCollection,
+ OpenAITextEmbeddingGenerationService embeddingGeneration,
+ Map data) {
+
+ return Flux.fromIterable(data.entrySet())
+ .flatMap(entry -> {
+ System.out.println("Save '" + entry.getKey() + "' to memory.");
+
+ return embeddingGeneration
+ .generateEmbeddingsAsync(Collections.singletonList(entry.getValue()))
+ .flatMap(embeddings -> {
+ GitHubFile gitHubFile = new GitHubFile(
+ GitHubFile.encodeId(entry.getKey()),
+ entry.getValue(),
+ entry.getKey(),
+ embeddings.get(0).getVector());
+ return recordCollection.upsertAsync(gitHubFile, null);
+ });
+ })
+ .collectList();
+ }
+
+ private static Map sampleData() {
+ return Arrays.stream(new String[][] {
+ { "https://github.com/microsoft/semantic-kernel/blob/main/README.md",
+ "README: Installation, getting started with Semantic Kernel, 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/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/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/Redis_DataStorage.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/Redis_DataStorage.java
new file mode 100644
index 00000000..cde31a3a
--- /dev/null
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/memory/Redis_DataStorage.java
@@ -0,0 +1,186 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.samples.syntaxexamples.memory;
+
+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.azure.core.util.MetricsOptions;
+import com.azure.core.util.TracingOptions;
+import com.microsoft.semantickernel.aiservices.openai.textembedding.OpenAITextEmbeddingGenerationService;
+import com.microsoft.semantickernel.connectors.data.redis.RedisVectorStore;
+import com.microsoft.semantickernel.connectors.data.redis.RedisVectorStoreOptions;
+import com.microsoft.semantickernel.data.VectorStoreRecordCollection;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordDataAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordKeyAttribute;
+import com.microsoft.semantickernel.data.recordattributes.VectorStoreRecordVectorAttribute;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import redis.clients.jedis.JedisPooled;
+
+public class Redis_DataStorage {
+
+ private static final String CLIENT_KEY = System.getenv("CLIENT_KEY");
+ private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY");
+
+ // Only required if AZURE_CLIENT_KEY is set
+ private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
+
+ private static final String MODEL_ID = System.getenv()
+ .getOrDefault("EMBEDDING_MODEL_ID", "text-embedding-3-large");
+ private static final int EMBEDDING_DIMENSIONS = 1536;
+
+ // Can start a test server with:
+ // docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
+ private static final String REDIS_URL = "redis://127.0.0.1:6379";
+
+ public static class GitHubFile {
+
+ @VectorStoreRecordKeyAttribute()
+ private final String id;
+ @VectorStoreRecordDataAttribute(hasEmbedding = true, embeddingFieldName = "embedding")
+ private final String description;
+ @VectorStoreRecordDataAttribute
+ private final String link;
+ @VectorStoreRecordVectorAttribute(dimensions = EMBEDDING_DIMENSIONS, indexKind = "Hnsw")
+ private final List embedding;
+
+ public GitHubFile() {
+ this(null, null, null, Collections.emptyList());
+ }
+
+ public GitHubFile(
+ String id,
+ String description,
+ String link,
+ List embedding) {
+ this.id = id;
+ this.description = description;
+ this.link = link;
+ this.embedding = embedding;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ static String encodeId(String realId) {
+ byte[] bytes = Base64.getUrlEncoder().encode(realId.getBytes(StandardCharsets.UTF_8));
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println("==============================================================");
+ System.out.println("========== Redis Vector Store Example ==============");
+ System.out.println("==============================================================");
+
+ OpenAIAsyncClient client;
+
+ if (AZURE_CLIENT_KEY != null) {
+ client = new OpenAIClientBuilder()
+ .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
+ .endpoint(CLIENT_ENDPOINT)
+ .buildAsyncClient();
+
+ } else {
+ client = new OpenAIClientBuilder()
+ .credential(new KeyCredential(CLIENT_KEY))
+ .buildAsyncClient();
+ }
+
+ var embeddingGeneration = OpenAITextEmbeddingGenerationService.builder()
+ .withOpenAIAsyncClient(client)
+ .withModelId(MODEL_ID)
+ .withDimensions(EMBEDDING_DIMENSIONS)
+ .build();
+
+ dataStorageWithRedis(embeddingGeneration);
+ }
+
+ public static void dataStorageWithRedis(
+ OpenAITextEmbeddingGenerationService embeddingGeneration) {
+
+ JedisPooled jedis = new JedisPooled(REDIS_URL);
+
+ RedisVectorStore vectorStore = RedisVectorStore.builder()
+ .withClient(jedis)
+ .withOptions(new RedisVectorStoreOptions())
+ .build();
+
+ String collectionName = "skgithubfiles";
+ var collection = vectorStore.getCollection(collectionName, GitHubFile.class, null);
+
+ // Create collection if it does not exist and store data
+ List ids = collection
+ .createCollectionIfNotExistsAsync()
+ .then(storeData(collection, embeddingGeneration, sampleData()))
+ .block();
+
+ List data = collection.getBatchAsync(ids, null).block();
+
+ data.forEach(gitHubFile -> System.out.println("Retrieved: " + gitHubFile.getDescription()));
+
+ // TODO: Implement search functionality using Redis.
+
+ }
+
+ private static Mono> storeData(
+ VectorStoreRecordCollection recordStore,
+ OpenAITextEmbeddingGenerationService embeddingGeneration,
+ Map data) {
+
+ return Flux.fromIterable(data.entrySet())
+ .flatMap(entry -> {
+ System.out.println("Save '" + entry.getKey() + "' to memory.");
+
+ return embeddingGeneration
+ .generateEmbeddingsAsync(Collections.singletonList(entry.getValue()))
+ .flatMap(embeddings -> {
+ GitHubFile gitHubFile = new GitHubFile(
+ GitHubFile.encodeId(entry.getKey()),
+ entry.getValue(),
+ entry.getKey(),
+ embeddings.get(0).getVector());
+ return recordStore.upsertAsync(gitHubFile, null);
+ });
+ })
+ .collectList();
+ }
+
+ private static Map sampleData() {
+ return Arrays.stream(new String[][] {
+ { "https://github.com/microsoft/semantic-kernel/blob/main/README.md",
+ "README: Installation, getting started with Semantic Kernel, 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/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]));
+ }
+
+ private static ClientOptions clientOptions() {
+ return new ClientOptions()
+ .setTracingOptions(new TracingOptions())
+ .setMetricsOptions(new MetricsOptions())
+ .setApplicationId("Semantic-Kernel");
+ }
+}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example07_BingAndGooglePlugins.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example07_BingAndGooglePlugins.java
similarity index 98%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example07_BingAndGooglePlugins.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example07_BingAndGooglePlugins.java
index 6db7deb7..70a8ef28 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example07_BingAndGooglePlugins.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example07_BingAndGooglePlugins.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.samples.connectors.web.bing.BingConnector;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
@@ -59,7 +60,7 @@ public static void main(String[] args) {
var bing = KernelPluginFactory.createFromObject(new WebSearchEnginePlugin(bingConnector),
"bing");
- var chatCompletionService = ChatCompletionService.builder()
+ var chatCompletionService = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example10_DescribeAllPluginsAndFunctions.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example10_DescribeAllPluginsAndFunctions.java
similarity index 92%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example10_DescribeAllPluginsAndFunctions.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example10_DescribeAllPluginsAndFunctions.java
index 6bc59774..1205b335 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example10_DescribeAllPluginsAndFunctions.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example10_DescribeAllPluginsAndFunctions.java
@@ -10,6 +10,7 @@
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.Kernel.Builder;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
@@ -19,6 +20,7 @@
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionMetadata;
import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
public class Example10_DescribeAllPluginsAndFunctions {
@@ -31,7 +33,7 @@ public class Example10_DescribeAllPluginsAndFunctions {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
///
/// Print a list of all the functions imported into the kernel, including function descriptions,
@@ -53,13 +55,13 @@ public static void main(String[] args) {
.buildAsyncClient();
}
- TextGenerationService textGenerationService = OpenAITextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
Builder kernelBuilder = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService);
+ .withAIService(ChatCompletionService.class, openAIChatCompletion);
kernelBuilder.withPlugin(
KernelPluginFactory.createFromObject(
@@ -74,7 +76,7 @@ public static void main(String[] args) {
KernelPluginFactory
.importPluginFromDirectory(
Path.of(PLUGIN_DIR,
- "java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins"),
+ "samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins"),
"SummarizePlugin",
null));
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example13_ConversationSummaryPlugin.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example13_ConversationSummaryPlugin.java
similarity index 95%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example13_ConversationSummaryPlugin.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example13_ConversationSummaryPlugin.java
index eeff25c8..9cdafbb7 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example13_ConversationSummaryPlugin.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/plugins/Example13_ConversationSummaryPlugin.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.FunctionResult;
@@ -13,6 +14,7 @@
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin;
import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments.Builder;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
import reactor.core.publisher.Mono;
@@ -21,7 +23,7 @@
* plugin.
*
* Refer to the
+ * "https://github.com/microsoft/semantic-kernel-java/blob/main/samples/semantickernel-concepts/semantickernel-syntax-examples/README.md">
* README for configuring your environment to run the examples.
*/
public class Example13_ConversationSummaryPlugin {
@@ -32,7 +34,7 @@ public class Example13_ConversationSummaryPlugin {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
private static final String chatTranscript = """
John: Hello, how are you?
@@ -225,13 +227,13 @@ private static Kernel initializeKernel() {
.buildAsyncClient();
}
- TextGenerationService textGenerationService = OpenAITextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
return Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.build();
}
}
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example06_TemplateLanguage.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example06_TemplateLanguage.java
similarity index 91%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example06_TemplateLanguage.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example06_TemplateLanguage.java
index 86e61d51..698a2e1b 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example06_TemplateLanguage.java
+++ b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example06_TemplateLanguage.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.aiservices.openai.textcompletion.OpenAITextGenerationService;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
@@ -15,6 +16,7 @@
import com.microsoft.semantickernel.semanticfunctions.KernelPromptTemplateFactory;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
public class Example06_TemplateLanguage {
@@ -25,7 +27,7 @@ public class Example06_TemplateLanguage {
// Only required if AZURE_CLIENT_KEY is set
private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
private static final String MODEL_ID = System.getenv()
- .getOrDefault("MODEL_ID", "text-davinci-003");
+ .getOrDefault("MODEL_ID", "gpt-35-turbo");
public static void main(String[] args) throws ConfigurationException {
@@ -44,13 +46,13 @@ public static void main(String[] args) throws ConfigurationException {
.buildAsyncClient();
}
- TextGenerationService textGenerationService = OpenAITextGenerationService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
Kernel kernel = Kernel.builder()
- .withAIService(TextGenerationService.class, textGenerationService)
+ .withAIService(ChatCompletionService.class, openAIChatCompletion)
.build();
// Load native plugin into the kernel function collection, sharing its functions with prompt templates
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example56_TemplateMethodFunctionsWithMultipleArguments.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/template/Example64_MultiplePromptTemplates.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/util/LocaleParser.java b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/util/LocaleParser.java
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/util/LocaleParser.java
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/java/com/microsoft/semantickernel/samples/util/LocaleParser.java
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionWithService/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/Chat/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/MakeAbstractReadable/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Notegen/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Summarize/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/SummarizePlugin/Topics/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/Plugins/WriterPlugin/ShortPoem/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-system-prompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-system-prompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-system-prompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-system-prompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-context.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-context.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-context.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-context.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-prompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-prompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-prompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/30-user-prompt.txt
diff --git a/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/duke.png b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/duke.png
new file mode 100644
index 00000000..31793b08
Binary files /dev/null and b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/chatcompletion/duke.png differ
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStory.yaml b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStory.yaml
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStory.yaml
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStory.yaml
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStoryHandlebars.yaml b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStoryHandlebars.yaml
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStoryHandlebars.yaml
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/java/GenerateStoryHandlebars.yaml
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/log4j2.xml b/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/log4j2.xml
similarity index 100%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/log4j2.xml
rename to samples/semantickernel-concepts/semantickernel-syntax-examples/src/main/resources/log4j2.xml
diff --git a/java/samples/semantickernel-demos/booking-agent-m365/pom.xml b/samples/semantickernel-demos/booking-agent-m365/pom.xml
similarity index 98%
rename from java/samples/semantickernel-demos/booking-agent-m365/pom.xml
rename to samples/semantickernel-demos/booking-agent-m365/pom.xml
index 2df9a709..c427bb4e 100644
--- a/java/samples/semantickernel-demos/booking-agent-m365/pom.xml
+++ b/samples/semantickernel-demos/booking-agent-m365/pom.xml
@@ -4,7 +4,7 @@
com.microsoft.semantic-kernelsemantickernel-demos
- 1.1.5
+ 1.2.0../pom.xml
diff --git a/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java b/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java
similarity index 100%
rename from java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java
rename to samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingAgent.java
diff --git a/java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java b/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java
similarity index 100%
rename from java/samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java
rename to samples/semantickernel-demos/booking-agent-m365/src/main/java/com/microsoft/semantickernel/BookingPlugin.java
diff --git a/java/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml b/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml
similarity index 100%
rename from java/samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml
rename to samples/semantickernel-demos/booking-agent-m365/src/main/resources/log4j2.xml
diff --git a/java/samples/semantickernel-demos/pom.xml b/samples/semantickernel-demos/pom.xml
similarity index 83%
rename from java/samples/semantickernel-demos/pom.xml
rename to samples/semantickernel-demos/pom.xml
index 15f02813..4ef911aa 100644
--- a/java/samples/semantickernel-demos/pom.xml
+++ b/samples/semantickernel-demos/pom.xml
@@ -4,16 +4,17 @@
com.microsoft.semantic-kernelsemantickernel-samples-parent
- 1.1.5
+ 1.2.0../pom.xmlsemantickernel-demos
- 1.1.5pomsemantic-kernel-demosbooking-agent-m365
+ semantickernel-spring-starter
+ sk-presidio-sample
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml b/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml
similarity index 70%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml
rename to samples/semantickernel-demos/semantickernel-spring-starter/pom.xml
index e3f462b7..acd56827 100644
--- a/java/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml
+++ b/samples/semantickernel-demos/semantickernel-spring-starter/pom.xml
@@ -1,19 +1,37 @@
-
+4.0.0com.microsoft.semantic-kernel
- samples
- 0.2.14-alpha-SNAPSHOT
+ semantickernel-demos
+ 1.2.0../pom.xmlsemantickernel-spring-starterSemantic Kernel Spring Boot Starter
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-bom
+ ${project.version}
+ pom
+ import
+
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-api
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-aiservices-openai
+
+
org.slf4jslf4j-api
@@ -40,21 +58,6 @@
spring-boot3.2.1
-
- com.azure
- azure-ai-openai
- 1.0.0-beta.7
-
-
- com.microsoft.semantic-kernel
- semantickernel-core
- test
-
-
- com.microsoft.semantic-kernel
- semantickernel-connectors-ai-openai
- test
- org.springframeworkspring-test
@@ -64,7 +67,7 @@
com.azureazure-identity
- 1.9.1
+ 1.12.2org.junit.jupiter
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/AzureOpenAIConnectionProperties.java b/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/AzureOpenAIConnectionProperties.java
similarity index 96%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/AzureOpenAIConnectionProperties.java
rename to samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/AzureOpenAIConnectionProperties.java
index cf23fc8b..643006f8 100644
--- a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/AzureOpenAIConnectionProperties.java
+++ b/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/AzureOpenAIConnectionProperties.java
@@ -1,3 +1,4 @@
+// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.starter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -29,14 +30,14 @@ public String getEndpoint() {
return endpoint;
}
- public String getKey() {
- return key;
- }
-
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
+ public String getKey() {
+ return key;
+ }
+
public void setKey(String key) {
this.key = key;
}
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/SemanticKernelAutoConfiguration.java b/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/SemanticKernelAutoConfiguration.java
similarity index 86%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/SemanticKernelAutoConfiguration.java
rename to samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/SemanticKernelAutoConfiguration.java
index df35c130..b1d66cc0 100644
--- a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/SemanticKernelAutoConfiguration.java
+++ b/samples/semantickernel-demos/semantickernel-spring-starter/src/main/java/com/microsoft/semantickernel/starter/SemanticKernelAutoConfiguration.java
@@ -1,10 +1,12 @@
+// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.starter;
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.aiservices.openai.textcompletion.OpenAITextGenerationService;
+import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -20,7 +22,21 @@
@EnableConfigurationProperties(AzureOpenAIConnectionProperties.class)
public class SemanticKernelAutoConfiguration {
- private static final Logger LOGGER = LoggerFactory.getLogger(SemanticKernelAutoConfiguration.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(
+ SemanticKernelAutoConfiguration.class);
+
+ private static String setModelID(AzureOpenAIConnectionProperties connectionProperties) {
+ String modelId;
+ if (connectionProperties.getDeploymentName() == null) {
+ modelId = "text-davinci-003";
+ LOGGER.warn(
+ "No deployment name specified, using default model id: " + modelId);
+ } else {
+ modelId = connectionProperties.getDeploymentName();
+ LOGGER.info("Using model id: " + modelId);
+ }
+ return modelId;
+ }
/**
* Creates a {@link OpenAIAsyncClient} with the endpoint and key specified in the
@@ -54,25 +70,12 @@ public OpenAIAsyncClient openAIAsyncClient(
@Bean
public Kernel semanticKernel(OpenAIAsyncClient client,
AzureOpenAIConnectionProperties connectionProperties) {
- return SKBuilders.kernel()
- .withDefaultAIService(
- SKBuilders.textCompletion()
+ return Kernel.builder()
+ .withAIService(TextGenerationService.class,
+ OpenAITextGenerationService.builder()
.withModelId(setModelID(connectionProperties))
- .withOpenAIClient(client)
+ .withOpenAIAsyncClient(client)
.build())
.build();
}
-
- private static String setModelID(AzureOpenAIConnectionProperties connectionProperties) {
- String modelId;
- if (connectionProperties.getDeploymentName() == null) {
- modelId = "text-davinci-003";
- LOGGER.warn(
- "No deployment name specified, using default model id: " + modelId);
- } else {
- modelId = connectionProperties.getDeploymentName();
- LOGGER.info("Using model id: " + modelId);
- }
- return modelId;
- }
}
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/resources/application.properties b/samples/semantickernel-demos/semantickernel-spring-starter/src/main/resources/application.properties
similarity index 100%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/src/main/resources/application.properties
rename to samples/semantickernel-demos/semantickernel-spring-starter/src/main/resources/application.properties
diff --git a/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/AzureOpenAIConnectionPropertiesTest.java b/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/AzureOpenAIConnectionPropertiesTest.java
new file mode 100644
index 00000000..56fd962a
--- /dev/null
+++ b/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/AzureOpenAIConnectionPropertiesTest.java
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.azureopenai;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.microsoft.semantickernel.starter.AzureOpenAIConnectionProperties;
+import com.microsoft.semantickernel.starter.SemanticKernelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.test.context.ActiveProfiles;
+
+@ActiveProfiles("test")
+public class AzureOpenAIConnectionPropertiesTest {
+
+ ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withPropertyValues(
+ // @formatter:off
+ "client.azureopenai.key=TEST_KEY",
+ "client.azureopenai.endpoint=TEST_ENDPOINT",
+ "client.azureopenai.deploymentname=TEST_DEPLOYMENT_NAME"
+
+ // @formatter:on
+ )
+ .withConfiguration(
+ AutoConfigurations.of(SemanticKernelAutoConfiguration.class));
+
+ @Test
+ public void ConnectionPropertiesTest() {
+ contextRunner.run(
+ context -> {
+ AzureOpenAIConnectionProperties props = context
+ .getBean(AzureOpenAIConnectionProperties.class);
+ assertNotNull(props.getEndpoint());
+ assertNotNull(props.getKey());
+ assertNotNull(props.getDeploymentName());
+ });
+ }
+}
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/SemanticKernelAutoConfigurationTest.java b/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/SemanticKernelAutoConfigurationTest.java
similarity index 95%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/SemanticKernelAutoConfigurationTest.java
rename to samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/SemanticKernelAutoConfigurationTest.java
index c4bec236..fa7419f4 100644
--- a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/SemanticKernelAutoConfigurationTest.java
+++ b/samples/semantickernel-demos/semantickernel-spring-starter/src/test/java/com/microsoft/semantickernel/azureopenai/SemanticKernelAutoConfigurationTest.java
@@ -1,3 +1,4 @@
+// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.azureopenai;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -23,7 +24,7 @@ public class SemanticKernelAutoConfigurationTest {
public void testSemanticKernelAutoConfig() {
ApplicationContextRunner runner = new ApplicationContextRunner();
runner.withPropertyValues(
- // @formatter:off
+ // @formatter:off
"client.azureopenai.key=TEST_KEY",
"client.azureopenai.endpoint=TEST_ENDPOINT"
// @formatter:on
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/application.properties b/samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/application.properties
similarity index 100%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/application.properties
rename to samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/application.properties
diff --git a/java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/log4j2.xml b/samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/log4j2.xml
similarity index 100%
rename from java/samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/log4j2.xml
rename to samples/semantickernel-demos/semantickernel-spring-starter/src/test/resources/log4j2.xml
diff --git a/samples/semantickernel-demos/sk-presidio-sample/.mvn/jvm.config b/samples/semantickernel-demos/sk-presidio-sample/.mvn/jvm.config
new file mode 100644
index 00000000..32599cef
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/.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/samples/semantickernel-demos/sk-presidio-sample/.mvn/wrapper/maven-wrapper.properties b/samples/semantickernel-demos/sk-presidio-sample/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..6d3a5665
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/.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/samples/semantickernel-demos/sk-presidio-sample/README.md b/samples/semantickernel-demos/sk-presidio-sample/README.md
new file mode 100644
index 00000000..fe9f4c4e
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/README.md
@@ -0,0 +1,51 @@
+# Presidio Sample
+
+This sample demonstrates how to use Presidio with Semantic Kernel to redact sensitive data from a prompt. A sample
+output from this example is shown below:
+
+```
+==============================
+Input text is:
+The users name is: Steven.
+Steven has account number 012345612.
+Steven was born in New York and their mother is Sally.
+==============================
+Anonymised text is:
+The users name is: PERSON4.
+PERSON4 has account number AU_ACN3.
+PERSON4 was born in LOCATION1 and their mother is PERSON2.
+
+==============================
+User Question:
+Question: Where was the user born?
+==============================
+Anonymised response:
+The user was born in LOCATION1.
+==============================
+Deanonymised response:
+The user was born in New York.
+
+==============================
+User Question:
+Question: Who is the users mother?
+==============================
+Anonymised response:
+The user's mother is PERSON2.
+==============================
+Deanonymised response:
+The user's mother is Sally.
+```
+
+# App structure
+
+The [semantickernel-presidio-plugin](..%2F..%2Fsemantickernel-sample-plugins%2Fsemantickernel-presidio-plugin) plugin
+takes user text and runs it through Presidio to redact sensitive data. The plugin then returns the redacted text. The
+redacted information is then sent to an LLM for processing. The response is then de-anonymised.
+
+# Build and Run
+
+As this example depends on running Presidio, it run within docker containers using docker compose.
+
+- Before building and running ensure that you have run `./mvnw install` on the semantic kernel you wish to use.
+- Copy [env.example](env.example) to `.env` and update the values as needed.
+- Run [buildAndRun.sh](buildAndRun.sh)
\ No newline at end of file
diff --git a/samples/semantickernel-demos/sk-presidio-sample/buildAndRun.sh b/samples/semantickernel-demos/sk-presidio-sample/buildAndRun.sh
new file mode 100755
index 00000000..43a1c466
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/buildAndRun.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -eux
+
+./mvnw package
+
+docker-compose build && docker-compose up
\ No newline at end of file
diff --git a/samples/semantickernel-demos/sk-presidio-sample/docker-compose.yml b/samples/semantickernel-demos/sk-presidio-sample/docker-compose.yml
new file mode 100644
index 00000000..87435525
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/docker-compose.yml
@@ -0,0 +1,28 @@
+version: '3.6'
+services:
+ presidio-analyzer:
+ image: "mcr.microsoft.com/presidio-analyzer"
+ ports:
+ - 3001:3000
+ logging:
+ driver: none
+ presidio-anonymizer:
+ image: "mcr.microsoft.com/presidio-anonymizer"
+ ports:
+ - 3000:3000
+ logging:
+ driver: none
+ sk-presidio-sample:
+ image: "sk-presidio-sample"
+ depends_on:
+ - presidio-anonymizer
+ - presidio-analyzer
+ build:
+ context: .
+ dockerfile: ./sk-presidio-sample-dockerfile
+ secrets:
+ - ai-config
+secrets:
+ ai-config:
+ file: ./.env
+
diff --git a/samples/semantickernel-demos/sk-presidio-sample/env.example b/samples/semantickernel-demos/sk-presidio-sample/env.example
new file mode 100644
index 00000000..85a2b743
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/env.example
@@ -0,0 +1,7 @@
+# If OpenAI
+#CLIENT_KEY=""
+
+# If Azure OpenAI
+#USE_AZURE_CLIENT=true
+#CLIENT_ENDPOINT=""
+#AZURE_CLIENT_KEY=""
diff --git a/samples/semantickernel-demos/sk-presidio-sample/mvnw b/samples/semantickernel-demos/sk-presidio-sample/mvnw
new file mode 100755
index 00000000..8d937f4c
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/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/samples/semantickernel-demos/sk-presidio-sample/pom.xml b/samples/semantickernel-demos/sk-presidio-sample/pom.xml
new file mode 100644
index 00000000..11dd2ae6
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+ com.microsoft.semantic-kernel
+ semantickernel-demos
+ 1.2.0
+ ../pom.xml
+
+
+ sk-presidio-sample
+ Presidio Sample
+
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-bom
+ ${project.version}
+ pom
+ import
+
+
+
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-api
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-aiservices-openai
+
+
+ com.microsoft.semantic-kernel
+ semantickernel-presidio-plugin
+ ${project.version}
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 17
+ 17
+
+
+
+ maven-assembly-plugin
+
+
+
+ com.microsoft.semantickernel.Main
+
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/semantickernel-demos/sk-presidio-sample/scripts/run.sh b/samples/semantickernel-demos/sk-presidio-sample/scripts/run.sh
new file mode 100644
index 00000000..7578ab41
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/scripts/run.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# It takes some time for presidio to start, wait for it
+sleep 10
+
+set -a
+. /run/secrets/ai-config
+set +a
+
+java -jar sk-presidio-sample.jar
\ No newline at end of file
diff --git a/samples/semantickernel-demos/sk-presidio-sample/sk-presidio-sample-dockerfile b/samples/semantickernel-demos/sk-presidio-sample/sk-presidio-sample-dockerfile
new file mode 100644
index 00000000..7a5102a2
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/sk-presidio-sample-dockerfile
@@ -0,0 +1,15 @@
+######################################################
+## Build Deployment
+FROM mcr.microsoft.com/openjdk/jdk:21-ubuntu as presidio-sk-sample-app
+
+COPY --chown=app:app scripts/run.sh /home/app/
+
+RUN chmod +x /home/app/run.sh
+
+WORKDIR /home/app
+USER app
+
+COPY target/sk-presidio-sample-*-jar-with-dependencies.jar /home/app/sk-presidio-sample.jar
+
+CMD /home/app/run.sh
+
diff --git a/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java b/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java
new file mode 100644
index 00000000..366d5014
--- /dev/null
+++ b/samples/semantickernel-demos/sk-presidio-sample/src/main/java/com/microsoft/semantickernel/Main.java
@@ -0,0 +1,161 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel;
+
+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.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
+import com.microsoft.semantickernel.orchestration.InvocationContext;
+import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
+import com.microsoft.semantickernel.plugin.KernelPluginFactory;
+import com.microsoft.semantickernel.presidio.AnonymizedText;
+import com.microsoft.semantickernel.presidio.AnonymizedTextConverter;
+import com.microsoft.semantickernel.presidio.RedactorPlugin;
+import com.microsoft.semantickernel.semanticfunctions.KernelFunctionArguments;
+import com.microsoft.semantickernel.services.ServiceNotFoundException;
+import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
+import com.microsoft.semantickernel.services.chatcompletion.ChatHistory;
+import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
+import java.util.List;
+import reactor.core.publisher.Mono;
+
+public class Main {
+
+ private static final String USE_AZURE_CLIENT = System.getenv("USE_AZURE_CLIENT");
+
+ private static final String CLIENT_KEY = System.getenv("CLIENT_KEY");
+ private static final String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY");
+
+ // Only required if AZURE_CLIENT_KEY is set
+ private static final String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT");
+ private static final String MODEL_ID = System.getenv()
+ .getOrDefault("MODEL_ID", "gpt-4o");
+
+ public static void main(String[] args) throws InterruptedException {
+
+ Kernel kernel = buildKernel();
+
+ String text = """
+ The users name is: Steven.
+ Steven has account number 012345612.
+ Steven was born in New York and their mother is Sally.
+ """.stripIndent();
+
+ System.out.println("==============================");
+ System.out.println("Input text is: \n" + text);
+
+ AnonymizedText result = kernel
+ .invokeAsync("redactor", "redact")
+ .withResultType(AnonymizedText.class)
+ .withArguments(
+ KernelFunctionArguments.builder()
+ .withVariable("input", text)
+ .build())
+ .block()
+ .getResult();
+
+ System.out.println("==============================");
+ System.out.println("Anonymised text is: \n" + result.getRedacted());
+
+ askQuestion(kernel, result, "Question: Where was the user born?").block();
+ askQuestion(kernel, result, "Question: Who is the users mother?").block();
+
+ }
+
+ private static Mono>> askQuestion(
+ Kernel kernel,
+ AnonymizedText anonymizedUserInfo,
+ String question) {
+ ChatHistory chat = formChatHistory();
+
+ chat.addUserMessage(anonymizedUserInfo.getRedacted());
+ chat.addUserMessage(question);
+
+ System.out.println("==============================");
+ System.out.println("User Question: \n" + question);
+
+ try {
+ return kernel
+ .getService(ChatCompletionService.class)
+ .getChatMessageContentsAsync(chat, kernel,
+ InvocationContext.builder()
+ .withPromptExecutionSettings(
+ PromptExecutionSettings.builder()
+ .withMaxTokens(2048)
+ .withTemperature(0.5)
+ .build())
+ .build())
+ .map(chatHistory -> {
+ String message = chatHistory.get(0).getContent();
+ System.out.println("==============================");
+ System.out.println(
+ "Anonymised response: \n" + message);
+
+ System.out.println("==============================");
+ System.out.println(
+ "Deanonymised response: \n" + anonymizedUserInfo.unredact(message));
+ return chatHistory;
+ });
+
+ } catch (ServiceNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static ChatHistory formChatHistory() {
+ ChatHistory chat = new ChatHistory();
+
+ chat.addSystemMessage(
+ """
+ You answer questions about the provided information.
+ The following is an example of answering a question about a user.
+
+ Information about the user:
+ The users name is PERSON100.
+ PERSON100 has long hair.
+
+ Question: What does the users hair look like?
+ Answer: The user has long hair.
+ """.stripIndent());
+
+ return chat;
+ }
+
+ private static Kernel buildKernel() {
+ OpenAIAsyncClient client;
+
+ if (Boolean.parseBoolean(USE_AZURE_CLIENT)) {
+ client = new OpenAIClientBuilder()
+ .credential(new AzureKeyCredential(AZURE_CLIENT_KEY))
+ .endpoint(CLIENT_ENDPOINT)
+ .buildAsyncClient();
+
+ } else {
+ client = new OpenAIClientBuilder()
+ .credential(new KeyCredential(CLIENT_KEY))
+ .buildAsyncClient();
+ }
+
+ ChatCompletionService chat = OpenAIChatCompletion.builder()
+ .withModelId(MODEL_ID)
+ .withOpenAIAsyncClient(client)
+ .build();
+
+ ContextVariableTypes.addGlobalConverter(new AnonymizedTextConverter());
+
+ return Kernel
+ .builder()
+ .withAIService(ChatCompletionService.class, chat)
+ .withPlugin(
+ KernelPluginFactory.createFromObject(
+ new RedactorPlugin(
+ "http://presidio-analyzer:3000",
+ "http://presidio-anonymizer:3000"),
+ "redactor"))
+ .build();
+
+ }
+
+}
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/log4j2.xml b/samples/semantickernel-demos/sk-presidio-sample/src/main/resources/log4j2.xml
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/log4j2.xml
rename to samples/semantickernel-demos/sk-presidio-sample/src/main/resources/log4j2.xml
diff --git a/java/samples/semantickernel-learn-resources/pom.xml b/samples/semantickernel-learn-resources/pom.xml
similarity index 98%
rename from java/samples/semantickernel-learn-resources/pom.xml
rename to samples/semantickernel-learn-resources/pom.xml
index 54be08fc..63ee1288 100644
--- a/java/samples/semantickernel-learn-resources/pom.xml
+++ b/samples/semantickernel-learn-resources/pom.xml
@@ -4,7 +4,7 @@
com.microsoft.semantic-kernelsemantickernel-samples-parent
- 1.1.5
+ 1.2.0../pom.xml
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/AIServices.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/AIServices.java
similarity index 93%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/AIServices.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/AIServices.java
index d7a5a82d..09df9f87 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/AIServices.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/AIServices.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.textcompletion.TextGenerationService;
@@ -44,7 +45,7 @@ public static void main(String[] args) {
}
//
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withModelId(CHAT_MODEL_ID)
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/ConfiguringPrompts.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/ConfiguringPrompts.java
similarity index 95%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/ConfiguringPrompts.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/ConfiguringPrompts.java
index 2f73c58b..df05d8a4 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/ConfiguringPrompts.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/ConfiguringPrompts.java
@@ -8,6 +8,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.semanticfunctions.InputVariable;
import com.microsoft.semantickernel.semanticfunctions.KernelFunction;
@@ -47,7 +48,7 @@ public static void main(String[] args) {
}
//
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withModelId(CHAT_MODEL_ID)
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java
similarity index 97%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java
index d009ecbe..2cbb5baa 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/CreatingFunctions.java
@@ -44,7 +44,7 @@ public static void main(String[] args) {
//
Kernel kernel = Kernel.builder()
- .withAIService(ChatCompletionService.class, ChatCompletionService.builder()
+ .withAIService(ChatCompletionService.class, OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build())
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java
similarity index 97%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java
index fcb0c1dc..f271b757 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/FunctionsWithinPrompts.java
@@ -9,6 +9,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
import com.microsoft.semantickernel.plugin.KernelPlugin;
@@ -54,7 +55,7 @@ public static void main(String[] args) {
}
//
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Plugin.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Plugin.java
similarity index 96%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Plugin.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Plugin.java
index eff1a254..c0ed21eb 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Plugin.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Plugin.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.implementation.CollectionUtil;
import com.microsoft.semantickernel.orchestration.InvocationContext;
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
@@ -55,7 +56,7 @@ public static void main(String[] args) {
}
//
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Prompts.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Prompts.java
similarity index 98%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Prompts.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Prompts.java
index 82ce0e3c..20051eb8 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Prompts.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Prompts.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
public class Prompts {
@@ -35,7 +36,7 @@ public static void main(String[] args) {
//
Kernel kernel = Kernel.builder()
- .withAIService(ChatCompletionService.class, ChatCompletionService.builder()
+ .withAIService(ChatCompletionService.class, OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build())
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java
similarity index 95%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java
index 5cd4bd20..3b5ba591 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/SerializingPrompts.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.contextvariables.converters.CollectionVariableContextVariableTypeConverter;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.samples.plugins.ConversationSummaryPlugin;
@@ -39,7 +40,7 @@ public class SerializingPrompts {
private static final String MODEL_ID = System.getenv()
.getOrDefault("MODEL_ID", "gpt-3.5-turbo");
- private static final String PLUGINS_DIR = "java/samples/semantickernel-learn-resources/src/main/resources/Plugins";
+ private static final String PLUGINS_DIR = "samples/semantickernel-learn-resources/src/main/resources/Plugins";
public static void main(String[] args) throws IOException {
System.out.println("======== Serializing Prompts ========");
@@ -79,7 +80,7 @@ public static void main(String[] args) throws IOException {
//
// Create Kernel
Kernel kernel = Kernel.builder()
- .withAIService(ChatCompletionService.class, ChatCompletionService.builder()
+ .withAIService(ChatCompletionService.class, OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build())
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java
similarity index 97%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java
index d030b4e5..41b09651 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/Templates.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
import com.microsoft.semantickernel.orchestration.FunctionResult;
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
@@ -72,7 +73,7 @@ public static void main(String[] args) {
})
.build();
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java
similarity index 95%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java
index e19a2ad1..73f137dc 100644
--- a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java
+++ b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/documentationexamples/UsingTheKernel.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.plugin.KernelPlugin;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.samples.plugins.MathPlugin;
@@ -48,7 +49,7 @@ public static void main(String[] args) {
//
- ChatCompletionService chatCompletionService = ChatCompletionService.builder()
+ ChatCompletionService chatCompletionService = OpenAIChatCompletion.builder()
.withModelId(MODEL_ID)
.withOpenAIAsyncClient(client)
.build();
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/ConversationSummaryPlugin.java
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/MathPlugin.java
diff --git a/java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java b/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java
rename to samples/semantickernel-learn-resources/src/main/java/com/microsoft/semantickernel/samples/plugins/PromptFunctionConstants.java
diff --git a/java/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/config.json b/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/config.json
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/config.json
rename to samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/config.json
diff --git a/java/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/skprompt.txt b/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/skprompt.txt
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/skprompt.txt
rename to samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/Chat/skprompt.txt
diff --git a/java/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml b/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml
rename to samples/semantickernel-learn-resources/src/main/resources/Plugins/Prompts/getIntent.prompt.yaml
diff --git a/java/samples/semantickernel-learn-resources/src/main/resources/log4j2.xml b/samples/semantickernel-learn-resources/src/main/resources/log4j2.xml
similarity index 100%
rename from java/samples/semantickernel-learn-resources/src/main/resources/log4j2.xml
rename to samples/semantickernel-learn-resources/src/main/resources/log4j2.xml
diff --git a/java/samples/semantickernel-sample-plugins/pom.xml b/samples/semantickernel-sample-plugins/pom.xml
similarity index 88%
rename from java/samples/semantickernel-sample-plugins/pom.xml
rename to samples/semantickernel-sample-plugins/pom.xml
index 79365be6..31bd11cc 100644
--- a/java/samples/semantickernel-sample-plugins/pom.xml
+++ b/samples/semantickernel-sample-plugins/pom.xml
@@ -4,16 +4,16 @@
com.microsoft.semantic-kernelsemantickernel-samples-parent
- 1.1.5
+ 1.2.0../pom.xmlsemantickernel-sample-plugins
- 1.1.5pomsemantickernel-sample-pluginssemantickernel-openapi-plugin
+ semantickernel-presidio-plugin
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml
similarity index 95%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml
index 679c9762..6ac975d2 100644
--- a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml
+++ b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/pom.xml
@@ -4,7 +4,7 @@
com.microsoft.semantic-kernelsemantickernel-sample-plugins
- 1.1.5
+ 1.2.0../pom.xml
@@ -83,6 +83,11 @@
log4j-slf4j2-impltest
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/OpenAPIHttpRequestPlugin.java
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/main/java/com/microsoft/semantickernel/samples/openapi/SemanticKernelOpenAPIImporter.java
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAdoptiumImporter.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAdoptiumImporter.java
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAdoptiumImporter.java
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAdoptiumImporter.java
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAuthenticatedRequestImporter.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAuthenticatedRequestImporter.java
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAuthenticatedRequestImporter.java
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleAuthenticatedRequestImporter.java
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleOpenAPIParent.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleOpenAPIParent.java
similarity index 90%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleOpenAPIParent.java
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleOpenAPIParent.java
index 9cfc77a3..5132af8f 100644
--- a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleOpenAPIParent.java
+++ b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExampleOpenAPIParent.java
@@ -5,6 +5,7 @@
import com.azure.core.credential.KeyCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.Kernel.Builder;
+import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
public class ExampleOpenAPIParent {
@@ -35,7 +36,7 @@ public static Builder kernelBuilder() {
.buildAsyncClient();
}
- ChatCompletionService openAIChatCompletion = ChatCompletionService.builder()
+ ChatCompletionService openAIChatCompletion = OpenAIChatCompletion.builder()
.withOpenAIAsyncClient(client)
.withModelId(MODEL_ID)
.build();
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExamplePetstoreImporter.java b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExamplePetstoreImporter.java
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExamplePetstoreImporter.java
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/java/ExamplePetstoreImporter.java
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.json b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.json
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.json
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.json
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.yaml b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.yaml
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.yaml
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/adoptium.yaml
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/authenticatedRequest.yaml b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/authenticatedRequest.yaml
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/authenticatedRequest.yaml
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/authenticatedRequest.yaml
diff --git a/java/semantickernel-api/src/test/resources/log4j2.xml b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/log4j2.xml
similarity index 100%
rename from java/semantickernel-api/src/test/resources/log4j2.xml
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/log4j2.xml
diff --git a/java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/petstore.yaml b/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/petstore.yaml
similarity index 100%
rename from java/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/petstore.yaml
rename to samples/semantickernel-sample-plugins/semantickernel-openapi-plugin/src/test/resources/petstore.yaml
diff --git a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml
similarity index 90%
rename from java/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml
rename to samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml
index 0cc358b1..cd3c0431 100644
--- a/java/samples/semantickernel-concepts/semantickernel-syntax-examples/pom.xml
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/pom.xml
@@ -3,14 +3,13 @@
4.0.0com.microsoft.semantic-kernel
- semantickernel-concepts
- 1.1.5
+ semantickernel-sample-plugins
+ 1.2.0../pom.xml
- semantickernel-syntax-examples
- Semantic Kernel Samples
- Sample code for using the Semantic Kernel project
+ semantickernel-presidio-plugin
+ semantickernel-presidio-pluginjar
@@ -61,8 +60,9 @@
azure-identity
- com.microsoft.semantic-kernel
- semantickernel-aiservices-openai
+ org.junit.jupiter
+ junit-jupiter-api
+ test
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/AnonymizedText.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/AnonymizedText.java
new file mode 100644
index 00000000..6de328b6
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/AnonymizedText.java
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class AnonymizedText {
+
+ private final String unRedacted;
+ private final String redacted;
+ private final Map redactedTokenMap;
+
+ public AnonymizedText(
+ String unRedacted,
+ String redacted,
+ Map redactedTokenMap) {
+ this.unRedacted = unRedacted;
+ this.redacted = redacted;
+ this.redactedTokenMap = Collections.unmodifiableMap(redactedTokenMap);
+ }
+
+ public String getUnRedacted() {
+ return unRedacted;
+ }
+
+ public String getRedacted() {
+ return redacted;
+ }
+
+ public Map getRedactedTokenMap() {
+ return redactedTokenMap;
+ }
+
+ public String unredact(String message) {
+ return redactedTokenMap
+ .entrySet()
+ .stream()
+ .reduce(message,
+ (msg, entry) -> msg.replaceAll(entry.getKey(), entry.getValue()),
+ (msg1, msg2) -> msg1 + msg2);
+ }
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/AnonymizedTextConverter.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/AnonymizedTextConverter.java
new file mode 100644
index 00000000..ab00fed9
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/AnonymizedTextConverter.java
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio;
+
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
+
+public class AnonymizedTextConverter extends ContextVariableTypeConverter {
+
+ public AnonymizedTextConverter() {
+ super(
+ AnonymizedText.class,
+ it -> (AnonymizedText) it,
+ AnonymizedText::getRedacted,
+ text -> {
+ throw new UnsupportedOperationException("AnonymizedText is write-only");
+ });
+ }
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioAnalysisClient.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioAnalysisClient.java
new file mode 100644
index 00000000..d9e67805
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioAnalysisClient.java
@@ -0,0 +1,62 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio;
+
+import com.azure.core.http.ContentType;
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpHeaderName;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.microsoft.semantickernel.presidio.models.AnalyzerRequest;
+import com.microsoft.semantickernel.presidio.models.AnalyzerResult;
+import java.net.URL;
+import java.util.List;
+import reactor.core.publisher.Mono;
+
+public class PresidioAnalysisClient extends PresidioApiClient {
+
+ public PresidioAnalysisClient(
+ HttpClient client,
+ URL endpoint) {
+ super(client, endpoint);
+ }
+
+ public Mono> analyze(AnalyzerRequest analyzerRequest) {
+ try {
+ HttpRequest request = new HttpRequest(HttpMethod.POST,
+ new URL(super.endpoint, "/analyze"))
+ .setHeader(HttpHeaderName.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+ .setBody(super.mapper.writeValueAsBytes(analyzerRequest));
+
+ return super.client.send(request)
+ .flatMap(httpResponse -> {
+ if (httpResponse.getStatusCode() != 200) {
+ return Mono.error(
+ new RuntimeException(
+ "Request failed: " + httpResponse.getStatusCode()));
+ } else {
+ return httpResponse.getBodyAsString();
+ }
+ })
+ .flatMap(body -> {
+ try {
+ TypeReference> type = new TypeReference<>() {
+ };
+
+ return Mono.just(mapper.readValue(body, type));
+ } catch (JsonProcessingException e) {
+ return Mono.error(
+ new RuntimeException("Failed to parse response", e));
+ }
+ });
+ } catch (Exception e) {
+ return Mono.error(e);
+ }
+ }
+
+ public Mono> analyze(String text, String language) {
+ return analyze(new AnalyzerRequest(text, language));
+ }
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioAnonmizerClient.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioAnonmizerClient.java
new file mode 100644
index 00000000..fa4979ad
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioAnonmizerClient.java
@@ -0,0 +1,69 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio;
+
+import com.azure.core.http.ContentType;
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpHeaderName;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.microsoft.semantickernel.presidio.models.AnalyzerResult;
+import com.microsoft.semantickernel.presidio.models.AnonymizeRequest;
+import com.microsoft.semantickernel.presidio.models.AnonymizerResult;
+import com.microsoft.semantickernel.presidio.models.anonymizerType.AnonymizerType;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import reactor.core.publisher.Mono;
+
+public class PresidioAnonmizerClient extends PresidioApiClient {
+
+ public PresidioAnonmizerClient(
+ HttpClient client,
+ URL endpoint) {
+ super(client, endpoint);
+ }
+
+ public Mono anonymize(String text,
+ Map anonymizers,
+ List analyzerResults) {
+
+ return anonymize(new AnonymizeRequest(text, anonymizers, analyzerResults));
+ }
+
+ private Mono anonymize(AnonymizeRequest anonymizeRequest) {
+
+ try {
+ HttpRequest request = new HttpRequest(HttpMethod.POST,
+ new URL(super.endpoint, "/anonymize"))
+ .setHeader(HttpHeaderName.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+ .setBody(super.mapper.writeValueAsBytes(anonymizeRequest));
+
+ return super.client.send(request)
+ .flatMap(httpResponse -> {
+ if (httpResponse.getStatusCode() >= 400) {
+ return Mono.error(
+ new RuntimeException(
+ "Request failed: " + httpResponse.getStatusCode()));
+ } else {
+ return httpResponse.getBodyAsString();
+ }
+ })
+ .flatMap(body -> {
+ try {
+ TypeReference type = new TypeReference<>() {
+ };
+
+ return Mono.just(mapper.readValue(body, type));
+ } catch (JsonProcessingException e) {
+ return Mono.error(
+ new RuntimeException("Failed to parse response", e));
+ }
+ });
+ } catch (Exception e) {
+ return Mono.error(e);
+ }
+
+ }
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioApiClient.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioApiClient.java
new file mode 100644
index 00000000..8f2ea06c
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/PresidioApiClient.java
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio;
+
+import com.azure.core.http.HttpClient;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.net.URL;
+
+public abstract class PresidioApiClient {
+
+ protected final HttpClient client;
+ protected final URL endpoint;
+ protected final ObjectMapper mapper;
+
+ public PresidioApiClient(
+ HttpClient client,
+ URL endpoint) {
+ this.client = client;
+ this.endpoint = endpoint;
+ this.mapper = new ObjectMapper();
+ }
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/RedactorPlugin.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/RedactorPlugin.java
new file mode 100644
index 00000000..a8e156b4
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/RedactorPlugin.java
@@ -0,0 +1,141 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio;
+
+import com.azure.core.http.HttpClient;
+import com.microsoft.semantickernel.presidio.models.AnalyzerResult;
+import com.microsoft.semantickernel.presidio.models.anonymizerType.AnonymizerType.Replace;
+import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction;
+import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter;
+import com.microsoft.semantickernel.semanticfunctions.annotations.SKSample;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Mono;
+
+public class RedactorPlugin {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(RedactorPlugin.class);
+
+ private final PresidioAnalysisClient analysisClient;
+
+ private final PresidioAnonmizerClient anonymizeClient;
+
+ public RedactorPlugin(
+ String analysisServer,
+ String anonymizeServer) {
+ URL analysisUrl = null;
+ try {
+ analysisUrl = URI.create(analysisServer).toURL();
+ } catch (MalformedURLException e) {
+ LOGGER.error("Failed to parse url", e);
+ }
+
+ analysisClient = new PresidioAnalysisClient(
+ HttpClient.createDefault(),
+ analysisUrl);
+
+ URL anonymizeUrl = null;
+ try {
+ anonymizeUrl = URI.create(anonymizeServer).toURL();
+ } catch (MalformedURLException e) {
+ LOGGER.error("Failed to parse url", e);
+ }
+
+ anonymizeClient = new PresidioAnonmizerClient(
+ HttpClient.createDefault(),
+ anonymizeUrl);
+ }
+
+ @DefineKernelFunction(name = "redact", description = "Takes a string of data and redacts sensitive data from that text.", returnType = "com.microsoft.semantickernel.presidio.AnonymizedText", returnDescription = "The redacted text", samples = {
+ @SKSample(inputs = "Bob is tall.", output = "PERSON1 is tall.")
+ })
+ public Mono redactData(
+ @KernelFunctionParameter(name = "input", description = "Text to be redacted") String text) {
+ return analysisClient
+ .analyze(text, "en")
+ .flatMap(analysisResult -> {
+ Map> grouped = groupResultsByAnonymizedData(
+ analysisResult, text);
+
+ Map requestMaps = formAnonymizersMap(grouped);
+
+ List allAnalyses = collectAllAnalyses(grouped);
+
+ return anonymizeClient
+ .anonymize(text, requestMaps, allAnalyses)
+ .map(redacted -> {
+ Map anonymizedTokenMap = formAnonymizedTokenMap(grouped);
+
+ return new AnonymizedText(
+ text,
+ redacted.text(),
+ anonymizedTokenMap);
+ });
+ });
+
+ }
+
+ private static Map formAnonymizedTokenMap(
+ Map> grouped) {
+ return grouped
+ .entrySet()
+ .stream()
+ .collect(Collectors.toMap(
+ entry -> entry.getValue().get(0).entityType(),
+ Entry::getKey));
+ }
+
+ private static List collectAllAnalyses(
+ Map> grouped) {
+ return grouped.values()
+ .stream()
+ .flatMap(Collection::stream)
+ .toList();
+ }
+
+ private static Map formAnonymizersMap(
+ Map> grouped) {
+ return grouped
+ .entrySet()
+ .stream()
+ .collect(Collectors.toMap(
+ entry -> entry.getValue().get(0).entityType(),
+ entry -> new Replace(entry.getValue().get(0).entityType())));
+ }
+
+ private static Map> groupResultsByAnonymizedData(
+ List analysisResult, String text) {
+ Map> grouped = analysisResult
+ .stream()
+ .collect(Collectors.groupingBy(
+ analyzerResult -> text.substring(analyzerResult.start(),
+ analyzerResult.end())));
+
+ AtomicInteger count = new AtomicInteger(0);
+ grouped = grouped
+ .entrySet()
+ .stream()
+ .collect(Collectors.toMap(Entry::getKey,
+ entry -> {
+ count.incrementAndGet();
+ return entry.getValue().stream().map(
+ r -> new AnalyzerResult(
+ r.start(),
+ r.end(),
+ r.score(),
+ r.entityType() + count.get(),
+ r.recognitionMetadata(),
+ r.analysisExplanation()))
+ .toList();
+ }));
+ return grouped;
+ }
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalysisExplanation.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalysisExplanation.java
new file mode 100644
index 00000000..d135503b
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalysisExplanation.java
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+public record AnalysisExplanation(
+ String recognizer,
+ String pattern_name,
+ String pattern,
+ Float original_score,
+ Float score,
+ String textual_explanation,
+ Float score_context_improvement,
+ String supportive_context_word,
+ Float validation_result
+) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalyzerRequest.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalyzerRequest.java
new file mode 100644
index 00000000..e2e28d97
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalyzerRequest.java
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+public record AnalyzerRequest(String text, String language) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalyzerResult.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalyzerResult.java
new file mode 100644
index 00000000..65adb9cc
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnalyzerResult.java
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+
+public record AnalyzerResult(
+ Integer start,
+ Integer end,
+ Float score,
+ @JsonProperty("entity_type")
+ String entityType,
+ @JsonProperty("recognition_metadata")
+ RecognitionMetadata recognitionMetadata,
+ @JsonProperty("analysis_explanation")
+ AnalysisExplanation analysisExplanation
+) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizeRequest.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizeRequest.java
new file mode 100644
index 00000000..a3de4d34
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizeRequest.java
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.microsoft.semantickernel.presidio.models.anonymizerType.AnonymizerType;
+import java.util.List;
+import java.util.Map;
+
+public record AnonymizeRequest(
+ String text,
+ Map anonymizers,
+ @JsonProperty("analyzer_results")
+ List analyzerResults) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/Anonymizer.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/Anonymizer.java
new file mode 100644
index 00000000..891b2fda
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/Anonymizer.java
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+public record Anonymizer(
+ Integer charsToMask,
+ boolean fromEnd,
+ String maskingChar,
+ String type
+) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizerItem.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizerItem.java
new file mode 100644
index 00000000..edac2185
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizerItem.java
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+public record AnonymizerItem(
+ String operator,
+ String entity_type,
+ String text,
+ Integer start,
+ Integer end
+) {
+
+}
\ No newline at end of file
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizerResult.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizerResult.java
new file mode 100644
index 00000000..d601daa2
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/AnonymizerResult.java
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+import java.util.List;
+
+public record AnonymizerResult(
+ String text,
+ List items) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/RecognitionMetadata.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/RecognitionMetadata.java
new file mode 100644
index 00000000..9d23d963
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/RecognitionMetadata.java
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public record RecognitionMetadata(
+ @JsonProperty("recognizer_identifier")
+ String recognizerIdentifier,
+ @JsonProperty("recognizer_name")
+ String recognizerName
+) {
+
+}
diff --git a/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/anonymizerType/AnonymizerType.java b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/anonymizerType/AnonymizerType.java
new file mode 100644
index 00000000..8bb22ee2
--- /dev/null
+++ b/samples/semantickernel-sample-plugins/semantickernel-presidio-plugin/src/main/java/com/microsoft/semantickernel/presidio/models/anonymizerType/AnonymizerType.java
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.presidio.models.anonymizerType;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class AnonymizerType {
+
+ private String type;
+
+ AnonymizerType(
+ @JsonProperty("type") String type) {
+ this.type = type;
+ }
+
+ @JsonProperty("type")
+ public String getType() {
+ return type;
+ }
+
+ public static class Replace extends AnonymizerType {
+
+ private final String new_value;
+
+ @JsonCreator
+ public Replace(
+ @JsonProperty("new_value") String new_value) {
+ super("replace");
+ this.new_value = new_value;
+ }
+
+ @JsonProperty("new_value")
+ public String getNewValue() {
+ return new_value;
+ }
+ }
+}
diff --git a/java/semantickernel-api/pom.xml b/semantickernel-api/pom.xml
similarity index 88%
rename from java/semantickernel-api/pom.xml
rename to semantickernel-api/pom.xml
index a47c141c..2bb0a050 100644
--- a/java/semantickernel-api/pom.xml
+++ b/semantickernel-api/pom.xml
@@ -6,7 +6,7 @@
com.microsoft.semantic-kernelsemantickernel-parent
- 1.1.5
+ 1.2.0../pom.xml
@@ -70,13 +70,24 @@
3.3.1test
+
+
+ javax.xml.stream
+ stax-api
+ provided
+ org.mockitomockito-junit-jupiter5.11.0
+ test
+
+ io.opentelemetry
+ opentelemetry-api
+
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelPluginCollection.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/connectors/WebSearchEngineConnector.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/connectors/WebSearchEngineConnector.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/connectors/WebSearchEngineConnector.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/connectors/WebSearchEngineConnector.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/CaseInsensitiveMap.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/CaseInsensitiveMap.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/CaseInsensitiveMap.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/CaseInsensitiveMap.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariable.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariable.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariable.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariable.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableType.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableType.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableType.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableType.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypes.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypes.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypes.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/ContextVariableTypes.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/BooleanVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/BooleanVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/BooleanVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/BooleanVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CharacterVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CharacterVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CharacterVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CharacterVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/ChatHistoryVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CollectionVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CompletionUsageContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CompletionUsageContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CompletionUsageContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/CompletionUsageContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/DateTimeContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/DateTimeContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/DateTimeContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/DateTimeContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/InstantContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/InstantContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/InstantContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/InstantContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/NumberVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/NumberVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/NumberVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/NumberVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveBooleanVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveBooleanVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveBooleanVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveBooleanVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/PrimitiveVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java
similarity index 58%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java
index 32fe4200..4a431e60 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/StringVariableContextVariableTypeConverter.java
@@ -3,8 +3,10 @@
import static com.microsoft.semantickernel.contextvariables.ContextVariableTypes.convert;
+import com.microsoft.semantickernel.contextvariables.ContextVariable;
import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
import com.microsoft.semantickernel.contextvariables.ContextVariableTypes;
+import javax.annotation.Nullable;
/**
* A {@link ContextVariableTypeConverter} for {@code java.lang.String} variables. Use
@@ -22,8 +24,29 @@ public class StringVariableContextVariableTypeConverter extends
public StringVariableContextVariableTypeConverter() {
super(
String.class,
- s -> convert(s, String.class),
+ StringVariableContextVariableTypeConverter::convertToString,
ContextVariableTypeConverter::escapeXmlString,
s -> s);
}
+
+ @Nullable
+ public static String convertToString(@Nullable Object s) {
+ String converted = convert(s, String.class);
+ if (converted != null) {
+ return converted;
+ }
+
+ if (s instanceof ContextVariable) {
+ s = ((ContextVariable>) s).getValue();
+ }
+
+ if (s != null) {
+ String str = s.toString();
+ // ignore if this looks like an object reference
+ if (!str.matches(".*@[a-f0-9]+$")) {
+ return str;
+ }
+ }
+ return null;
+ }
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/TextContentVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/VoidVariableContextVariableTypeConverter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/VoidVariableContextVariableTypeConverter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/VoidVariableContextVariableTypeConverter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/contextvariables/converters/VoidVariableContextVariableTypeConverter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/AIException.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/AIException.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/AIException.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/AIException.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKCheckedException.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKCheckedException.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKCheckedException.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKCheckedException.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKException.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKException.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKException.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SKException.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokedEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/FunctionInvokingEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHook.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHookEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHookEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHookEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHookEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/KernelHooks.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PostChatCompletionEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PostChatCompletionEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PostChatCompletionEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PostChatCompletionEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreChatCompletionEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreChatCompletionEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreChatCompletionEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreChatCompletionEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PreToolCallEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderedEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/hooks/PromptRenderingEvent.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/CollectionUtil.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/CollectionUtil.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/CollectionUtil.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/CollectionUtil.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/EmbeddedResourceLoader.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/EmbeddedResourceLoader.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/EmbeddedResourceLoader.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/EmbeddedResourceLoader.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/ServiceLoadUtil.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/ServiceLoadUtil.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/ServiceLoadUtil.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/ServiceLoadUtil.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Todo.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Todo.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Todo.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Todo.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Verify.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Verify.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Verify.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/Verify.java
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/chatcompletion/ChatPromptParseVisitor.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/chatcompletion/ChatPromptParseVisitor.java
new file mode 100644
index 00000000..f7b3e068
--- /dev/null
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/chatcompletion/ChatPromptParseVisitor.java
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.implementation.chatcompletion;
+
+import com.azure.core.util.BinaryData;
+import javax.annotation.Nullable;
+
+public interface ChatPromptParseVisitor {
+
+ ChatPromptParseVisitor addMessage(String role, String content);
+
+ ChatPromptParseVisitor addFunction(String name, @Nullable String description,
+ @Nullable BinaryData parameters);
+
+ boolean areMessagesEmpty();
+
+ ChatPromptParseVisitor fromRawPrompt(String rawPrompt);
+
+ T get();
+
+ ChatPromptParseVisitor reset();
+}
\ No newline at end of file
diff --git a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/XMLPromptParser.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/chatcompletion/ChatXMLPromptParser.java
similarity index 66%
rename from java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/XMLPromptParser.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/chatcompletion/ChatXMLPromptParser.java
index c60b4a90..1c8f78c6 100644
--- a/java/aiservices/openai/src/main/java/com/microsoft/semantickernel/aiservices/openai/chatcompletion/XMLPromptParser.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/chatcompletion/ChatXMLPromptParser.java
@@ -1,31 +1,22 @@
// Copyright (c) Microsoft. All rights reserved.
-package com.microsoft.semantickernel.aiservices.openai.chatcompletion;
+package com.microsoft.semantickernel.implementation.chatcompletion;
-import com.azure.ai.openai.models.ChatRequestAssistantMessage;
-import com.azure.ai.openai.models.ChatRequestFunctionMessage;
-import com.azure.ai.openai.models.ChatRequestMessage;
-import com.azure.ai.openai.models.ChatRequestSystemMessage;
-import com.azure.ai.openai.models.ChatRequestToolMessage;
-import com.azure.ai.openai.models.ChatRequestUserMessage;
-import com.azure.ai.openai.models.FunctionDefinition;
import com.azure.core.util.BinaryData;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.semantickernel.exceptions.SKException;
import com.microsoft.semantickernel.orchestration.ToolCallBehavior;
-import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.UUID;
+import javax.annotation.Nullable;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
@@ -33,47 +24,44 @@
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
-import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class XMLPromptParser {
+public class ChatXMLPromptParser {
- private static final Logger LOGGER = LoggerFactory.getLogger(XMLPromptParser.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ChatXMLPromptParser.class);
- public static ParsedPrompt parse(String rawPrompt) {
+ public static ChatPromptParseVisitor parse(
+ String rawPrompt,
+ ChatPromptParseVisitor chatPromptParseVisitor) {
List prompts = Arrays.asList(
rawPrompt,
"" + rawPrompt + "");
for (String prompt : prompts) {
try {
- List parsedMessages = getChatRequestMessages(prompt);
- List parsedFunctions = getFunctionDefinitions(prompt);
+ chatPromptParseVisitor = getChatRequestMessages(prompt, chatPromptParseVisitor);
+ chatPromptParseVisitor = getFunctionDefinitions(prompt, chatPromptParseVisitor);
- if (!parsedMessages.isEmpty()) {
- return new ParsedPrompt(parsedMessages, parsedFunctions);
+ if (!chatPromptParseVisitor.areMessagesEmpty()) {
+ return chatPromptParseVisitor;
}
} catch (SKException e) {
//ignore
+ chatPromptParseVisitor = chatPromptParseVisitor.reset();
}
}
- ChatRequestUserMessage message = new ChatRequestUserMessage(rawPrompt);
-
- if (message.getName() == null) {
- message.setName(UUID.randomUUID().toString());
- }
-
- return new ParsedPrompt(Collections.singletonList(message), null);
+ return chatPromptParseVisitor.fromRawPrompt(rawPrompt);
}
- private static List getChatRequestMessages(String prompt) {
+ private static ChatPromptParseVisitor getChatRequestMessages(String prompt,
+ ChatPromptParseVisitor chatPromptParseVisitor) {
// TODO: XML parsing should be done as a chain of XMLEvent handlers.
// If one handler does not recognize the element, it should pass it to the next handler.
// In this way, we can avoid parsing the whole prompt twice and easily extend the parsing logic.
- List messages = new ArrayList<>();
+
try (InputStream is = new ByteArrayInputStream(prompt.getBytes(StandardCharsets.UTF_8))) {
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader reader = factory.createXMLEventReader(is);
@@ -84,22 +72,41 @@ private static List getChatRequestMessages(String prompt) {
if (name.equals("message")) {
String role = getAttributeValue(event, "role");
String content = reader.getElementText();
- messages.add(getChatRequestMessage(role, content));
+ chatPromptParseVisitor = chatPromptParseVisitor.addMessage(role, content);
}
}
}
} catch (IOException | XMLStreamException | IllegalArgumentException e) {
throw new SKException("Failed to parse messages");
}
- return messages;
+ return chatPromptParseVisitor;
+ }
+
+ private static class FunctionDefinition {
+
+ private final String name;
+ private final String description;
+ @Nullable
+ private BinaryData parameters;
+
+ public FunctionDefinition(String name, String description) {
+ this.name = name;
+ this.description = description;
+ this.parameters = null;
+ }
+
+ public void setParameters(BinaryData binaryData) {
+ this.parameters = binaryData;
+ }
}
- private static List getFunctionDefinitions(String prompt) {
+ private static ChatPromptParseVisitor getFunctionDefinitions(String prompt,
+ ChatPromptParseVisitor chatPromptParseVisitor) {
// TODO: XML parsing should be done as a chain of XMLEvent handlers. See previous remark.
//
// ...
//
- List functionDefinitions = new ArrayList<>();
+
try (InputStream is = new ByteArrayInputStream(prompt.getBytes(StandardCharsets.UTF_8))) {
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLEventReader reader = factory.createXMLEventReader(is);
@@ -119,8 +126,8 @@ private static List getFunctionDefinitions(String prompt) {
String description = getAttributeValue(event, "description");
// name has to match '^[a-zA-Z0-9_-]{1,64}$'
functionDefinition = new FunctionDefinition(
- ToolCallBehavior.formFullFunctionName(pluginName, name))
- .setDescription(description);
+ ToolCallBehavior.formFullFunctionName(pluginName, name),
+ description);
} else if (elementName.equals("parameter")) {
String name = getAttributeValue(event, "name");
String type = getAttributeValue(event, "type").toLowerCase(Locale.ROOT);
@@ -185,7 +192,10 @@ private static List getFunctionDefinitions(String prompt) {
BinaryData binaryData = BinaryData.fromObject(jsonNode);
functionDefinition.setParameters(binaryData);
}
- functionDefinitions.add(functionDefinition);
+ chatPromptParseVisitor = chatPromptParseVisitor.addFunction(
+ functionDefinition.name,
+ functionDefinition.description,
+ functionDefinition.parameters);
functionDefinition = null;
parameters.clear();
requiredParameters.clear();
@@ -195,7 +205,7 @@ private static List getFunctionDefinitions(String prompt) {
} catch (IOException | XMLStreamException | IllegalArgumentException e) {
LOGGER.error("Error parsing prompt", e);
}
- return functionDefinitions;
+ return chatPromptParseVisitor;
}
private static String getElementName(XMLEvent xmlEvent) {
@@ -217,57 +227,4 @@ private static String getAttributeValue(XMLEvent xmlEvent, String attributeName)
// TODO: programmer's error - log at debug
return "";
}
-
- private static ChatRequestMessage getChatRequestMessage(
- String role,
- String content) {
- try {
- AuthorRole authorRole = AuthorRole.valueOf(role.toUpperCase(Locale.ROOT));
- return OpenAIChatCompletion.getChatRequestMessage(authorRole, content);
- } catch (IllegalArgumentException e) {
- LOGGER.debug("Unknown author role: " + role);
- throw new SKException("Unknown author role: " + role);
- }
- }
-
- public static ChatRequestMessage unescapeRequest(ChatRequestMessage message) {
- if (message instanceof ChatRequestUserMessage) {
- ChatRequestUserMessage chatRequestMessage = (ChatRequestUserMessage) message;
- String content = StringEscapeUtils.unescapeXml(
- chatRequestMessage.getContent().toString());
-
- return new ChatRequestUserMessage(content)
- .setName(chatRequestMessage.getName());
- } else if (message instanceof ChatRequestSystemMessage) {
- ChatRequestSystemMessage chatRequestMessage = (ChatRequestSystemMessage) message;
- String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
-
- return new ChatRequestSystemMessage(content)
- .setName(chatRequestMessage.getName());
- } else if (message instanceof ChatRequestAssistantMessage) {
- ChatRequestAssistantMessage chatRequestMessage = (ChatRequestAssistantMessage) message;
- String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
-
- return new ChatRequestAssistantMessage(content)
- .setToolCalls(chatRequestMessage.getToolCalls())
- .setFunctionCall(chatRequestMessage.getFunctionCall())
- .setName(chatRequestMessage.getName());
- } else if (message instanceof ChatRequestFunctionMessage) {
- ChatRequestFunctionMessage chatRequestMessage = (ChatRequestFunctionMessage) message;
- String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
-
- return new ChatRequestFunctionMessage(
- chatRequestMessage.getName(),
- content);
- } else if (message instanceof ChatRequestToolMessage) {
- ChatRequestToolMessage chatRequestMessage = (ChatRequestToolMessage) message;
- String content = StringEscapeUtils.unescapeXml(chatRequestMessage.getContent());
-
- return new ChatRequestToolMessage(
- content,
- chatRequestMessage.getToolCallId());
- }
-
- throw new SKException("Unknown message type: " + message.getClass().getSimpleName());
- }
}
\ No newline at end of file
diff --git a/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/SemanticKernelTelemetry.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/SemanticKernelTelemetry.java
new file mode 100644
index 00000000..2ba4b846
--- /dev/null
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/telemetry/SemanticKernelTelemetry.java
@@ -0,0 +1,79 @@
+// Copyright (c) Microsoft. All rights reserved.
+package com.microsoft.semantickernel.implementation.telemetry;
+
+import com.azure.ai.openai.models.CompletionsUsage;
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.SpanBuilder;
+import io.opentelemetry.api.trace.StatusCode;
+import javax.annotation.Nullable;
+
+public class SemanticKernelTelemetry {
+
+ public static final String OPEN_AI_PROVIDER = "openai";
+
+ public static Span startChatCompletionSpan(
+ @Nullable String modelName,
+ String modelProvider,
+ @Nullable Integer maxTokens,
+ @Nullable Double temperature,
+ @Nullable Double topP) {
+ return startCompletionSpan("chat.completions", modelName, modelProvider, maxTokens,
+ temperature, topP);
+ }
+
+ public static Span startTextCompletionSpan(
+ @Nullable String modelName,
+ String modelProvider,
+ @Nullable Integer maxTokens,
+ @Nullable Double temperature,
+ @Nullable Double topP) {
+ return startCompletionSpan("text.completions", modelName, modelProvider, maxTokens,
+ temperature, topP);
+ }
+
+ private static Span startCompletionSpan(
+ String operationName,
+ @Nullable String modelName,
+ String modelProvider,
+ @Nullable Integer maxTokens,
+ @Nullable Double temperature,
+ @Nullable Double topP) {
+ OpenTelemetry otel = GlobalOpenTelemetry.get();
+
+ if (modelName == null) {
+ modelName = "unknown";
+ }
+ SpanBuilder builder = otel
+ .getTracer("SemanticKernel")
+ .spanBuilder(operationName + " " + modelName)
+ .setAttribute("gen_ai.request.model", modelName)
+ .setAttribute("gen_ai.operation.name", operationName)
+ .setAttribute("gen_ai.system", modelProvider);
+
+ if (maxTokens != null) {
+ builder.setAttribute("gen_ai.request.max_tokens", maxTokens);
+ }
+ if (temperature != null) {
+ builder.setAttribute("gen_ai.request.temperature", temperature);
+ }
+ if (topP != null) {
+ builder.setAttribute("gen_ai.request.top_p", topP);
+ }
+
+ return builder.startSpan();
+ }
+
+ public static void endSpanWithUsage(Span span, CompletionsUsage usage) {
+ span.setStatus(StatusCode.OK);
+ span.setAttribute("gen_ai.response.completion_tokens", usage.getCompletionTokens());
+ span.setAttribute("gen_ai.response.prompt_tokens", usage.getPromptTokens());
+ span.end();
+ }
+
+ public static void endSpanWithError(Span span) {
+ span.setStatus(StatusCode.ERROR);
+ span.end();
+ }
+}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/CodeTokenizer.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/CodeTokenizer.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/CodeTokenizer.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/CodeTokenizer.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/DefaultPromptTemplate.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/TemplateTokenizer.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/TemplateTokenizer.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/TemplateTokenizer.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/TemplateTokenizer.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Block.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Block.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Block.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Block.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/BlockTypes.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/BlockTypes.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/BlockTypes.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/BlockTypes.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeBlock.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/CodeRendering.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/FunctionIdBlock.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/NamedArgBlock.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Symbols.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Symbols.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Symbols.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/Symbols.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextBlock.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/TextRendering.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/ValBlock.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/implementation/templateengine/tokenizer/blocks/VarBlock.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionInvocation.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResult.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResult.java
similarity index 94%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResult.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResult.java
index 359598c8..510bb65f 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResult.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResult.java
@@ -16,7 +16,7 @@
public class FunctionResult {
private final ContextVariable result;
- private final FunctionResultMetadata metadata;
+ private final FunctionResultMetadata> metadata;
@Nullable
private final Object unconvertedResult;
@@ -30,7 +30,7 @@ public class FunctionResult {
*/
public FunctionResult(
ContextVariable result,
- @Nullable FunctionResultMetadata metadata,
+ @Nullable FunctionResultMetadata> metadata,
@Nullable Object unconvertedResult) {
this.result = result;
this.metadata = metadata == null ? FunctionResultMetadata.empty() : metadata;
@@ -77,7 +77,7 @@ public ContextVariable getResultVariable() {
*
* @return The metadata about the result of the function invocation.
*/
- public FunctionResultMetadata getMetadata() {
+ public FunctionResultMetadata> getMetadata() {
return metadata;
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResultMetadata.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResultMetadata.java
similarity index 83%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResultMetadata.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResultMetadata.java
index 9d9612c3..f9e79c7f 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResultMetadata.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionResultMetadata.java
@@ -1,9 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.orchestration;
-import com.azure.ai.openai.models.CompletionsUsage;
import com.microsoft.semantickernel.contextvariables.CaseInsensitiveMap;
import com.microsoft.semantickernel.contextvariables.ContextVariable;
+import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
+
import java.time.OffsetDateTime;
import javax.annotation.Nullable;
@@ -12,7 +13,7 @@
*
* This class is used to return metadata about the result of a function invocation.
*/
-public class FunctionResultMetadata {
+public class FunctionResultMetadata {
/**
* The key for id metadata.
@@ -50,7 +51,7 @@ public FunctionResultMetadata(CaseInsensitiveMap> metadata) {
/**
* Create a new instance of FunctionResultMetadata.
*/
- public static FunctionResultMetadata build(String id) {
+ public static FunctionResultMetadata> build(String id) {
return build(id, null, null);
}
@@ -62,21 +63,24 @@ public static FunctionResultMetadata build(String id) {
* @param createdAt The time the result was created.
* @return A new instance of FunctionResultMetadata.
*/
- public static FunctionResultMetadata build(
+ public static FunctionResultMetadata build(
String id,
- @Nullable CompletionsUsage usage,
+ @Nullable UsageType usage,
@Nullable OffsetDateTime createdAt) {
CaseInsensitiveMap> metadata = new CaseInsensitiveMap<>();
+
metadata.put(ID, ContextVariable.of(id));
+
if (usage != null) {
- metadata.put(USAGE, ContextVariable.of(usage));
+ metadata.put(USAGE, ContextVariable.of(usage,
+ new ContextVariableTypeConverter.NoopConverter<>(Object.class)));
}
if (createdAt != null) {
metadata.put(CREATED_AT, ContextVariable.of(createdAt));
}
- return new FunctionResultMetadata(metadata);
+ return new FunctionResultMetadata<>(metadata);
}
/**
@@ -84,8 +88,8 @@ public static FunctionResultMetadata build(
*
* @return A new instance of FunctionResultMetadata.
*/
- public static FunctionResultMetadata empty() {
- return new FunctionResultMetadata(new CaseInsensitiveMap<>());
+ public static FunctionResultMetadata> empty() {
+ return new FunctionResultMetadata<>(new CaseInsensitiveMap<>());
}
/**
@@ -117,12 +121,12 @@ public String getId() {
* @return The usage of the result of the function invocation.
*/
@Nullable
- public CompletionsUsage getUsage() {
+ public UsageType getUsage() {
ContextVariable> usage = metadata.get(USAGE);
if (usage == null) {
return null;
}
- return usage.getValue(CompletionsUsage.class);
+ return (UsageType) usage.getValue(Object.class);
}
/**
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationContext.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationReturnMode.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationReturnMode.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationReturnMode.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/InvocationReturnMode.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java
similarity index 99%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java
index 10b2079f..12dc0bbc 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/PromptExecutionSettings.java
@@ -550,7 +550,7 @@ public Builder withTokenSelectionBiases(Map tokenSelectionBias
*/
public Builder withResponseFormat(ResponseFormat responseFormat) {
if (responseFormat != null) {
- settings.put(RESPONSE_FORMAT, responseFormat);
+ settings.put(RESPONSE_FORMAT, responseFormat.toString());
}
return this;
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ResponseFormat.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ResponseFormat.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ResponseFormat.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ResponseFormat.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ToolCallBehavior.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ToolCallBehavior.java
similarity index 99%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ToolCallBehavior.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ToolCallBehavior.java
index 8148eb16..affa13ac 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ToolCallBehavior.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ToolCallBehavior.java
@@ -70,7 +70,7 @@ public static ToolCallBehavior allowOnlyKernelFunctions(boolean autoInvoke,
}
private static final int DEFAULT_MAXIMUM_AUTO_INVOKE_ATTEMPTS = 5;
- private static final String FUNCTION_NAME_SEPARATOR = "-";
+ public static final String FUNCTION_NAME_SEPARATOR = "-";
private final int maximumAutoInvokeAttempts;
/**
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPlugin.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPlugin.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPlugin.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPlugin.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/plugin/KernelPluginFactory.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/AggregatorPromptTemplateFactory.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/AggregatorPromptTemplateFactory.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/AggregatorPromptTemplateFactory.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/AggregatorPromptTemplateFactory.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/HandlebarsPromptTemplateFactory.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/HandlebarsPromptTemplateFactory.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/HandlebarsPromptTemplateFactory.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/HandlebarsPromptTemplateFactory.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputConfig.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputConfig.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputConfig.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputConfig.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputParameter.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputParameter.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputParameter.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputParameter.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputVariable.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputVariable.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputVariable.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/InputVariable.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java
similarity index 100%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunction.java
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java
similarity index 98%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java
index ecf39ef8..f3b46c21 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionArguments.java
@@ -295,6 +295,9 @@ public Builder withVariable(String key, ContextVariable value) {
* @throws SKException if the value cannot be converted to a ContextVariable
*/
public Builder withVariable(String key, Object value) {
+ if (value instanceof ContextVariable) {
+ return withVariable(key, (ContextVariable>) value);
+ }
return withVariable(key, ContextVariable.ofGlobalType(value));
}
diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java
similarity index 83%
rename from java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java
rename to semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java
index 77ba8318..6d9d1166 100644
--- a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java
+++ b/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/KernelFunctionFromMethod.java
@@ -147,7 +147,7 @@ private static MethodDetails getMethodDetails(
}
@SuppressWarnings("unchecked")
- private static ImplementationFunc getFunction(Method method, Object instance) {
+ public static ImplementationFunc getFunction(Method method, Object instance) {
return (kernel, function, arguments, variableType, invocationContext) -> {
InvocationContext context;
if (invocationContext == null) {
@@ -354,22 +354,190 @@ private static Object getArgumentValue(
Parameter parameter,
Kernel kernel,
InvocationContext invocationContext) {
+ // The actual type of the method argument
+ Class> targetArgType = parameter.getType();
+
+ if (Kernel.class.isAssignableFrom(targetArgType)) {
+ return kernel;
+ }
+
String variableName = getGetVariableName(parameter);
+ ContextVariable> variable = getVariableFromContext(method, context, variableName);
+
+ // The Value of what has been provided
+ Object sourceValue = null;
+ ContextVariableType> sourceType = null;
+
+ // if needed extract the default value from annotation and substitute it for the missing variable
+ variable = extractDefaultTypeFromAnnotation(
+ method,
+ parameter,
+ invocationContext,
+ variable,
+ sourceValue,
+ variableName);
+
+ if (variable != null) {
+ sourceValue = variable.getValue();
+ sourceType = variable.getType();
+ }
+
+ Class> requestedType = targetArgType;
+
+ KernelFunctionParameter annotation = parameter.getAnnotation(KernelFunctionParameter.class);
+ if (annotation != null && annotation.type() != null) {
+ requestedType = annotation.type();
+ }
+
+ // Ignore string as there is a good chance the developer user left it to default
+ if (requestedType != String.class && !targetArgType.isAssignableFrom(requestedType)) {
+ throw new AIException(
+ AIException.ErrorCodes.INVALID_CONFIGURATION,
+ "Annotation on method: " + method.getName() + " requested conversion to type: "
+ + requestedType.getName()
+ + ", however this cannot be assigned to parameter of type: "
+ + targetArgType);
+ }
+
+ if (requestedType == String.class && !targetArgType.isAssignableFrom(requestedType)) {
+ LOGGER.warn(
+ "Annotation on method: {} is requesting a String which is not assignable to method type {}, possibly as the type argument has not been provided on the annotation.",
+ method.getName(),
+ targetArgType.getName());
+ }
+
+ // First try to convert to the type requested from the annotation
+ Object converted = toObjectType(
+ parameter.getName(),
+ sourceType,
+ sourceValue,
+ requestedType,
+ invocationContext);
+
+ if (targetArgType.isInstance(converted)) {
+ return converted;
+ }
+
+ if (converted != null) {
+ // Could not convert to requested type, try to target type
+ ContextVariable