├── src ├── client │ ├── __init__.py │ ├── utils │ │ └── __init__.py │ ├── content │ │ ├── __init__.py │ │ ├── config │ │ │ ├── __init__.py │ │ │ ├── tabs │ │ │ │ └── __init__.py │ │ │ └── config.py │ │ └── tools │ │ │ ├── __init__.py │ │ │ ├── tabs │ │ │ └── __init__.py │ │ │ └── tools.py │ ├── spring_ai │ │ ├── src │ │ │ └── main │ │ │ │ ├── resources │ │ │ │ ├── application.yml │ │ │ │ └── application-dev.yml │ │ │ │ └── java │ │ │ │ └── org │ │ │ │ └── springframework │ │ │ │ └── ai │ │ │ │ └── openai │ │ │ │ └── samples │ │ │ │ └── helloworld │ │ │ │ ├── model │ │ │ │ ├── ChatMessage.java │ │ │ │ ├── ChatStreamResponse.java │ │ │ │ ├── ChatRequest.java │ │ │ │ ├── ChatChoice.java │ │ │ │ └── ChatResponse.java │ │ │ │ ├── WebCorsConfig.java │ │ │ │ ├── Application.java │ │ │ │ └── Config.java │ │ ├── ollama-values.yaml │ │ ├── templates │ │ │ ├── obaas.yaml │ │ │ └── start.sh │ │ └── LICENSE.txt │ ├── media │ │ ├── logo.png │ │ └── favicon.png │ ├── mcp │ │ ├── rag │ │ │ ├── cover.png │ │ │ ├── images │ │ │ │ ├── export.png │ │ │ │ └── rag_tool.png │ │ │ ├── main.py │ │ │ ├── rag_base_optimizer_config_direct.py │ │ │ └── rag_base_optimizer_config_mcp.py │ │ └── todo_list.md │ └── Dockerfile ├── common │ ├── __init__.py │ └── _version.py ├── server │ ├── __init__.py │ ├── api │ │ ├── __init__.py │ │ ├── utils │ │ │ ├── __init__.py │ │ │ ├── README.md │ │ │ └── mcp.py │ │ └── v1 │ │ │ ├── __init__.py │ │ │ ├── probes.py │ │ │ └── mcp.py │ ├── agents │ │ └── __init__.py │ ├── bootstrap │ │ ├── __init__.py │ │ ├── README.md │ │ ├── bootstrap.py │ │ ├── settings.py │ │ ├── configfile.py │ │ └── databases.py │ ├── mcp │ │ ├── tools │ │ │ └── __init__.py │ │ ├── prompts │ │ │ ├── __init__.py │ │ │ └── cache.py │ │ ├── proxies │ │ │ ├── __init__.py │ │ │ └── sqlcl.py │ │ ├── resources │ │ │ └── __init__.py │ │ └── __init__.py │ ├── etc │ │ └── README.md │ ├── wip │ │ └── settings.py │ └── Dockerfile ├── .streamlit │ └── config.toml ├── entrypoint.sh └── Dockerfile ├── helm ├── .helmignore ├── Chart.yaml ├── templates │ ├── global-api-secret.yaml │ ├── client │ │ ├── service.yaml │ │ ├── configmap.yaml │ │ ├── hpa.yaml │ │ └── ingress.yaml │ ├── ollama │ │ └── service-11434.yaml │ └── server │ │ ├── database │ │ ├── adb-wallet-secret.yaml │ │ ├── priv-secret.yaml │ │ ├── adb-operator.yaml │ │ ├── oci-configmap.yaml │ │ ├── auth-secret.yaml │ │ ├── init-configmap.yaml │ │ └── init-job.yaml │ │ ├── service.yaml │ │ ├── hpa.yaml │ │ └── ingress.yaml └── examples │ ├── values-kind-adb-free.yaml │ ├── values-kind-sidb-free.yaml │ └── values-kind-other.yaml ├── docs ├── layouts │ ├── shortcodes │ │ ├── short_app_ref.html │ │ ├── full_app_ref.html │ │ ├── imagelink.html │ │ └── latest_release.html │ └── partials │ │ ├── content-footer.html │ │ ├── logo.html │ │ └── menu-footer.html ├── static │ ├── images │ │ ├── logo.png │ │ ├── favicon.png │ │ └── logo_130_130.png │ └── fonts │ │ ├── MontserratAlt1-Light.woff │ │ └── MontserratAlt1-Light.woff2 ├── content │ ├── client │ │ ├── images │ │ │ ├── gui.png │ │ │ ├── api_server.png │ │ │ ├── arch_overview.png │ │ │ └── vector_storage.png │ │ ├── testbed │ │ │ └── images │ │ │ │ ├── test.png │ │ │ │ ├── upload.png │ │ │ │ ├── evaluation.png │ │ │ │ ├── generate.png │ │ │ │ ├── generation.png │ │ │ │ ├── qa_dataset.png │ │ │ │ └── evaluation_report.png │ │ ├── tools │ │ │ ├── images │ │ │ │ ├── embed.png │ │ │ │ ├── split.png │ │ │ │ ├── chatbot_input_bar.png │ │ │ │ ├── chatbot_rephrase.png │ │ │ │ ├── prompt_eng_system.png │ │ │ │ └── prompt_eng_context.png │ │ │ └── _index.md │ │ ├── chatbot │ │ │ └── images │ │ │ │ ├── chatbot_vs.png │ │ │ │ ├── language_parameters.png │ │ │ │ └── chatbot_history_context.png │ │ ├── configuration │ │ │ ├── images │ │ │ │ ├── models_add.png │ │ │ │ ├── oci_config.png │ │ │ │ ├── models_config.png │ │ │ │ ├── database_config.png │ │ │ │ ├── settings_upload.png │ │ │ │ ├── settings_download.png │ │ │ │ └── settings_spring_ai.png │ │ │ ├── settings.md │ │ │ └── _index.md │ │ └── api_server │ │ │ ├── images │ │ │ ├── api_server_config.png │ │ │ ├── api_server_activity.png │ │ │ └── api_server_settings.png │ │ │ └── _index.md │ ├── advanced │ │ ├── images │ │ │ ├── export.png │ │ │ ├── rag_tool.png │ │ │ ├── infra_oci.png │ │ │ ├── iac_stack_k8s_info.png │ │ │ ├── iac_stack_vm_info.png │ │ │ ├── iac_stack_information.png │ │ │ ├── iac_stack_k8s_optimizer.png │ │ │ ├── iac_stack_review_apply.png │ │ │ ├── iac_stack_vm_optimizer.png │ │ │ ├── iac_stack_access_control.png │ │ │ └── iac_stack_k8s_access_control.png │ │ └── _index.md │ ├── walkthrough │ │ └── images │ │ │ ├── models_edit.png │ │ │ ├── split_embed_web.png │ │ │ ├── chatbot_no_models.png │ │ │ ├── chatbot_say_hello.png │ │ │ ├── chatbot_vs_enable.png │ │ │ ├── models_enable_llm.png │ │ │ └── models_enable_embed.png │ └── help │ │ ├── _index.md │ │ └── troubleshooting │ │ └── _index.md ├── demo │ └── README.md ├── .gitignore ├── assets │ └── css │ │ ├── fonts.css │ │ ├── theme-docs-dark.css │ │ └── theme-docs-light.css ├── README.md └── hugo.toml ├── opentofu ├── versions.tf ├── modules │ ├── network │ │ ├── provider.tf │ │ ├── variables.tf │ │ └── output.tf │ ├── vm │ │ ├── provider.tf │ │ ├── locals.tf │ │ ├── variables.tf │ │ ├── iam.tf │ │ ├── data.tf │ │ └── nsgs.tf │ └── kubernetes │ │ ├── provider.tf │ │ ├── output.tf │ │ ├── cfgmgt_optimizer.tf │ │ ├── templates │ │ ├── cloudinit-oke.sh │ │ └── ai-optimizer-values.yaml │ │ ├── cfgmgt.tf │ │ ├── data.tf │ │ └── variables.tf ├── .gitignore ├── examples │ ├── vm-arm-shape.tfvars │ ├── k8s-byo-other-db.tfvars │ ├── vm-byo-adb.tfvars │ ├── k8s-new-adb.tfvars │ ├── vm-byo-other-db.tfvars │ ├── vm-new-adb.tfvars │ └── README.md ├── data.tf ├── output.tf ├── module_network.tf ├── provider.tf └── module_vm.tf ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── 3-doc_improvement.yml │ └── 1-feature_request.yml └── workflows │ └── pytest.yml ├── .dockerignore ├── tests ├── unit │ ├── conftest.py │ ├── common │ │ └── test_version.py │ ├── client │ │ └── conftest.py │ └── server │ │ ├── bootstrap │ │ ├── conftest.py │ │ └── test_bootstrap_module_config.py │ │ └── api │ │ └── utils │ │ └── test_utils_module_config.py ├── integration │ ├── conftest.py │ ├── client │ │ ├── content │ │ │ └── test_testbed.py │ │ └── utils │ │ │ └── test_st_footer.py │ └── server │ │ └── api │ │ └── v1 │ │ └── test_probes.py └── conftest.py ├── pytest.ini ├── widget ├── index.html └── app.js ├── .yamllint ├── SECURITY.md ├── LICENSE.txt ├── pyproject.toml ├── CONTRIBUTING.md └── .gitignore /src/client/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /helm/.helmignore: -------------------------------------------------------------------------------- 1 | scripts/ -------------------------------------------------------------------------------- /src/client/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/client/content/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/agents/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/api/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/bootstrap/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/mcp/tools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/client/content/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/client/content/tools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/mcp/prompts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/mcp/proxies/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/server/mcp/resources/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/client/content/config/tabs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/client/content/tools/tabs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/layouts/shortcodes/short_app_ref.html: -------------------------------------------------------------------------------- 1 | {{ .Site.Params.ShortName }} -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: dev 4 | -------------------------------------------------------------------------------- /src/client/media/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/src/client/media/logo.png -------------------------------------------------------------------------------- /docs/static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/static/images/logo.png -------------------------------------------------------------------------------- /src/client/mcp/rag/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/src/client/mcp/rag/cover.png -------------------------------------------------------------------------------- /src/client/media/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/src/client/media/favicon.png -------------------------------------------------------------------------------- /docs/layouts/shortcodes/full_app_ref.html: -------------------------------------------------------------------------------- 1 | {{ .Site.Params.LongName }} (the {{ .Site.Params.ShortName }}) -------------------------------------------------------------------------------- /docs/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/static/images/favicon.png -------------------------------------------------------------------------------- /src/server/etc/README.md: -------------------------------------------------------------------------------- 1 | # etc 2 | 3 | Director to store settings files for automatic consumption on startup. 4 | -------------------------------------------------------------------------------- /docs/content/client/images/gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/images/gui.png -------------------------------------------------------------------------------- /src/server/bootstrap/README.md: -------------------------------------------------------------------------------- 1 | # Bootstrap 2 | 3 | To avoid circular logic, bootstrap should only call utils (not core) -------------------------------------------------------------------------------- /docs/static/images/logo_130_130.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/static/images/logo_130_130.png -------------------------------------------------------------------------------- /src/client/mcp/rag/images/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/src/client/mcp/rag/images/export.png -------------------------------------------------------------------------------- /docs/content/advanced/images/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/export.png -------------------------------------------------------------------------------- /docs/layouts/shortcodes/imagelink.html: -------------------------------------------------------------------------------- 1 | 2 | {{ .Get 3 | -------------------------------------------------------------------------------- /src/client/mcp/rag/images/rag_tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/src/client/mcp/rag/images/rag_tool.png -------------------------------------------------------------------------------- /docs/content/advanced/images/rag_tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/rag_tool.png -------------------------------------------------------------------------------- /docs/content/client/images/api_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/images/api_server.png -------------------------------------------------------------------------------- /docs/content/advanced/images/infra_oci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/infra_oci.png -------------------------------------------------------------------------------- /docs/content/client/images/arch_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/images/arch_overview.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/test.png -------------------------------------------------------------------------------- /docs/content/client/tools/images/embed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/tools/images/embed.png -------------------------------------------------------------------------------- /docs/content/client/tools/images/split.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/tools/images/split.png -------------------------------------------------------------------------------- /docs/static/fonts/MontserratAlt1-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/static/fonts/MontserratAlt1-Light.woff -------------------------------------------------------------------------------- /docs/static/fonts/MontserratAlt1-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/static/fonts/MontserratAlt1-Light.woff2 -------------------------------------------------------------------------------- /docs/content/client/images/vector_storage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/images/vector_storage.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/upload.png -------------------------------------------------------------------------------- /docs/content/client/chatbot/images/chatbot_vs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/chatbot/images/chatbot_vs.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/evaluation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/evaluation.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/generate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/generate.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/generation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/generation.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/qa_dataset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/qa_dataset.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/models_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/models_edit.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_k8s_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_k8s_info.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_vm_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_vm_info.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/split_embed_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/split_embed_web.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_information.png -------------------------------------------------------------------------------- /docs/content/client/tools/images/chatbot_input_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/tools/images/chatbot_input_bar.png -------------------------------------------------------------------------------- /docs/content/client/tools/images/chatbot_rephrase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/tools/images/chatbot_rephrase.png -------------------------------------------------------------------------------- /docs/content/client/tools/images/prompt_eng_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/tools/images/prompt_eng_system.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/chatbot_no_models.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/chatbot_no_models.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/chatbot_say_hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/chatbot_say_hello.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/chatbot_vs_enable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/chatbot_vs_enable.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/models_enable_llm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/models_enable_llm.png -------------------------------------------------------------------------------- /src/server/api/utils/README.md: -------------------------------------------------------------------------------- 1 | # Utils 2 | 3 | Utils relies on core, which establishes the bootstrap objects/settings. Scripts here will reference other utils. -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_k8s_optimizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_k8s_optimizer.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_review_apply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_review_apply.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_vm_optimizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_vm_optimizer.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/models_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/models_add.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/oci_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/oci_config.png -------------------------------------------------------------------------------- /docs/content/client/testbed/images/evaluation_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/testbed/images/evaluation_report.png -------------------------------------------------------------------------------- /docs/content/client/tools/images/prompt_eng_context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/tools/images/prompt_eng_context.png -------------------------------------------------------------------------------- /docs/content/walkthrough/images/models_enable_embed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/walkthrough/images/models_enable_embed.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_access_control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_access_control.png -------------------------------------------------------------------------------- /docs/content/client/api_server/images/api_server_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/api_server/images/api_server_config.png -------------------------------------------------------------------------------- /docs/content/client/chatbot/images/language_parameters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/chatbot/images/language_parameters.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/models_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/models_config.png -------------------------------------------------------------------------------- /docs/content/advanced/images/iac_stack_k8s_access_control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/advanced/images/iac_stack_k8s_access_control.png -------------------------------------------------------------------------------- /docs/content/client/api_server/images/api_server_activity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/api_server/images/api_server_activity.png -------------------------------------------------------------------------------- /docs/content/client/api_server/images/api_server_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/api_server/images/api_server_settings.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/database_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/database_config.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/settings_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/settings_upload.png -------------------------------------------------------------------------------- /docs/content/client/chatbot/images/chatbot_history_context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/chatbot/images/chatbot_history_context.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/settings_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/settings_download.png -------------------------------------------------------------------------------- /docs/content/client/configuration/images/settings_spring_ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/ai-optimizer/HEAD/docs/content/client/configuration/images/settings_spring_ai.png -------------------------------------------------------------------------------- /src/client/mcp/todo_list.md: -------------------------------------------------------------------------------- 1 | - [ ] Analyze requirements 2 | - [ ] Set up necessary files 3 | - [ ] Implement main functionality 4 | - [ ] Handle edge cases 5 | - [ ] Test the implementation 6 | - [ ] Verify results 7 | -------------------------------------------------------------------------------- /docs/content/help/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = 'Get Help' 3 | +++ 4 | 5 | -------------------------------------------------------------------------------- /src/client/mcp/rag/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | Main module for RAG functionality. 3 | """ 4 | 5 | 6 | def main(): 7 | """ 8 | Entry point for the RAG module. 9 | """ 10 | print("Hello from rag!") 11 | 12 | 13 | if __name__ == "__main__": 14 | main() 15 | -------------------------------------------------------------------------------- /docs/layouts/shortcodes/latest_release.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/demo/README.md: -------------------------------------------------------------------------------- 1 | ## Demo: OracleVS extension for no data duplication in vectorstore 2 | 3 | Demo to show an *experimental* implementation of a "referenced" vectorstore, coming by a relational table data source. 4 | 5 | Run the Jupyter Notepad `oraclevs_new.ipynb` and follow the instructions and explanation there. -------------------------------------------------------------------------------- /src/client/spring_ai/ollama-values.yaml: -------------------------------------------------------------------------------- 1 | ollama: 2 | gpu: 3 | enabled: true 4 | type: 'nvidia' 5 | number: 1 6 | models: 7 | - llama3.1 8 | - llama3.2 9 | - mxbai-embed-large 10 | - nomic-embed-text 11 | nodeSelector: 12 | node.kubernetes.io/instance-type: VM.GPU.A10.1 13 | -------------------------------------------------------------------------------- /src/server/api/v1/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | 6 | from . import chat, databases, embed, models, oci, probes, testbed, settings, mcp, mcp_prompts 7 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Documentation Specific 3 | ############################################################################## 4 | /themes/ 5 | /public/ 6 | hugo_stats.json 7 | 8 | # Temporary lock file while building 9 | /.hugo_build.lock -------------------------------------------------------------------------------- /opentofu/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | 4 | # Do Not Modify. Updated during release cycle. 5 | locals { 6 | app_version = "0.0.0" 7 | compute_os_ver = "8.10" 8 | k8s_version = "1.34.1" 9 | } -------------------------------------------------------------------------------- /docs/assets/css/fonts.css: -------------------------------------------------------------------------------- 1 | @import "fonts.css"; 2 | 3 | @font-face { 4 | font-family: 'MontserratAlt1-Light'; 5 | src: url('/ai-optimizer/fonts/MontserratAlt1-Light.woff2') format('woff2'), 6 | url('/ai-optimizer/fonts/MontserratAlt1-Light.woff') format('woff'); 7 | font-weight: normal; 8 | font-style: normal; 9 | font-size: smaller; 10 | } -------------------------------------------------------------------------------- /opentofu/modules/network/provider.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | terraform { 6 | required_providers { 7 | oci = { 8 | source = "oracle/oci" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/common/_version.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | 6 | from importlib.metadata import version, PackageNotFoundError 7 | 8 | try: 9 | __version__ = version("ai-optimizer") 10 | except PackageNotFoundError: 11 | __version__ = "0.0.0" 12 | -------------------------------------------------------------------------------- /docs/content/advanced/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = 'Advanced' 3 | weight = 40 4 | +++ 5 | 9 | 10 | There is a lot more you can do with the {{< short_app_ref >}}. Explore some of the more Advanced capabilities here: 11 | 12 | {{% children %}} -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 📖 Documentation 4 | url: https://oracle.github.io/ai-optimizer/ 5 | about: Learn more about how to use the AI Optimizer and Toolkit 6 | - name: ❓ Anything else? 7 | url: https://oracledevs.slack.com/archives/C089NPXG8AU 8 | about: Ask questions or provide feedback on the AI Optimizer and Toolkit community Slack channel -------------------------------------------------------------------------------- /opentofu/modules/vm/provider.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | terraform { 6 | required_providers { 7 | oci = { 8 | source = "oracle/oci" 9 | configuration_aliases = [oci.home_region] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/provider.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | terraform { 6 | required_providers { 7 | oci = { 8 | source = "oracle/oci" 9 | configuration_aliases = [oci.home_region] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | [global] 4 | disableWidgetStateDuplicationWarning = true 5 | 6 | [browser] 7 | gatherUsageStats = false 8 | serverAddress = "localhost" 9 | 10 | [server] 11 | cookieSecret = "oaie-client-cookie" 12 | headless = true 13 | 14 | [client] 15 | toolbarMode = "minimal" -------------------------------------------------------------------------------- /src/server/bootstrap/bootstrap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore genai 6 | 7 | from server.bootstrap import databases, models, oci, settings 8 | from common import logging_config 9 | 10 | logger = logging_config.logging.getLogger("bootstrap") 11 | 12 | DATABASE_OBJECTS = databases.main() 13 | MODEL_OBJECTS = models.main() 14 | OCI_OBJECTS = oci.main() 15 | SETTINGS_OBJECTS = settings.main() 16 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: ai-optimizer 3 | description: A Helm chart Oracle AI Optimizer and Toolkit 4 | # Do Not Modify. Updated automatically during release cycle by .github/workflows/releases.yml 5 | version: 0.0.0 6 | appVersion: "0.0.0" 7 | type: application 8 | home: https://github.com/oracle/ai-optimizer 9 | sources: 10 | - https://github.com/oracle/ai-optimizer 11 | icon: https://github.com/oracle/ai-optimizer/blob/main/src/client/media/logo.png 12 | maintainers: 13 | - name: Oracle 14 | email: obaas_ww@oracle.com 15 | url: https://github.com/oracle/ai-optimizer 16 | -------------------------------------------------------------------------------- /opentofu/.gitignore: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # IaC 3 | ############################################################################## 4 | # Ignore all tfvars files (contain credentials) 5 | **/**.tfvars 6 | # But allow example tfvars files for CI/CD testing (safe, no real credentials) 7 | !examples/*.tfvars 8 | 9 | # Terraform/OpenTofu state and cache 10 | **/.terraform* 11 | **/terraform.tfstate* 12 | **/*.tfplan 13 | **/*.tfplan.out 14 | 15 | # Private keys and sensitive files 16 | **/*.pem 17 | 18 | # Stage directory 19 | **/stage/*.* 20 | **/stage/kubeconfig -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | 4 | # Ignore everything 5 | ** 6 | 7 | # Keep the src directory and pyproject.toml file 8 | !src/ 9 | !pyproject.toml 10 | 11 | # Inside src, ignore specific things 12 | src/**/Dockerfile* 13 | src/**/__pycache__/ 14 | src/**/.pytest_cache/ 15 | src/**/tns_admin/ 16 | src/**/.oci/ 17 | src/**/.* 18 | src/**/*.sh 19 | src/**/*.log 20 | 21 | # But explicitly keep these 22 | !src/.streamlit 23 | !src/client/spring_ai/templates/start.sh 24 | !src/entrypoint.sh -------------------------------------------------------------------------------- /helm/templates/global-api-secret.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{ include "global.apiKeyOrSecretName.required" . }} 6 | 7 | {{- if .Values.global.api.apiKey }} 8 | apiVersion: v1 9 | kind: Secret 10 | metadata: 11 | name: {{ include "global.apiSecretName" . }} 12 | labels: 13 | {{- include "global.labels" . | nindent 4 }} 14 | type: Opaque 15 | data: 16 | "{{ include "global.apiSecretKey" . }}": "{{ .Values.global.api.apiKey | b64enc }}" 17 | {{- end }} -------------------------------------------------------------------------------- /opentofu/examples/vm-arm-shape.tfvars: -------------------------------------------------------------------------------- 1 | # Example: VM with ARM (Ampere) compute shape 2 | 3 | # Run: examples/test.sh 4 | 5 | # Deployment Configuration 6 | label_prefix = "CITEST" 7 | optimizer_version = "Stable" 8 | infrastructure = "VM" 9 | 10 | # New ADB with BYOL 11 | adb_ecpu_core_count = 4 12 | adb_license_model = "BRING_YOUR_OWN_LICENSE" 13 | adb_edition = "ENTERPRISE_EDITION" 14 | adb_networking = "SECURE_ACCESS" 15 | adb_whitelist_cidrs = "192.168.0.0/16" 16 | 17 | # ARM Compute Shape 18 | compute_cpu_shape = "VM.Standard.A1.Flex" 19 | compute_cpu_ocpu = 4 20 | 21 | # Load Balancer 22 | lb_min_shape = 10 23 | lb_max_shape = 10 24 | -------------------------------------------------------------------------------- /opentofu/examples/k8s-byo-other-db.tfvars: -------------------------------------------------------------------------------- 1 | # Example: Kubernetes with BYO Other Database (non-ADB) 2 | 3 | # Run: examples/test.sh 4 | 5 | # Deployment Configuration 6 | label_prefix = "CITEST" 7 | optimizer_version = "Experimental" 8 | infrastructure = "Kubernetes" 9 | 10 | # BYO Other Database 11 | byo_db_type = "OTHER" 12 | byo_db_password = "FakePassword123!NotReal" 13 | byo_odb_host = "fake-db-host.example.com" 14 | byo_odb_port = 1521 15 | byo_odb_service = "FAKEPDB.example.com" 16 | 17 | # Compute 18 | compute_cpu_shape = "VM.Standard.A1.Flex" 19 | compute_cpu_ocpu = 4 20 | 21 | # Load Balancer 22 | lb_min_shape = 10 23 | lb_max_shape = 50 24 | -------------------------------------------------------------------------------- /opentofu/examples/vm-byo-adb.tfvars: -------------------------------------------------------------------------------- 1 | # Example: VM deployment with BYO Autonomous Database 2 | 3 | # Run: examples/test.sh 4 | 5 | # Deployment Configuration 6 | label_prefix = "CITEST" 7 | optimizer_version = "Stable" 8 | infrastructure = "VM" 9 | 10 | # BYO Autonomous Database 11 | byo_db_type = "ADB-S" 12 | byo_adb_ocid = "ocid1.autonomousdatabase.oc1.phx.aaaaaaaafakeadbocidforgithubactions" 13 | byo_db_password = "FakePassword123!NotReal" 14 | 15 | # Compute 16 | compute_cpu_shape = "VM.Standard.E5.Flex" 17 | compute_cpu_ocpu = 2 18 | 19 | # Load Balancer 20 | lb_min_shape = 10 21 | lb_max_shape = 10 22 | 23 | # Network Access 24 | client_allowed_cidrs = "10.0.0.0/8" 25 | server_allowed_cidrs = "10.0.0.0/8" 26 | -------------------------------------------------------------------------------- /opentofu/examples/k8s-new-adb.tfvars: -------------------------------------------------------------------------------- 1 | # Example: Kubernetes deployment with new Autonomous Database 2 | 3 | # Run: examples/test.sh 4 | 5 | # Deployment Configuration 6 | label_prefix = "CITEST" 7 | optimizer_version = "Stable" 8 | infrastructure = "Kubernetes" 9 | 10 | # New Autonomous Database 11 | adb_ecpu_core_count = 2 12 | adb_data_storage_size_in_gb = 20 13 | adb_is_cpu_auto_scaling_enabled = true 14 | adb_license_model = "LICENSE_INCLUDED" 15 | adb_networking = "PRIVATE_ENDPOINT_ACCESS" 16 | adb_whitelist_cidrs = "" 17 | 18 | # Compute 19 | compute_cpu_shape = "VM.Standard.E4.Flex" 20 | compute_cpu_ocpu = 2 21 | 22 | # Load Balancer 23 | lb_min_shape = 10 24 | lb_max_shape = 100 25 | -------------------------------------------------------------------------------- /opentofu/examples/vm-byo-other-db.tfvars: -------------------------------------------------------------------------------- 1 | # Example: VM deployment with BYO Other Database (non-ADB) 2 | 3 | # Run: examples/test.sh 4 | 5 | # Deployment Configuration 6 | label_prefix = "CITEST" 7 | optimizer_version = "Stable" 8 | infrastructure = "VM" 9 | 10 | # BYO Other Database 11 | byo_db_type = "OTHER" 12 | byo_db_password = "FakePassword123!NotReal" 13 | byo_odb_host = "fake-db-host.example.com" 14 | byo_odb_port = 1521 15 | byo_odb_service = "FAKEPDB.example.com" 16 | 17 | # Compute 18 | compute_cpu_shape = "VM.Standard.E5.Flex" 19 | compute_cpu_ocpu = 2 20 | 21 | # Load Balancer 22 | lb_min_shape = 10 23 | lb_max_shape = 10 24 | 25 | # Network Access 26 | client_allowed_cidrs = "10.0.0.0/8" 27 | server_allowed_cidrs = "10.0.0.0/8" 28 | -------------------------------------------------------------------------------- /helm/templates/client/service.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if .Values.client.enabled }} 6 | apiVersion: v1 7 | kind: Service 8 | metadata: 9 | name: {{ include "global.fullname" . }}-client-http 10 | labels: 11 | app.kubernetes.io/component: client 12 | {{- include "global.labels" . | nindent 4 }} 13 | spec: 14 | type: {{ .Values.client.service.type }} 15 | ports: 16 | - protocol: TCP 17 | port: 80 18 | targetPort: 8501 19 | selector: 20 | app.kubernetes.io/component: client 21 | {{- include "global.selectorLabels" . | nindent 4 }} 22 | {{ end -}} -------------------------------------------------------------------------------- /helm/examples/values-kind-adb-free.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore sidb ollama 4 | 5 | # Example Helm Values for Containerized ADB 6 | server: 7 | replicaCount: 1 8 | image: 9 | repository: localhost/ai-optimizer-server 10 | tag: latest 11 | database: 12 | type: "ADB-FREE" 13 | image: 14 | repository: container-registry.oracle.com/database/adb-free 15 | tag: latest 16 | client: 17 | replicaCount: 1 18 | image: 19 | repository: localhost/ai-optimizer-client 20 | tag: latest 21 | ollama: 22 | enabled: true 23 | replicaCount: 1 24 | models: 25 | enabled: true 26 | -------------------------------------------------------------------------------- /helm/examples/values-kind-sidb-free.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore sidb ollama 4 | 5 | # Example Helm Values for Containerized SIDB 6 | server: 7 | replicaCount: 1 8 | image: 9 | repository: localhost/ai-optimizer-server 10 | tag: latest 11 | database: 12 | type: "SIDB-FREE" 13 | image: 14 | repository: container-registry.oracle.com/database/free 15 | tag: latest 16 | client: 17 | replicaCount: 1 18 | image: 19 | repository: localhost/ai-optimizer-client 20 | tag: latest 21 | ollama: 22 | enabled: true 23 | replicaCount: 1 24 | models: 25 | enabled: true 26 | -------------------------------------------------------------------------------- /helm/templates/ollama/service-11434.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent ollama 4 | 5 | {{- if .Values.ollama.enabled }} 6 | apiVersion: v1 7 | kind: Service 8 | metadata: 9 | name: {{ include "ollama.serviceName" . }} 10 | labels: 11 | app.kubernetes.io/component: ollama 12 | {{- include "global.labels" . | nindent 4 }} 13 | spec: 14 | type: "ClusterIP" 15 | ports: 16 | - port: 11434 17 | targetPort: api 18 | protocol: TCP 19 | name: api 20 | selector: 21 | app.kubernetes.io/component: ollama 22 | {{ include "global.selectorLabels" . | nindent 4 }} 23 | {{ end -}} -------------------------------------------------------------------------------- /helm/templates/server/database/adb-wallet-secret.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | # ADB Wallet Password Secret 6 | {{- if .Values.server.database }} 7 | {{- if eq (include "server.database.isADBS" .) "true" }} 8 | apiVersion: v1 9 | kind: Secret 10 | metadata: 11 | name: {{ .Release.Name }}-adb-wallet-pass-{{ .Release.Revision }} 12 | labels: 13 | app.kubernetes.io/component: database 14 | {{- include "global.labels" . | nindent 4 }} 15 | stringData: 16 | {{ .Release.Name }}-adb-wallet-pass-{{ .Release.Revision }}: {{ include "server.randomPassword" . | quote }} 17 | {{- end }} 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /opentofu/modules/network/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | variable "compartment_id" { 6 | type = string 7 | } 8 | 9 | variable "label_prefix" { 10 | type = string 11 | } 12 | 13 | variable "infra" { 14 | type = string 15 | } 16 | 17 | variable "vcn_cidr" { 18 | type = map(any) 19 | default = { 20 | "VM" = ["10.42.0.0/27"] 21 | "Kubernetes" = ["10.42.0.0/16"] 22 | } 23 | } 24 | 25 | variable "oci_services" { 26 | description = "OCI Services Network object containing id, name, and cidr_block" 27 | type = object({ 28 | cidr_block = string 29 | id = string 30 | name = string 31 | }) 32 | } -------------------------------------------------------------------------------- /docs/content/client/tools/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = 'Tools' 3 | menus = 'main' 4 | weight = 90 5 | +++ 6 | 7 | 11 | 12 | The {{< full_app_ref >}} has many features that can be used with Large Language Models. 13 | 14 | ## 📚 Split/Embed 15 | 16 | Splitting and/or Embedding unstructured data is the foundation to Oracle Database Vector Search. 17 | 18 | ## 🎤 Prompts 19 | 20 | Prompts are a set of instructions given to the language model to guide the response. They are used to set the context or define the kind of response you are expecting. The {{< short_app_ref >}} provides both System and Context example prompts and allows you to modify these prompts to your needs. 21 | -------------------------------------------------------------------------------- /opentofu/data.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | data "oci_identity_availability_domains" "all" { 6 | compartment_id = var.tenancy_ocid 7 | } 8 | 9 | data "oci_core_services" "core_services" { 10 | filter { 11 | name = "name" 12 | values = ["All .* Services In Oracle Services Network"] 13 | regex = true 14 | } 15 | } 16 | 17 | data "oci_database_autonomous_database" "byo_adb" { 18 | for_each = var.byo_db_type == "ADB-S" ? { byo = true } : {} 19 | autonomous_database_id = var.byo_adb_ocid 20 | } 21 | 22 | data "oci_core_subnet" "byo_vcn_private" { 23 | count = var.byo_vcn_ocid != "" ? 1 : 0 24 | subnet_id = var.byo_private_subnet_ocid 25 | } -------------------------------------------------------------------------------- /opentofu/examples/vm-new-adb.tfvars: -------------------------------------------------------------------------------- 1 | # Example: VM deployment with new Autonomous Database 2 | 3 | # Run: examples/test.sh 4 | 5 | # Deployment Configuration 6 | label_prefix = "CITEST" 7 | optimizer_version = "Stable" 8 | infrastructure = "VM" 9 | 10 | # New Autonomous Database (not BYO) 11 | # byo_db_type not set - will create new ADB 12 | adb_ecpu_core_count = 2 13 | adb_data_storage_size_in_gb = 20 14 | adb_is_cpu_auto_scaling_enabled = true 15 | adb_license_model = "LICENSE_INCLUDED" 16 | adb_networking = "SECURE_ACCESS" 17 | adb_whitelist_cidrs = "0.0.0.0/0" 18 | 19 | # Compute 20 | compute_cpu_shape = "VM.Standard.E5.Flex" 21 | compute_cpu_ocpu = 2 22 | 23 | # Load Balancer 24 | lb_min_shape = 10 25 | lb_max_shape = 10 26 | 27 | # Network Access 28 | client_allowed_cidrs = "0.0.0.0/0" 29 | server_allowed_cidrs = "0.0.0.0/0" 30 | -------------------------------------------------------------------------------- /tests/unit/conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Pytest configuration for unit tests. 6 | 7 | This conftest automatically marks all tests in the test/unit/ directory 8 | with the 'unit' marker, enabling selective test execution: 9 | 10 | pytest -m "unit" # Run only unit tests 11 | pytest -m "not unit" # Skip unit tests 12 | pytest -m "unit and not slow" # Fast unit tests only 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | def pytest_collection_modifyitems(items): 19 | """Automatically add 'unit' marker to all tests in this directory.""" 20 | for item in items: 21 | # Check if the test is under test/unit/ 22 | if "/test/unit/" in str(item.fspath): 23 | item.add_marker(pytest.mark.unit) 24 | -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | output "kubeconfig_cmd" { 6 | description = "Command to generate kubeconfig file" 7 | value = format( 8 | "oci ce cluster create-kubeconfig --cluster-id %s --region %s --token-version 2.0.0 --kube-endpoint %s --file $HOME/.kube/config --with-auth-context --profile DEFAULT", 9 | oci_containerengine_cluster.default_cluster.id, 10 | var.region, 11 | oci_containerengine_cluster.default_cluster.endpoint_config[0].is_public_ip_enabled ? "PUBLIC_ENDPOINT" : "PRIVATE_ENDPOINT" 12 | ) 13 | } 14 | 15 | output "helm_manual_instructions" { 16 | description = "Instructions for manual Helm deployment (when cfgmgt was skipped)" 17 | value = local.should_show_manual_steps ? local.manual_helm_instructions : null 18 | } -------------------------------------------------------------------------------- /helm/templates/server/database/priv-secret.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | # Database Privileged User Secret 6 | {{- if .Values.server.database }} 7 | {{- $secretName := include "server.databasePrivSecret" . }} 8 | {{- $secret_existing := lookup "v1" "Secret" .Release.Namespace $secretName }} 9 | {{- if not $secret_existing }} 10 | apiVersion: v1 11 | kind: Secret 12 | metadata: 13 | name: {{ $secretName }} 14 | labels: 15 | app.kubernetes.io/component: database 16 | {{- include "global.labels" . | nindent 4 }} 17 | annotations: 18 | helm.sh/resource-policy: keep 19 | type: Opaque 20 | stringData: 21 | username: {{ if eq (include "server.database.isADB" .) "true" }}"ADMIN"{{ else }}"SYSTEM"{{ end }} 22 | password: {{ include "server.randomPassword" . | quote }} 23 | {{- end }} 24 | {{- end }} 25 | -------------------------------------------------------------------------------- /tests/integration/conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Pytest configuration for integration tests. 6 | 7 | This conftest automatically marks all tests in the test/integration/ directory 8 | with the 'integration' marker, enabling selective test execution: 9 | 10 | pytest -m "integration" # Run only integration tests 11 | pytest -m "not integration" # Skip integration tests 12 | pytest -m "integration and not db" # Integration tests without DB 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | def pytest_collection_modifyitems(items): 19 | """Automatically add 'integration' marker to all tests in this directory.""" 20 | for item in items: 21 | # Check if the test is under test/integration/ 22 | if "/test/integration/" in str(item.fspath): 23 | item.add_marker(pytest.mark.integration) 24 | -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/model/ChatMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | 6 | package org.springframework.ai.openai.samples.helloworld.model; 7 | 8 | 9 | public class ChatMessage { 10 | private String role; 11 | private String content; 12 | 13 | public ChatMessage() {} 14 | 15 | public ChatMessage(String role, String content) { 16 | this.role = role; 17 | this.content = content; 18 | } 19 | 20 | public String getRole() { 21 | return role; 22 | } 23 | 24 | public void setRole(String role) { 25 | this.role = role; 26 | } 27 | 28 | public String getContent() { 29 | return content; 30 | } 31 | 32 | public void setContent(String content) { 33 | this.content = content; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /opentofu/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | output "app_version" { 6 | description = "Application Version" 7 | value = local.app_version 8 | } 9 | 10 | output "app_name" { 11 | description = "Application Name (Label). The namespace for K8s installations" 12 | value = local.label_prefix 13 | } 14 | 15 | output "optimizer_client_url" { 16 | description = "URL for AI Optimizer and Toolkit Client Access" 17 | value = var.deploy_optimizer ? format("http://%s", oci_load_balancer_load_balancer.lb.ip_address_details[0].ip_address) : "N/A" 18 | } 19 | 20 | output "optimizer_server_url" { 21 | description = "URL for AI Optimizer and Toolkit Server API Access" 22 | value = var.deploy_optimizer ? format("http://%s:8000/v1/docs", oci_load_balancer_load_balancer.lb.ip_address_details[0].ip_address) : "N/A" 23 | } 24 | -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/model/ChatStreamResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | package org.springframework.ai.openai.samples.helloworld.model; 6 | 7 | 8 | public class ChatStreamResponse { 9 | private String object; 10 | private ChatChoice[] choices; 11 | 12 | public ChatStreamResponse() {} 13 | 14 | public ChatStreamResponse(String object, ChatChoice[] choices) { 15 | this.object = object; 16 | this.choices = choices; 17 | } 18 | 19 | public String getObject() { 20 | return object; 21 | } 22 | 23 | public void setObject(String object) { 24 | this.object = object; 25 | } 26 | 27 | public ChatChoice[] getChoices() { 28 | return choices; 29 | } 30 | 31 | public void setChoices(ChatChoice[] choices) { 32 | this.choices = choices; 33 | } 34 | } -------------------------------------------------------------------------------- /helm/examples/values-kind-other.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore sidb ollama 4 | 5 | # Example Helm Values for external databases 6 | server: 7 | replicaCount: 1 8 | image: 9 | repository: localhost/ai-optimizer-server 10 | tag: latest 11 | database: 12 | type: "OTHER" 13 | other: 14 | # Option 1: Provide full DSN string 15 | dsn: "mydbhost.example.com:1521/MYSERVICE" 16 | # Option 2: Provide individual components (commented out when using dsn) 17 | # host: "mydbhost.example.com" 18 | # port: "1521" 19 | # service_name: "MYSERVICE" 20 | privAuthN: 21 | secretName: "db-priv-authn" 22 | passwordKey: "password" 23 | client: 24 | replicaCount: 1 25 | image: 26 | repository: localhost/ai-optimizer-client 27 | tag: latest 28 | ollama: 29 | enabled: true 30 | replicaCount: 1 31 | models: 32 | enabled: true 33 | -------------------------------------------------------------------------------- /src/client/content/tools/tools.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | 6 | import inspect 7 | import streamlit as st 8 | 9 | from client.content.tools.tabs.prompt_eng import get_prompts, display_prompt_eng 10 | from client.content.tools.tabs.split_embed import display_split_embed 11 | from client.content.config.tabs.models import get_models 12 | from client.content.config.tabs.databases import get_databases 13 | from client.content.config.tabs.oci import get_oci 14 | 15 | 16 | def main() -> None: 17 | """Streamlit GUI""" 18 | prompt_eng, split_embed = st.tabs(["🎤 Prompts", "📚 Split/Embed"]) 19 | 20 | with prompt_eng: 21 | get_prompts() 22 | display_prompt_eng() 23 | with split_embed: 24 | get_models() 25 | get_databases() 26 | get_oci() 27 | display_split_embed() 28 | 29 | 30 | if __name__ == "__main__" or "page.py" in inspect.stack()[1].filename: 31 | main() 32 | -------------------------------------------------------------------------------- /helm/templates/client/configmap.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if .Values.client.enabled }} 6 | apiVersion: v1 7 | kind: ConfigMap 8 | metadata: 9 | name: {{ include "global.fullname" . }}-st-config 10 | labels: 11 | app.kubernetes.io/component: client 12 | {{- include "global.labels" . | nindent 4}} 13 | data: 14 | config.toml: | 15 | [global] 16 | disableWidgetStateDuplicationWarning = true 17 | 18 | [browser] 19 | gatherUsageStats = false 20 | serverAddress = "0.0.0.0" 21 | 22 | [server] 23 | port = "8501" 24 | cookieSecret = "{{ randAlphaNum 32 | b64enc }}" 25 | headless = true 26 | fileWatcherType = "none" 27 | {{- $path := include "global.getPath" . }} 28 | {{- if ne $path "/" }} 29 | baseUrlPath = {{ include "global.getPath" . | quote }} 30 | {{- end }} 31 | 32 | [client] 33 | toolbarMode = "minimal" 34 | {{ end -}} -------------------------------------------------------------------------------- /opentofu/module_network.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | variable "byo_vcn_ocid" { 6 | description = "Bring Your Own Virtual Cloud Network - VCN OCID" 7 | type = string 8 | default = "" 9 | } 10 | 11 | variable "byo_public_subnet_ocid" { 12 | description = "Bring Your Own Virtual Cloud Network - Pubic Subnet OCID" 13 | type = string 14 | default = "" 15 | } 16 | 17 | variable "byo_private_subnet_ocid" { 18 | description = "Bring Your Own Virtual Cloud Network - Private Subnet OCID" 19 | type = string 20 | default = "" 21 | } 22 | 23 | module "network" { 24 | for_each = var.byo_vcn_ocid == "" ? { managed = true } : {} 25 | source = "./modules/network" 26 | compartment_id = local.compartment_ocid 27 | label_prefix = local.label_prefix 28 | infra = var.infrastructure 29 | oci_services = data.oci_core_services.core_services.services.0 30 | 31 | } -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/cfgmgt_optimizer.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | locals { 6 | optimizer_values = templatefile("${path.module}/templates/ai-optimizer-values.yaml", { 7 | label = var.label_prefix 8 | repository_base = local.repository_base 9 | oci_region = var.region 10 | db_type = var.db_conn.db_type 11 | db_ocid = var.db_ocid 12 | db_dsn = var.db_conn.service 13 | db_name = lower(var.db_name) 14 | node_pool_gpu_deploy = var.node_pool_gpu_deploy 15 | lb_ip = var.lb.ip_address_details[0].ip_address 16 | }) 17 | } 18 | 19 | resource "local_sensitive_file" "optimizer_values" { 20 | count = var.deploy_optimizer ? 1 : 0 21 | content = local.optimizer_values 22 | filename = "${path.root}/cfgmgt/stage/ai-optimizer-values.yaml" 23 | file_permission = 0600 24 | } -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/model/ChatRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | package org.springframework.ai.openai.samples.helloworld.model; 6 | 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class ChatRequest { 12 | private String model; 13 | private List> messages; 14 | private boolean stream; 15 | 16 | public String getModel() { 17 | return model; 18 | } 19 | 20 | public void setModel(String model) { 21 | this.model = model; 22 | } 23 | 24 | public List> getMessages() { 25 | return messages; 26 | } 27 | 28 | public void setMessages(List> messages) { 29 | this.messages = messages; 30 | } 31 | 32 | public boolean isStream() { 33 | return stream; 34 | } 35 | 36 | public void setStream(boolean stream) { 37 | this.stream = stream; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/server/mcp/prompts/cache.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Shared cache for MCP prompt text overrides. 6 | This allows dynamic prompt updates without losing decorator metadata (title, tags). 7 | """ 8 | 9 | # Global cache for prompt text overrides 10 | # Key: prompt_name (str), Value: updated prompt text (str) 11 | prompt_text_overrides = {} 12 | 13 | 14 | def get_override(prompt_name: str) -> str | None: 15 | """Get the override text for a prompt if it exists""" 16 | return prompt_text_overrides.get(prompt_name) 17 | 18 | 19 | def set_override(prompt_name: str, text: str) -> None: 20 | """Set an override text for a prompt""" 21 | prompt_text_overrides[prompt_name] = text 22 | 23 | 24 | def clear_override(prompt_name: str) -> None: 25 | """Clear the override for a prompt, reverting to default""" 26 | prompt_text_overrides.pop(prompt_name, None) 27 | 28 | 29 | def clear_all_overrides() -> None: 30 | """Clear all prompt overrides""" 31 | prompt_text_overrides.clear() 32 | -------------------------------------------------------------------------------- /opentofu/modules/network/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | // VCN 6 | output "vcn_ocid" { 7 | description = "VCN Identifier." 8 | value = oci_core_vcn.vcn.id 9 | } 10 | 11 | output "vcn_cidr_block" { 12 | description = "VCN CIDR Block." 13 | value = one(oci_core_vcn.vcn.cidr_blocks) 14 | } 15 | 16 | // Private Subnet 17 | output "private_subnet_ocid" { 18 | description = "Private Subnet Identifier." 19 | value = try(oci_core_subnet.private.id, null) 20 | } 21 | 22 | output "private_subnet_cidr_block" { 23 | description = "Private Subnet CIDR Block." 24 | value = try(oci_core_subnet.private.cidr_block, null) 25 | } 26 | 27 | // Public Subnet 28 | output "public_subnet_ocid" { 29 | description = "Public Subnet Identifier." 30 | value = oci_core_subnet.public.id 31 | } 32 | 33 | output "public_subnet_cidr_block" { 34 | description = "Public Subnet CIDR Block." 35 | value = oci_core_subnet.public.cidr_block 36 | } -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Oracle AI Optimizer & Toolkit - Documentation 2 | 3 | ## Description 4 | 5 | This directory contains the documentation for the the [**Oracle AI Optimizer & Toolkit**](https://github.com/oracle/ai-optimizer). 6 | 7 | ## Getting Started - Documentation 8 | 9 | The **Oracle AI Optimizer & Toolkit** documentation is powered by [Hugo](https://gohugo.io/) using the [Relearn](https://github.com/McShelby/hugo-theme-relearn) theme. 10 | 11 | To contribute to the documentation, install [Hugo](https://gohugo.io/installation/). Installation instructions vary per Operating System. 12 | 13 | From the `docs` directory: 14 | 15 | 1. Download the [Relearn](https://github.com/McShelby/hugo-theme-relearn) theme 16 | ```bash 17 | mkdir -p themes/relearn 18 | ``` 19 | 20 | ```bash 21 | curl -L $(curl -s https://api.github.com/repos/McShelby/hugo-theme-relearn/releases/latest \ 22 | | grep "tarball_url" | cut -d '"' -f 4) \ 23 | | tar -xz -C themes/relearn --strip-components=1 --exclude='*/exampleSite' 24 | ``` 25 | 26 | 1. Start Hugo: `hugo serve` 27 | 28 | This will serve the documentation on `http://localhost:1313/ai-optimizer/` for review. 29 | -------------------------------------------------------------------------------- /opentofu/modules/vm/locals.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | locals { 6 | streamlit_client_port = 8501 7 | fastapi_server_port = 8000 8 | } 9 | 10 | locals { 11 | cloud_init_compute = templatefile("${path.module}/templates/cloudinit-compute.tpl", { 12 | db_type = var.db_conn.db_type 13 | db_password = var.db_conn.password 14 | db_service = var.db_conn.service 15 | optimizer_version = var.optimizer_version 16 | install_ollama = var.vm_is_gpu_shape ? true : false 17 | }) 18 | 19 | cloud_init_database = templatefile("${path.module}/templates/cloudinit-database.tpl", { 20 | compartment_id = var.compartment_id 21 | db_name = var.db_name 22 | db_type = var.db_conn.db_type 23 | db_dba_user = var.db_conn.username 24 | db_password = var.db_conn.password 25 | db_service = var.db_conn.service 26 | }) 27 | 28 | vm_compute_shape = var.vm_is_gpu_shape ? var.compute_gpu_shape : var.compute_cpu_shape 29 | } -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ; Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | 4 | ; spell-checker: disable 5 | 6 | [pytest] 7 | pythonpath = src tests 8 | addopts = --disable-warnings --import-mode=importlib 9 | filterwarnings = 10 | ignore::DeprecationWarning 11 | asyncio_default_fixture_loop_scope = function 12 | 13 | ; Test markers for selective test execution 14 | ; Usage examples: 15 | ; pytest -m "unit" # Run only unit tests 16 | ; pytest -m "integration" # Run only integration tests 17 | ; pytest -m "not slow" # Skip slow tests 18 | ; pytest -m "not db" # Skip tests requiring database 19 | ; pytest -m "unit and not slow" # Fast unit tests only 20 | markers = 21 | unit: Unit tests (mocked dependencies, fast execution) 22 | integration: Integration tests (real components, may require external services) 23 | slow: Slow tests (deselect with '-m "not slow"') 24 | db: Tests requiring Oracle database container (deselect with '-m "not db"') 25 | db_container: Alias for db marker - tests requiring database container -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/model/ChatChoice.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | package org.springframework.ai.openai.samples.helloworld.model; 6 | 7 | 8 | public class ChatChoice { 9 | private ChatMessage message; 10 | private int index = 0; 11 | private String finish_reason = null; 12 | 13 | public ChatChoice() {} 14 | 15 | public ChatChoice(ChatMessage message) { 16 | this.message = message; 17 | } 18 | 19 | public ChatMessage getMessage() { 20 | return message; 21 | } 22 | 23 | public void setMessage(ChatMessage message) { 24 | this.message = message; 25 | } 26 | 27 | public int getIndex() { 28 | return index; 29 | } 30 | 31 | public void setIndex(int index) { 32 | this.index = index; 33 | } 34 | 35 | public String getFinish_reason() { 36 | return finish_reason; 37 | } 38 | 39 | public void setFinish_reason(String finish_reason) { 40 | this.finish_reason = finish_reason; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/WebCorsConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | package org.springframework.ai.openai.samples.helloworld; 6 | 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 11 | 12 | @Configuration 13 | public class WebCorsConfig { 14 | 15 | @Bean 16 | public WebMvcConfigurer corsConfigurer() { 17 | return new WebMvcConfigurer() { 18 | @Override 19 | public void addCorsMappings(CorsRegistry registry) { 20 | registry.addMapping("/**") // apply to all endpoints 21 | .allowedOriginPatterns("*") // allow specific domain 22 | .allowedMethods("GET", "POST", "PUT") 23 | .allowedHeaders("*") 24 | .allowCredentials(true); 25 | } 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /widget/index.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Oracle AI Optimizer and Toolkit Widget 11 | 12 | 13 | 14 |
15 |
16 |

Oracle AI Optimizer and Toolkit

17 | 18 |
19 |
20 |
21 |
22 | 26 |
27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | extends: default 2 | 3 | ignore: | 4 | .venv/ 5 | docs/themes/ 6 | .github/ 7 | helm/templates/ 8 | opentofu/modules/*/templates/ 9 | src/client/spring_ai/templates/ 10 | 11 | rules: 12 | line-length: 13 | max: 120 14 | level: warning 15 | 16 | indentation: 17 | spaces: 2 18 | indent-sequences: true 19 | 20 | # Helm templates often use truthy values like yes/no, on/off 21 | truthy: 22 | allowed-values: ['true', 'false', 'yes', 'no', 'on', 'off'] 23 | check-keys: false 24 | 25 | # Allow both quoted and unquoted strings 26 | quoted-strings: 27 | quote-type: any 28 | required: false 29 | 30 | # Don't require document start marker (---) 31 | document-start: disable 32 | 33 | # More lenient on comments 34 | comments: 35 | min-spaces-from-content: 1 36 | 37 | # Disable for commented-out examples in Helm values 38 | comments-indentation: disable 39 | 40 | # Allow empty values (common in Helm templates) 41 | empty-values: 42 | forbid-in-block-mappings: false 43 | forbid-in-flow-mappings: false 44 | 45 | # Brackets and braces (lenient for Helm) 46 | brackets: 47 | min-spaces-inside: 0 48 | max-spaces-inside: 1 49 | 50 | braces: 51 | min-spaces-inside: 0 52 | max-spaces-inside: 1 53 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Root pytest configuration for the test suite. 6 | 7 | This conftest.py uses pytest_plugins to automatically load fixtures from: 8 | - shared_fixtures: Factory fixtures (make_database, make_model, etc.) 9 | - db_fixtures: Database container fixtures (db_container, db_connection, etc.) 10 | 11 | All fixtures defined in these modules are automatically available to all tests 12 | without needing explicit imports in child conftest.py files. 13 | 14 | Constants and helper functions (e.g., TEST_DB_CONFIG, assert_model_list_valid) 15 | still require explicit imports in the test files that use them. 16 | 17 | Note: The 'tests' directory is added to pythonpath in pytest.ini, enabling 18 | direct imports like 'from shared_fixtures import X' instead of 'from tests.shared_fixtures import X'. 19 | This removes the need for __init__.py files in test directories. 20 | """ 21 | 22 | # pytest_plugins automatically loads fixtures from these modules 23 | # This replaces scattered "from tests.shared_fixtures import ..." across conftest files 24 | pytest_plugins = [ 25 | "shared_fixtures", 26 | "db_fixtures", 27 | ] 28 | -------------------------------------------------------------------------------- /helm/templates/server/database/adb-operator.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent ocid 4 | 5 | # AutonomousDatabase Operator Resource (ADB-S) 6 | {{- if .Values.server.database }} 7 | {{- if eq (include "server.database.isADBS" .) "true" }} 8 | apiVersion: database.oracle.com/v4 9 | kind: AutonomousDatabase 10 | metadata: 11 | name: {{ .Release.Name }}-adb-s 12 | labels: 13 | app.kubernetes.io/component: database 14 | {{- include "global.labels" . | nindent 4 }} 15 | spec: 16 | action: "Sync" 17 | details: 18 | id: {{ .Values.server.database.oci.ocid }} 19 | wallet: 20 | name: {{ .Release.Name }}-adb-tns-admin-{{ .Release.Revision }} 21 | password: 22 | k8sSecret: 23 | name: {{ .Release.Name }}-adb-wallet-pass-{{ .Release.Revision }} 24 | {{- if .Values.server.oci_config }} 25 | ociConfig: 26 | configMapName: {{ .Values.server.oci_config.configMapName | default (printf "%s-oci-config" .Release.Name) }} 27 | {{- if .Values.server.oci_config.keySecretName }} 28 | secretName: {{ .Values.server.oci_config.keySecretName }} 29 | {{- end }} 30 | {{- end }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /helm/templates/server/database/oci-configmap.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if .Values.server.oci_config }} 6 | {{- /* Validate OCI config settings */ -}} 7 | {{- include "server.ociConfig.validate" . }} 8 | {{- /* Only create ConfigMap if configMapName is not specified (user wants us to create it) */ -}} 9 | {{- if not .Values.server.oci_config.configMapName }} 10 | {{- /* Determine the default ConfigMap name */ -}} 11 | {{- $configMapName := printf "%s-oci-config" .Release.Name }} 12 | 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: {{ $configMapName }} 17 | labels: 18 | app.kubernetes.io/component: server 19 | {{- include "global.labels" . | nindent 4 }} 20 | data: 21 | {{- with .Values.server.oci_config }} 22 | {{- if .tenancy }} 23 | tenancy: {{ .tenancy | quote }} 24 | {{- end }} 25 | {{- if .user }} 26 | user: {{ .user | quote }} 27 | {{- end }} 28 | {{- if .fingerprint }} 29 | fingerprint: {{ .fingerprint | quote }} 30 | {{- end }} 31 | {{- if .region }} 32 | region: {{ .region | quote }} 33 | {{- end }} 34 | {{- end }} 35 | {{- end }} 36 | {{- end -}} -------------------------------------------------------------------------------- /src/server/bootstrap/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore configfile 6 | 7 | from server.bootstrap.configfile import ConfigStore 8 | 9 | from common.schema import Settings 10 | from common import logging_config 11 | 12 | logger = logging_config.logging.getLogger("bootstrap.settings") 13 | 14 | 15 | def main() -> list[Settings]: 16 | """Bootstrap client settings for default/server. Replace with config file settings if provided.""" 17 | logger.debug("*** Bootstrapping Settings - Start") 18 | 19 | base_clients = ["default", "server"] 20 | settings_objects = [Settings(client=client) for client in base_clients] 21 | 22 | configuration = ConfigStore.get() 23 | if configuration and configuration.client_settings: 24 | logger.debug("Replacing client settings with config file.") 25 | settings_objects = [ 26 | configuration.client_settings.model_copy(update={"client": client}) for client in base_clients 27 | ] 28 | logger.info("Created default/server client settings.") 29 | logger.debug("*** Bootstrapping Settings - End") 30 | return settings_objects 31 | 32 | 33 | if __name__ == "__main__": 34 | main() 35 | -------------------------------------------------------------------------------- /helm/templates/server/service.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent sidb 4 | 5 | apiVersion: v1 6 | kind: Service 7 | metadata: 8 | name: {{ include "server.serviceName" . }} 9 | labels: 10 | app.kubernetes.io/component: server 11 | {{- include "global.labels" . | nindent 4 }} 12 | spec: 13 | type: {{ .Values.server.service.type }} 14 | ports: 15 | - name: http 16 | protocol: TCP 17 | port: 8000 18 | targetPort: 8000 19 | selector: 20 | app.kubernetes.io/component: server 21 | {{- include "global.selectorLabels" . | nindent 4 }} 22 | 23 | --- 24 | {{- if eq (include "server.database.isContainerDB" .) "true" }} 25 | apiVersion: v1 26 | kind: Service 27 | metadata: 28 | name: {{ .Release.Name }}-{{ include "server.database.dbName" . }}-1521 29 | labels: 30 | app.kubernetes.io/component: database 31 | {{- include "global.labels" . | nindent 4 }} 32 | spec: 33 | type: ClusterIP 34 | ports: 35 | - name: oracle-db 36 | protocol: TCP 37 | port: 1521 38 | targetPort: 1521 39 | selector: 40 | app.kubernetes.io/component: database 41 | {{- include "global.selectorLabels" . | nindent 4 }} 42 | {{- end }} 43 | -------------------------------------------------------------------------------- /src/server/api/v1/probes.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore noauth fastmcp healthz 6 | 7 | from fastapi import APIRouter, Request, Depends 8 | from fastmcp import FastMCP 9 | 10 | noauth = APIRouter() 11 | 12 | 13 | def get_mcp(request: Request) -> FastMCP: 14 | """Get the MCP engine from the app state""" 15 | return request.app.state.fastmcp_app 16 | 17 | 18 | @noauth.get("/liveness") 19 | async def liveness_probe(): 20 | """Kubernetes liveness probe""" 21 | return {"status": "alive"} 22 | 23 | 24 | @noauth.get("/readiness") 25 | async def readiness_probe(): 26 | """Kubernetes readiness probe""" 27 | return {"status": "ready"} 28 | 29 | 30 | @noauth.get("/mcp/healthz") 31 | def mcp_healthz(mcp_engine: FastMCP = Depends(get_mcp)): 32 | """Check if MCP server is ready.""" 33 | if mcp_engine is None: 34 | return {"status": "not ready"} 35 | 36 | server = mcp_engine.__dict__["_mcp_server"].__dict__ 37 | return { 38 | "status": "ready", 39 | "name": server["name"], 40 | "version": server["version"], 41 | "available_tools": len(getattr(mcp_engine, "available_tools", [])) if mcp_engine else 0, 42 | } 43 | -------------------------------------------------------------------------------- /src/server/api/utils/mcp.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore streamable fastmcp 6 | 7 | import os 8 | from fastmcp import FastMCP, Client 9 | from common import logging_config 10 | 11 | logger = logging_config.logging.getLogger("api.utils.mcp") 12 | 13 | 14 | def get_client(server: str = "http://127.0.0.1", port: int = 8000, client: str = None) -> dict: 15 | """Get the MCP Client Configuration""" 16 | mcp_client = { 17 | "mcpServers": { 18 | "optimizer": { 19 | "type": "streamableHttp", 20 | "transport": "streamable_http", 21 | "url": f"{server}:{port}/mcp/", 22 | "headers": {"Authorization": f"Bearer {os.getenv('API_SERVER_KEY')}"}, 23 | } 24 | } 25 | } 26 | if client == "langgraph": 27 | del mcp_client["mcpServers"]["optimizer"]["type"] 28 | 29 | return mcp_client 30 | 31 | 32 | async def list_prompts(mcp_engine: FastMCP) -> list: 33 | """Get list of prompts from MCP engine""" 34 | try: 35 | client = Client(mcp_engine) 36 | async with client: 37 | prompts = await client.list_prompts() 38 | return prompts 39 | finally: 40 | await client.close() 41 | -------------------------------------------------------------------------------- /tests/unit/common/test_version.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Unit tests for common/_version.py 6 | 7 | Tests version string retrieval. 8 | """ 9 | 10 | from common._version import __version__ 11 | 12 | 13 | class TestVersion: 14 | """Tests for __version__ variable.""" 15 | 16 | def test_version_is_string(self): 17 | """__version__ should be a string.""" 18 | assert isinstance(__version__, str) 19 | 20 | def test_version_is_non_empty(self): 21 | """__version__ should be non-empty.""" 22 | assert len(__version__) > 0 23 | 24 | def test_version_format(self): 25 | """__version__ should be a valid version string or fallback.""" 26 | # Version should either be a proper version number or the fallback "0.0.0" 27 | # Valid versions can be like "1.0.0", "1.0.0.dev1", "1.3.1.dev128+g867d96f69.d20251126" 28 | assert __version__ == "0.0.0" or "." in __version__ 29 | 30 | def test_version_no_leading_whitespace(self): 31 | """__version__ should not have leading whitespace.""" 32 | assert __version__ == __version__.lstrip() 33 | 34 | def test_version_no_trailing_whitespace(self): 35 | """__version__ should not have trailing whitespace.""" 36 | assert __version__ == __version__.rstrip() 37 | -------------------------------------------------------------------------------- /opentofu/provider.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | terraform { 6 | required_providers { 7 | oci = { 8 | source = "oracle/oci" 9 | version = "~> 7.8" // Last evaluated 8-Jul-2025 10 | } 11 | } 12 | required_version = ">= 1.5" 13 | } 14 | 15 | data "oci_identity_region_subscriptions" "home_region" { 16 | tenancy_id = var.tenancy_ocid 17 | filter { 18 | name = "is_home_region" 19 | values = ["true"] 20 | } 21 | } 22 | 23 | locals { 24 | home_region = data.oci_identity_region_subscriptions.home_region.region_subscriptions[0].region_name 25 | user_ocid = var.user_ocid != "" ? var.user_ocid : var.current_user_ocid 26 | } 27 | 28 | provider "oci" { 29 | region = var.region 30 | tenancy_ocid = var.tenancy_ocid 31 | user_ocid = local.user_ocid 32 | fingerprint = var.fingerprint 33 | private_key_path = var.private_key_path 34 | private_key = var.private_key 35 | } 36 | 37 | provider "oci" { 38 | region = local.home_region 39 | tenancy_ocid = var.tenancy_ocid 40 | user_ocid = local.user_ocid 41 | fingerprint = var.fingerprint 42 | private_key_path = var.private_key_path 43 | private_key = var.private_key 44 | alias = "home_region" 45 | } -------------------------------------------------------------------------------- /helm/templates/client/hpa.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if .Values.server.autoscaling.enabled }} 6 | apiVersion: autoscaling/v2 7 | kind: HorizontalPodAutoscaler 8 | metadata: 9 | name: {{ include "global.fullname" . }}-client 10 | labels: 11 | app.kubernetes.io/component: client 12 | {{- include "global.labels" . | nindent 4 }} 13 | spec: 14 | scaleTargetRef: 15 | apiVersion: apps/v1 16 | kind: Deployment 17 | name: {{ include "global.fullname" . }}-client 18 | minReplicas: {{ .Values.server.autoscaling.minReplicas }} 19 | maxReplicas: {{ .Values.server.autoscaling.maxReplicas }} 20 | metrics: 21 | {{- if .Values.server.autoscaling.targetCPUUtilizationPercentage }} 22 | - type: Resource 23 | resource: 24 | name: cpu 25 | target: 26 | type: Utilization 27 | averageUtilization: {{ .Values.server.autoscaling.targetCPUUtilizationPercentage }} 28 | {{- end }} 29 | {{- if .Values.server.autoscaling.targetMemoryUtilizationPercentage }} 30 | - type: Resource 31 | resource: 32 | name: memory 33 | target: 34 | type: Utilization 35 | averageUtilization: {{ .Values.server.autoscaling.targetMemoryUtilizationPercentage }} 36 | {{- end }} 37 | {{- end }} 38 | -------------------------------------------------------------------------------- /helm/templates/server/hpa.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if .Values.server.autoscaling.enabled }} 6 | apiVersion: autoscaling/v2 7 | kind: HorizontalPodAutoscaler 8 | metadata: 9 | name: {{ include "global.fullname" . }}-server 10 | labels: 11 | app.kubernetes.io/component: server 12 | {{- include "global.labels" . | nindent 4 }} 13 | spec: 14 | scaleTargetRef: 15 | apiVersion: apps/v1 16 | kind: Deployment 17 | name: {{ include "global.fullname" . }}-server 18 | minReplicas: {{ .Values.server.autoscaling.minReplicas }} 19 | maxReplicas: {{ .Values.server.autoscaling.maxReplicas }} 20 | metrics: 21 | {{- if .Values.server.autoscaling.targetCPUUtilizationPercentage }} 22 | - type: Resource 23 | resource: 24 | name: cpu 25 | target: 26 | type: Utilization 27 | averageUtilization: {{ .Values.server.autoscaling.targetCPUUtilizationPercentage }} 28 | {{- end }} 29 | {{- if .Values.server.autoscaling.targetMemoryUtilizationPercentage }} 30 | - type: Resource 31 | resource: 32 | name: memory 33 | target: 34 | type: Utilization 35 | averageUtilization: {{ .Values.server.autoscaling.targetMemoryUtilizationPercentage }} 36 | {{- end }} 37 | {{- end }} 38 | -------------------------------------------------------------------------------- /opentofu/module_vm.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | variable "vm_is_gpu_shape" { 6 | type = bool 7 | default = false 8 | } 9 | 10 | module "vm" { 11 | for_each = var.infrastructure == "VM" ? { managed = true } : {} 12 | source = "./modules/vm" 13 | optimizer_version = var.optimizer_version 14 | label_prefix = local.label_prefix 15 | tenancy_id = var.tenancy_ocid 16 | compartment_id = local.compartment_ocid 17 | vcn_id = local.vcn_ocid 18 | oci_services = data.oci_core_services.core_services.services.0 19 | lb_id = oci_load_balancer_load_balancer.lb.id 20 | lb_client_port = local.lb_client_port 21 | lb_server_port = local.lb_server_port 22 | db_name = local.db_name 23 | db_conn = local.db_conn 24 | vm_is_gpu_shape = var.vm_is_gpu_shape 25 | compute_os_ver = local.compute_os_ver 26 | compute_cpu_ocpu = var.compute_cpu_ocpu 27 | compute_cpu_shape = var.compute_cpu_shape 28 | compute_gpu_shape = var.compute_gpu_shape 29 | availability_domains = local.availability_domains 30 | private_subnet_id = local.private_subnet_ocid 31 | providers = { 32 | oci.home_region = oci.home_region 33 | } 34 | } -------------------------------------------------------------------------------- /docs/layouts/partials/content-footer.html: -------------------------------------------------------------------------------- 1 | 5 | {{ if ne .Title "Get Help" }} 6 |

Questions? Comments?

7 | {{- end }} 8 |

9 | We’d love to hear from you! You can contact us in the 10 | #ai-optimizer 11 | channel in the 12 | Oracle Developers Slack 13 | workspace, or 14 | open an issue in GitHub. 15 |

16 |
17 | Content licensed under Universal Permissive License© 2025 Oracle and/or its affiliates 18 | 19 | {{- $Date := "" }} 20 | {{- with .GitInfo }} 21 | {{- with .AuthorDate }} 22 | {{- $Date = . | time.Format ":date_medium" }} {{- end }} 23 | {{- else }} 24 | {{- with .Date }} {{- $Date = . | time.Format ":date_medium" }} {{- end }} 25 | {{- end }} 26 | {{- with $Date }}

Page Updated: {{ . }}

{{- end }} 27 | {{- partial "term-list.html" (dict "page" . "taxonomy" "categories" "icon" "layer-group" ) }} -------------------------------------------------------------------------------- /docs/layouts/partials/logo.html: -------------------------------------------------------------------------------- 1 | 5 | 38 | 41 | -------------------------------------------------------------------------------- /src/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | # spell-checker:ignore streamlit 5 | 6 | OCI_DIR="/app/.oci" 7 | CONFIG_FILE="${OCI_DIR}/config" 8 | 9 | # Process the OCI config file to change the path of the key_file 10 | if [ -f $CONFIG_FILE ]; then 11 | OCI_RUNTIME_DIR=$(dirname "$OCI_CLI_CONFIG_FILE") 12 | echo "Found OCI Config file in: ${OCI_DIR}; preparing writable copy in ${OCI_RUNTIME_DIR}" 13 | cp -r ${OCI_DIR}/* ${OCI_RUNTIME_DIR} 14 | KEY_FILE_PATH=$(grep '^key_file=' "$OCI_CLI_CONFIG_FILE" | cut -d'=' -f2) 15 | KEY_FILE_NAME=$(basename "$KEY_FILE_PATH") 16 | sed -i.bak "s|key_file=.*|key_file=${OCI_RUNTIME_DIR}/${KEY_FILE_NAME}|g" "$OCI_CLI_CONFIG_FILE" 2>/dev/null 17 | fi 18 | 19 | if [ -d /app/server ] && [ -d /app/client ]; then 20 | echo "Starting Application (Client and Server)" 21 | exec streamlit run ./launch_client.py 22 | fi 23 | 24 | if [ -d /app/server ] && [ ! -d /app/client ]; then 25 | echo "Starting Server" 26 | python ./launch_server.py 27 | fi 28 | 29 | if [ ! -d /app/server ] && [ -d /app/client ]; then 30 | echo "Starting Client" 31 | if [ -z "$API_SERVER_KEY" ] || [ -z "$API_SERVER_URL" ] || [ -z "$API_SERVER_PORT" ]; then 32 | echo "Error: Not all API_SERVER variables are set; unable to start the Client." 33 | exit 1 34 | fi 35 | exec streamlit run ./launch_client.py 36 | fi -------------------------------------------------------------------------------- /tests/integration/client/content/test_testbed.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=protected-access,import-error,import-outside-toplevel 2 | """ 3 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 4 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 5 | """ 6 | # spell-checker: disable 7 | 8 | from integration.client.conftest import run_page_with_models_enabled 9 | 10 | 11 | ############################################################################# 12 | # Test Streamlit UI 13 | ############################################################################# 14 | class TestStreamlit: 15 | """Test the Streamlit UI""" 16 | 17 | ST_FILE = "../src/client/content/testbed.py" 18 | 19 | def test_disabled(self, app_server, app_test): 20 | """Test everything is disabled as nothing configured""" 21 | assert app_server is not None 22 | at = app_test(self.ST_FILE).run() 23 | # When nothing is configured, one of these messages appears (depending on check order) 24 | valid_messages = [ 25 | "No OpenAI compatible language models are configured and/or enabled. Disabling Testing Framework.", 26 | "Database is not configured. Disabling Testbed.", 27 | ] 28 | assert at.error[0].value in valid_messages and at.error[0].icon == "🛑" 29 | 30 | def test_page_loads(self, app_server, app_test): 31 | """Confirm page loads with model enabled""" 32 | run_page_with_models_enabled(app_server, app_test, self.ST_FILE) 33 | -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/templates/cloudinit-oke.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 4 | # spell-checker: disable 5 | 6 | ## https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm 7 | oke_init_url='http://169.254.169.254/opc/v2/instance/metadata/oke_init_script' 8 | curl --fail -H "Authorization: Bearer Oracle" -L0 "${oke_init_url}" | base64 --decode >/var/run/oke-init.sh 9 | 10 | # detect architecture 11 | arch=$(uname -m) 12 | if [ "$arch" = "aarch64" ]; then 13 | binary_url="https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/oke-credential-provider-for-ocir-linux-arm64" 14 | else 15 | binary_url="https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/oke-credential-provider-for-ocir-linux-amd64" 16 | fi 17 | 18 | # download OCIR Access binaries on the worker node 19 | wget "$binary_url" -O /usr/local/bin/credential-provider-oke 20 | wget https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/credential-provider-config.yaml -P /etc/kubernetes/ 21 | # add permission to execute 22 | sudo chmod 755 /usr/local/bin/credential-provider-oke 23 | # configure kubelet with image credential provider 24 | bash /var/run/oke-init.sh --kubelet-extra-args "--image-credential-provider-bin-dir=/usr/local/bin/ --image-credential-provider-config=/etc/kubernetes/credential-provider-config.yaml" -------------------------------------------------------------------------------- /opentofu/modules/vm/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | variable "optimizer_version" { 6 | type = string 7 | } 8 | 9 | variable "tenancy_id" { 10 | type = string 11 | } 12 | 13 | variable "compartment_id" { 14 | type = string 15 | } 16 | 17 | variable "label_prefix" { 18 | type = string 19 | } 20 | 21 | variable "lb_id" { 22 | type = string 23 | } 24 | 25 | variable "availability_domains" { 26 | type = list(any) 27 | } 28 | variable "vcn_id" { 29 | type = string 30 | } 31 | 32 | variable "oci_services" { 33 | type = object({ 34 | cidr_block = string 35 | id = string 36 | name = string 37 | }) 38 | } 39 | 40 | variable "private_subnet_id" { 41 | type = string 42 | } 43 | 44 | variable "vm_is_gpu_shape" { 45 | type = bool 46 | } 47 | 48 | variable "compute_os_ver" { 49 | type = string 50 | } 51 | 52 | variable "compute_cpu_shape" { 53 | type = string 54 | } 55 | 56 | variable "compute_cpu_ocpu" { 57 | type = number 58 | } 59 | 60 | variable "compute_gpu_shape" { 61 | type = string 62 | } 63 | 64 | variable "db_name" { 65 | type = string 66 | } 67 | 68 | variable "db_conn" { 69 | type = object({ 70 | db_type = string 71 | username = string 72 | password = string 73 | service = string 74 | }) 75 | } 76 | 77 | variable "lb_client_port" { 78 | type = number 79 | } 80 | 81 | variable "lb_server_port" { 82 | type = number 83 | } -------------------------------------------------------------------------------- /tests/unit/client/conftest.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=import-error,redefined-outer-name 2 | """ 3 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 4 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 5 | 6 | Unit test fixtures for client tests. Unit tests mock dependencies rather than 7 | requiring a real server, but some fixtures help establish Streamlit session state. 8 | 9 | Note: Shared fixtures (sample_vector_store_data, sample_vector_store_data_alt, 10 | sample_vector_stores_list, make_database, make_model, etc.) are automatically 11 | available via pytest_plugins in test/conftest.py. 12 | """ 13 | # spell-checker: disable 14 | 15 | import os 16 | import sys 17 | 18 | import pytest 19 | from streamlit import session_state as state 20 | 21 | # Add src to path for client imports 22 | SRC_PATH = os.path.join(os.path.dirname(__file__), "..", "..", "..", "src") 23 | if SRC_PATH not in sys.path: 24 | sys.path.insert(0, SRC_PATH) 25 | 26 | 27 | @pytest.fixture(scope="session") 28 | def app_server(): 29 | """ 30 | Minimal fixture for unit tests that just need session state initialized. 31 | 32 | Unlike integration tests, this doesn't actually start a server. 33 | It just ensures Streamlit session state is available for testing. 34 | """ 35 | # Initialize basic state required by client modules 36 | if not hasattr(state, "server"): 37 | state.server = {"url": "http://localhost", "port": 8000, "key": "test-key"} 38 | if not hasattr(state, "client_settings"): 39 | state.client_settings = {"client": "test-client", "ll_model": {}} 40 | 41 | yield True # Just return True to indicate fixture is available 42 | -------------------------------------------------------------------------------- /tests/unit/server/bootstrap/conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Pytest fixtures for server/bootstrap unit tests. 6 | 7 | Note: Shared fixtures (make_database, make_model, make_oci_config, make_ll_settings, 8 | make_settings, make_configuration, temp_config_file, reset_config_store, clean_env) 9 | are automatically available via pytest_plugins in test/conftest.py. 10 | """ 11 | 12 | # pylint: disable=redefined-outer-name 13 | 14 | from unittest.mock import MagicMock, patch 15 | 16 | import pytest 17 | 18 | 19 | ################################################# 20 | # Unit Test Specific Mock Fixtures 21 | ################################################# 22 | 23 | 24 | @pytest.fixture 25 | def mock_oci_config_parser(): 26 | """Mock OCI config parser for testing OCI bootstrap.""" 27 | with patch("configparser.ConfigParser") as mock_parser: 28 | mock_instance = MagicMock() 29 | mock_instance.sections.return_value = [] 30 | mock_parser.return_value = mock_instance 31 | yield mock_parser 32 | 33 | 34 | @pytest.fixture 35 | def mock_oci_config_from_file(): 36 | """Mock oci.config.from_file for testing OCI bootstrap.""" 37 | with patch("oci.config.from_file") as mock_from_file: 38 | yield mock_from_file 39 | 40 | 41 | @pytest.fixture 42 | def mock_is_url_accessible(): 43 | """Mock is_url_accessible for testing model bootstrap.""" 44 | with patch("server.bootstrap.models.is_url_accessible") as mock_accessible: 45 | mock_accessible.return_value = (True, "OK") 46 | yield mock_accessible 47 | -------------------------------------------------------------------------------- /src/client/spring_ai/templates/obaas.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: ${{spring.datasource.url]}} 4 | username: ${{spring.datasource.username]}} 5 | password: ${{spring.datasource.password]}} 6 | ai: 7 | vectorstore: 8 | oracle: 9 | distance-type: {vector_search[distance_metric]} 10 | remove-existing-vector-store-table: True 11 | initialize-schema: True 12 | index-type: {vector_search[index_type]} 13 | openai: 14 | base-url: {ll_model[api_base]} 15 | api-key: {ll_model[api_key]} 16 | chat: 17 | options: 18 | temperature: {ll_model[temperature]} 19 | presencePenalty: {ll_model[presence_penalty]} 20 | frequencyPenalty: {ll_model[frequency_penalty]} 21 | maxTokens: {ll_model[max_tokens]} 22 | topP: {ll_model[top_p]} 23 | model: {ll_model[id]} 24 | embedding: 25 | options: 26 | model: {vector_search[id]} 27 | ollama: 28 | base-url: "http://ollama.ollama.svc.cluster.local:11434" 29 | chat: 30 | options: 31 | temperature: {ll_model[temperature]} 32 | presence-penalty: {ll_model[presence_penalty]} 33 | frequency-penalty: {ll_model[frequency_penalty]} 34 | num-predict: {ll_model[max_tokens]} 35 | top-p: {ll_model[top_p]} 36 | model: {ll_model[id]} 37 | embedding: 38 | options: 39 | model: {vector_search[id]} 40 | aims: 41 | sys_instr: \"{sys_prompt}\" 42 | vectortable: 43 | name: {vector_search[vector_store]} 44 | user: {database_config[user]} 45 | rag_params: 46 | search_type: Similarity 47 | top_k: {vector_search[top_k]} 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-doc_improvement.yml: -------------------------------------------------------------------------------- 1 | name: 📚 Documentation request 2 | description: Suggest additional documentation for the AI Optimizer and Toolkit 3 | labels: ["type:documentation"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thanks for taking the time to suggest more documentation for the AI Optimizer and Toolkit! 9 | We really appreciate the community's efforts to improve the AI Optimizer and Toolkit ❤️ 10 | - type: textarea 11 | attributes: 12 | label: Improve existing documentation 13 | description: Link to documentation page in question (if any) 14 | placeholder: | 15 | https://oracle.github.io/ai-optimizer/... 16 | validations: 17 | required: false 18 | - type: textarea 19 | attributes: 20 | label: Anything specific? 21 | description: Name of the feature where documentation need improvement 22 | placeholder: | 23 | This is not really clear... 24 | validations: 25 | required: false 26 | - type: textarea 27 | attributes: 28 | label: Say What!?! 29 | description: | 30 | Please describe what you think the documentation should say. 31 | Don't worry if you don't have a clear idea in mind; any input helps! 32 | placeholder: | 33 | ... 34 | validations: 35 | required: false 36 | - type: textarea 37 | attributes: 38 | label: Additional Context 39 | description: | 40 | Links? References? Anything that will give us more context about the documentation request here! 41 | 42 | _Tip: You can attach images by clicking this area to highlight it and then dragging files in._ 43 | validations: 44 | required: false 45 | -------------------------------------------------------------------------------- /docs/assets/css/theme-docs-dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | @import "theme-zen-dark.css"; 6 | 7 | :root { 8 | --PRIMARY-color: #C74634; 9 | --SECONDARY-color: #C74634; 10 | --MENU-HOME-LINK-HOVER-color:#C74634; 11 | --MENU-SEARCH-color:#C74634; 12 | --MENU-SECTION-ACTIVE-CATEGORY-color:#C74634; 13 | --MENU-SECTIONS-LINK-HOVER-color:#C74634; 14 | --INTERNAL-MAIN-font: "Liberation Sans",sans-serif; 15 | --INTERNAL-MAIN-TITLES-H1-font: "MontserratAlt1-Light",sans-serif; 16 | --INTERNAL-MAIN-TITLES-H2-font: "MontserratAlt1-Light",sans-serif; 17 | --MAIN-TITLES-H1-font: "MontserratAlt1-Light",sans-serif; 18 | --MAIN-TITLES-H2-font: "MontserratAlt1-Light",sans-serif; 19 | } 20 | 21 | body{ 22 | text-rendering: optimizeLegibility; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | b, strong, label, th { 27 | font-weight: bolder; 28 | } 29 | 30 | html { 31 | font-size: 16px; 32 | letter-spacing: .33px; 33 | } 34 | 35 | div.box, div.box code .copy-to-clipboard { 36 | font-size: 14px; 37 | letter-spacing: .33px; 38 | } 39 | 40 | .lightbox-link img { 41 | border: none !important; 42 | outline: none !important; 43 | } 44 | 45 | .lightbox-link:hover img { 46 | border: none !important; 47 | outline: none !important; 48 | } 49 | 50 | #R-body img[src$='#floatleft'] { 51 | float:left; 52 | margin-right: 1em; 53 | } 54 | 55 | #R-body img[src$='#floatright'] { 56 | float:right; 57 | margin-left: 1em; 58 | } 59 | 60 | #R-logo .powered-by { 61 | font-family: "MontserratAlt1-Light",sans-serif 62 | } -------------------------------------------------------------------------------- /docs/assets/css/theme-docs-light.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | @import "theme-zen-light.css"; 6 | 7 | :root { 8 | --PRIMARY-color: #C74634; 9 | --SECONDARY-color: #C74634; 10 | --MENU-HOME-LINK-HOVER-color:#C74634; 11 | --MENU-SEARCH-color:#C74634; 12 | --MENU-SECTION-ACTIVE-CATEGORY-color:#C74634; 13 | --MENU-SECTIONS-LINK-HOVER-color:#C74634; 14 | --INTERNAL-MAIN-font: "Liberation Sans",sans-serif; 15 | --INTERNAL-MAIN-TITLES-H1-font: "MontserratAlt1-Light",sans-serif; 16 | --INTERNAL-MAIN-TITLES-H2-font: "MontserratAlt1-Light",sans-serif; 17 | --MAIN-TITLES-H1-font: "MontserratAlt1-Light",sans-serif; 18 | --MAIN-TITLES-H2-font: "MontserratAlt1-Light",sans-serif; 19 | } 20 | 21 | body{ 22 | text-rendering: optimizeLegibility; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | b, strong, label, th { 27 | font-weight: bolder; 28 | } 29 | 30 | html { 31 | font-size: 16px; 32 | letter-spacing: .33px; 33 | } 34 | 35 | div.box, div.box code .copy-to-clipboard { 36 | font-size: 14px; 37 | letter-spacing: .33px; 38 | } 39 | 40 | .lightbox-link img { 41 | border: none !important; 42 | outline: none !important; 43 | } 44 | 45 | .lightbox-link:hover img { 46 | border: none !important; 47 | outline: none !important; 48 | } 49 | 50 | #R-body img[src$='#floatleft'] { 51 | float:left; 52 | margin-right: 1em; 53 | } 54 | 55 | #R-body img[src$='#floatright'] { 56 | float:right; 57 | margin-left: 1em; 58 | } 59 | 60 | #R-logo .powered-by { 61 | font-family: "MontserratAlt1-Light",sans-serif 62 | } -------------------------------------------------------------------------------- /src/client/Dockerfile: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: disable 4 | ############################################################# 5 | # Base - Web GUI 6 | # Build from the project root directory: 7 | # podman build -f src/client/Dockerfile -t ai-optimizer-client:latest . 8 | ############################################################# 9 | FROM container-registry.oracle.com/os/oraclelinux:8 AS optimizer_base 10 | ENV RUNUSER=oracleai \ 11 | VIRTUAL_ENV=/opt/.venv 12 | 13 | RUN groupadd -g 10001 $RUNUSER && \ 14 | useradd -u 10001 -g $RUNUSER -md /app $RUNUSER && \ 15 | dnf --nodocs -y install python3.11 python3.11-pip && \ 16 | dnf clean all && \ 17 | python3.11 -m venv --symlinks --upgrade-deps $VIRTUAL_ENV 18 | 19 | COPY --chown=$RUNUSER:$RUNUSER src /opt/package/src 20 | COPY pyproject.toml /opt/package/pyproject.toml 21 | 22 | RUN ${VIRTUAL_ENV}/bin/pip install --upgrade pip wheel setuptools uv && \ 23 | ${VIRTUAL_ENV}/bin/uv pip install "/opt/package[client]" 24 | 25 | ################################################## 26 | # Clint Application 27 | ################################################## 28 | FROM optimizer_base AS client 29 | ENV PATH=$VIRTUAL_ENV/bin:$PATH \ 30 | TEMP=/app/tmp 31 | 32 | # Prep the app directory 33 | RUN for dir in $TEMP; do \ 34 | install -d -m 0700 -o $RUNUSER -g $RUNUSER $dir; \ 35 | done 36 | 37 | COPY --chown=$RUNUSER:$RUNUSER src /app/ 38 | RUN rm -rf /app/server /app/launch_server.py 39 | 40 | # Set user and working directory 41 | USER $RUNUSER 42 | WORKDIR /app/ 43 | 44 | RUN chmod +x /app/entrypoint.sh 45 | ENTRYPOINT ["/app/entrypoint.sh"] 46 | -------------------------------------------------------------------------------- /src/client/spring_ai/templates/start.sh: -------------------------------------------------------------------------------- 1 | # Set Values 2 | export PROVIDER="{provider}" 3 | 4 | if [[ "{provider}" == "ollama" ]]; then 5 | PREFIX="OL"; UNSET_PREFIX="OP" 6 | export OPENAI_CHAT_MODEL="" 7 | unset OPENAI_EMBEDDING_MODEL 8 | unset OPENAI_URL 9 | export OLLAMA_BASE_URL="{ll_model[api_base]}" 10 | export OLLAMA_CHAT_MODEL="{ll_model[id]}" 11 | export OLLAMA_EMBEDDING_MODEL="{vector_search[id]}" 12 | else 13 | PREFIX="OP"; UNSET_PREFIX="OL" 14 | export OPENAI_CHAT_MODEL="{ll_model[id]}" 15 | export OPENAI_EMBEDDING_MODEL="{vector_search[id]}" 16 | export OPENAI_URL="{ll_model[api_base]}" 17 | export OLLAMA_CHAT_MODEL="" 18 | unset OLLAMA_EMBEDDING_MODEL 19 | fi 20 | 21 | TEMPERATURE="{ll_model[temperature]}" 22 | FREQUENCY_PENALTY="{ll_model[frequency_penalty]}" 23 | PRESENCE_PENALTY="{ll_model[presence_penalty]}" 24 | MAX_TOKENS="{ll_model[max_tokens]}" 25 | TOP_P="{ll_model[top_p]}" 26 | COMMON_VARS=("TEMPERATURE" "FREQUENCY_PENALTY" "PRESENCE_PENALTY" "MAX_TOKENS" "TOP_P") 27 | 28 | # Loop through the common variables and export them 29 | for var in "${{COMMON_VARS[@]}}"; do 30 | export ${{PREFIX}}_${{var}}="${{!var}}" 31 | unset ${{UNSET_PREFIX}}_${{var}} 32 | done 33 | 34 | # env_vars 35 | export SPRING_AI_OPENAI_API_KEY=${{OPENAI_API_KEY}} 36 | export DB_DSN="jdbc:oracle:thin:@{database_config[dsn]}" 37 | export DB_USERNAME="{database_config[user]}" 38 | export DB_PASSWORD="{database_config[password]}" 39 | export DISTANCE_TYPE="{vector_search[distance_metric]}" 40 | export INDEX_TYPE="{vector_search[index_type]}" 41 | export SYS_INSTR="{sys_prompt}" 42 | export TOP_K="{vector_search[top_k]}" 43 | 44 | export VECTOR_STORE="{vector_search[vector_store]}" 45 | export USER_TABLE=$DB_USERNAME 46 | mvn spring-boot:run -P {provider} -------------------------------------------------------------------------------- /docs/hugo.toml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | 4 | baseURL = 'https://oracle.github.io/ai-optimizer' 5 | languageCode = 'en-us' 6 | title = 'Oracle AI Optimizer & Toolkit' 7 | theme = "relearn" 8 | sectionPagesMenu = 'main' 9 | tableOfContents = true 10 | enableGitInfo = true 11 | 12 | # Required if you want to render robots.txt template 13 | enableRobotsTXT = true 14 | 15 | [markup] 16 | [markup.goldmark] 17 | duplicateResourceFiles = false 18 | [markup.goldmark.extensions] 19 | strikethrough = false 20 | [markup.goldmark.extensions.extras] 21 | [markup.goldmark.extensions.extras.subscript] 22 | enable = true 23 | 24 | # Parameters 25 | [params] 26 | collapsibleMenu = true 27 | showVisitedLinks = true 28 | themeVariant = ['auto', 'docs-light', 'docs-dark'] 29 | disableInlineCopyToClipBoard = true 30 | hideAuthorName = true 31 | LongName = "Oracle AI Optimizer and Toolkit" 32 | ShortName = "AI Optimizer" 33 | GitHubRepo = "https://github.com/oracle/ai-optimizer" 34 | 35 | [menu] 36 | [[menu.shortcuts]] 37 | identifier = 'ds' 38 | name = " GitHub Repository" 39 | url = 'https://github.com/oracle/ai-optimizer' 40 | weight = 10 41 | [[menu.shortcuts]] 42 | name = "Building a Chatbot" 43 | url = 'https://www.youtube.com/watch?v=oG9MPCpwUlU' 44 | weight = 11 45 | # [[menu.shortcuts]] 46 | # name = " Credits" 47 | # url = 'more/credits/' 48 | # weight = 30 49 | # [[menu.shortcuts]] 50 | # name = " Tags" 51 | # url = 'tags/' 52 | # weight = 40 -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | 6 | package org.springframework.ai.openai.samples.helloworld; 7 | 8 | import org.springframework.ai.embedding.EmbeddingModel; 9 | import org.springframework.ai.tool.ToolCallbackProvider; 10 | import org.springframework.ai.tool.annotation.Tool; 11 | import org.springframework.ai.tool.method.MethodToolCallbackProvider; 12 | import org.springframework.ai.chat.client.ChatClient; 13 | import org.springframework.ai.vectorstore.oracle.OracleVectorStore; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.boot.SpringApplication; 16 | import org.springframework.boot.autoconfigure.SpringBootApplication; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.jdbc.core.JdbcTemplate; 19 | import org.springframework.stereotype.Service; 20 | 21 | 22 | 23 | @SpringBootApplication 24 | public class Application { 25 | 26 | @Value("${aims.vectortable.name}") 27 | private String legacyTable; 28 | 29 | public static void main(String[] args) { 30 | SpringApplication.run(Application.class, args); 31 | } 32 | 33 | @Bean 34 | OracleVectorStore vectorStore(EmbeddingModel ec, JdbcTemplate t) { 35 | OracleVectorStore ovs = OracleVectorStore.builder(t,ec) 36 | .tableName(legacyTable+"_SPRINGAI") 37 | .initializeSchema(true) 38 | .build(); 39 | return ovs; 40 | } 41 | 42 | @Bean 43 | public ToolCallbackProvider ragTools(RagService ragService) { 44 | return MethodToolCallbackProvider.builder().toolObjects(ragService).build(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting security vulnerabilities 2 | 3 | Oracle values the independent security research community and believes that 4 | responsible disclosure of security vulnerabilities helps us ensure the security 5 | and privacy of all our users. 6 | 7 | Please do NOT raise a GitHub Issue to report a security vulnerability. If you 8 | believe you have found a security vulnerability, please submit a report to 9 | [secalert_us@oracle.com][1] preferably with a proof of concept. Please review 10 | some additional information on [how to report security vulnerabilities to Oracle][2]. 11 | We encourage people who contact Oracle Security to use email encryption using 12 | [our encryption key][3]. 13 | 14 | We ask that you do not use other channels or contact the project maintainers 15 | directly. 16 | 17 | Non-vulnerability related security issues including ideas for new or improved 18 | security features are welcome on GitHub Issues. 19 | 20 | ## Security updates, alerts and bulletins 21 | 22 | Security updates will be released on a regular cadence. Many of our projects 23 | will typically release security fixes in conjunction with the 24 | Oracle Critical Patch Update program. Additional 25 | information, including past advisories, is available on our [security alerts][4] 26 | page. 27 | 28 | ## Security-related information 29 | 30 | We will provide security related information such as a threat model, considerations 31 | for secure use, or any known security issues in our documentation. Please note 32 | that labs and sample code are intended to demonstrate a concept and may not be 33 | sufficiently hardened for production use. 34 | 35 | [1]: mailto:secalert_us@oracle.com 36 | [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html 37 | [3]: https://www.oracle.com/security-alerts/encryptionkey.html 38 | [4]: https://www.oracle.com/security-alerts/ 39 | -------------------------------------------------------------------------------- /src/client/mcp/rag/rag_base_optimizer_config_direct.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | import sys 6 | from typing import List 7 | import os 8 | from dotenv import load_dotenv 9 | import logging 10 | logger = logging.getLogger(__name__) 11 | 12 | logging.basicConfig( 13 | level=logging.INFO, 14 | format="%(name)s - %(levelname)s - %(message)s" 15 | ) 16 | 17 | 18 | logger.info("Successfully imported libraries and modules") 19 | 20 | from optimizer_utils import config 21 | 22 | from optimizer_utils import rag 23 | 24 | CHUNKS_DIR = "chunks_temp" 25 | data = {} 26 | 27 | def similarity_search(question: str, max_results: int = 5) -> List[str]: 28 | """ 29 | Use this tool to get the top similar information to any question that may benefit from up-to-date or domain-specific information. 30 | 31 | Args: 32 | question: The topic to search for 33 | max_results: Maximum number of results to retrieve (default: 5) 34 | 35 | Returns: 36 | List of information related to the question 37 | """ 38 | 39 | logger.info(f"Results provided for question: {question} with top {max_results}") 40 | chunks=["first chunk", "second chunk"] 41 | 42 | return chunks 43 | 44 | if __name__ == "__main__": 45 | # Initialize and run the server 46 | # Load JSON file 47 | file_path = os.path.join(os.getcwd(), "optimizer_settings.json") 48 | logger.info(file_path) 49 | rag.set_optimizer_settings_path(file_path) 50 | 51 | if len(sys.argv) > 1: 52 | question = sys.argv[1] 53 | print(question) 54 | logger.info(f"Question: {sys.argv[1]}") 55 | logger.info(f"\n\nAgent Answer: {rag.rag_tool_base(question)}") 56 | else: 57 | logger.info("No question provided.") -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | 6 | package org.springframework.ai.openai.samples.helloworld; 7 | 8 | import org.springframework.ai.chat.client.ChatClient; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.beans.factory.annotation.Value; 12 | 13 | @Configuration 14 | public class Config { 15 | 16 | @Bean 17 | public ChatClient chatClient(ChatClient.Builder builder) { 18 | return builder.build(); 19 | } 20 | 21 | // Optional: Centralize property values if used in multiple places 22 | @Bean 23 | public String modelOpenAI(@Value("${spring.ai.openai.chat.options.model}") String modelOpenAI) { 24 | return modelOpenAI; 25 | } 26 | 27 | @Bean 28 | public String modelOllamaAI(@Value("${spring.ai.ollama.chat.options.model}") String modelOllamaAI) { 29 | return modelOllamaAI; 30 | } 31 | 32 | @Bean 33 | public String legacyTable(@Value("${aims.vectortable.name}") String table) { 34 | return table; 35 | } 36 | 37 | @Bean 38 | public String userTable(@Value("${aims.vectortable.user}") String user) { 39 | return user; 40 | } 41 | 42 | 43 | @Bean 44 | public String contextInstr(@Value("${aims.sys_instr}") String instr) { 45 | return instr; 46 | } 47 | 48 | @Bean 49 | public String searchType(@Value("${aims.rag_params.search_type}") String searchType) { 50 | return searchType; 51 | } 52 | 53 | @Bean 54 | public Integer topK(@Value("${aims.rag_params.top_k}") int topK) { 55 | return topK; 56 | } 57 | 58 | } 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/java/org/springframework/ai/openai/samples/helloworld/model/ChatResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | package org.springframework.ai.openai.samples.helloworld.model; 6 | 7 | 8 | import java.util.List; 9 | 10 | public class ChatResponse { 11 | 12 | private String id; //chatcmpl-B9MBs8CjcvOU2jLn4n570S5qMJKcT 13 | private String object; //chat.completion 14 | private String created; // 1741569952, 15 | private String model; //gpt-4.1-2025-04-14", 16 | private List choices; // message 17 | 18 | public ChatResponse(String id, String object, String created, String model, List choices) { 19 | this.id = id; 20 | this.object = object; 21 | this.created = created; 22 | this.model = model; 23 | this.choices = choices; 24 | } 25 | 26 | public ChatResponse() {} 27 | 28 | 29 | public String getId() { 30 | return id; 31 | } 32 | 33 | public void setId(String id) { 34 | this.id = id; 35 | } 36 | 37 | public String getCreated() { 38 | return created; 39 | } 40 | 41 | public void setCreated(String created) { 42 | this.created = created; 43 | } 44 | 45 | public String getModel() { 46 | return model; 47 | } 48 | 49 | public void setModel(String model) { 50 | this.model = model; 51 | } 52 | 53 | public List getChoices() { 54 | return choices; 55 | } 56 | 57 | public void setChoices(List choices) { 58 | this.choices = choices; 59 | } 60 | 61 | 62 | 63 | public String getObject() { 64 | return object; 65 | } 66 | 67 | public void setObject(String object) { 68 | this.object = object; 69 | } 70 | } -------------------------------------------------------------------------------- /opentofu/modules/vm/iam.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | resource "oci_identity_dynamic_group" "compute_dynamic_group" { 6 | compartment_id = var.tenancy_id 7 | name = format("%s-compute-dyngrp", var.label_prefix) 8 | description = format("%s Dynamic Group - Computes", var.label_prefix) 9 | matching_rule = format( 10 | "All {instance.compartment.id = '%s', instance.id = '%s'}", 11 | var.compartment_id, oci_core_instance.instance.id 12 | ) 13 | provider = oci.home_region 14 | } 15 | 16 | resource "oci_identity_policy" "identity_node_policies" { 17 | compartment_id = var.tenancy_id 18 | name = format("%s-compute-instance-policy", var.label_prefix) 19 | description = format("%s InstancePrinciples", var.label_prefix) 20 | statements = [ 21 | format( 22 | "allow dynamic-group %s to use autonomous-database-family in compartment id %s", 23 | oci_identity_dynamic_group.compute_dynamic_group.name, var.compartment_id 24 | ), 25 | format( 26 | "allow dynamic-group %s to read objectstorage-namespaces in compartment id %s", 27 | oci_identity_dynamic_group.compute_dynamic_group.name, var.compartment_id 28 | ), 29 | format( 30 | "allow dynamic-group %s to inspect buckets in compartment id %s", 31 | oci_identity_dynamic_group.compute_dynamic_group.name, var.compartment_id 32 | ), 33 | format( 34 | "allow dynamic-group %s to read objects in compartment id %s", 35 | oci_identity_dynamic_group.compute_dynamic_group.name, var.compartment_id 36 | ), 37 | format( 38 | "allow dynamic-group %s to use generative-ai-family in tenancy", 39 | oci_identity_dynamic_group.compute_dynamic_group.name 40 | ), 41 | ] 42 | provider = oci.home_region 43 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Oracle and/or its affiliates. 2 | 3 | The Universal Permissive License (UPL), Version 1.0 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any 6 | person obtaining a copy of this software, associated documentation and/or data 7 | (collectively the "Software"), free of charge and under any and all copyright 8 | rights in the Software, and any and all patent rights owned or freely 9 | licensable by each licensor hereunder covering either (i) the unmodified 10 | Software as contributed to or provided by such licensor, or (ii) the Larger 11 | Works (as defined below), to deal in both 12 | 13 | (a) the Software, and 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if 15 | one is included with the Software (each a "Larger Work" to which the Software 16 | is contributed by such licensors), 17 | 18 | without restriction, including without limitation the rights to copy, create 19 | derivative works of, display, perform, and distribute the Software and make, 20 | use, sell, offer for sale, import, export, have made, and have sold the 21 | Software and the Larger Work(s), and to sublicense the foregoing rights on 22 | either these or other terms. 23 | 24 | This license is subject to the following condition: 25 | The above copyright notice and either this complete permission notice or at 26 | a minimum a reference to the UPL must be included in all copies or 27 | substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | -------------------------------------------------------------------------------- /src/client/spring_ai/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9090 3 | spring: 4 | datasource: 5 | url: ${DB_DSN} 6 | username: ${DB_USERNAME} 7 | password: ${DB_PASSWORD} 8 | ai: 9 | mcp: 10 | server: 11 | name: webmvc-mcp-server 12 | version: 1.0.0 13 | type: SYNC 14 | request-timeout: 120 15 | instructions: "Use this tool to answer any question that may benefit from up-to-date or domain-specific information." 16 | capabilities: 17 | tool: true 18 | resource: true 19 | prompt: true 20 | completion: true 21 | vectorstore: 22 | oracle: 23 | distance-type: ${DISTANCE_TYPE} 24 | remove-existing-vector-store-table: True 25 | initialize-schema: True 26 | index-type: ${INDEX_TYPE} 27 | openai: 28 | base-url: {OPENAI_URL} 29 | api-key: {OPENAI_API_KEY} 30 | chat: 31 | options: 32 | temperature: {OP_TEMPERATURE} 33 | frequencyPenalty: {OP_FREQUENCY_PENALTY} 34 | presencePenalty: {OP_PRESENCE_PENALTY} 35 | maxTokens: {OP_MAX_TOKENS} 36 | topP: {OP_TOP_P} 37 | model: ${OPENAI_CHAT_MODEL} 38 | embedding: 39 | options: 40 | model: ${OPENAI_EMBEDDING_MODEL} 41 | ollama: 42 | base-url: ${OLLAMA_BASE_URL} 43 | chat: 44 | options: 45 | top-p: {OL_TOP_P} 46 | presence-penalty: {OL_PRESENCE_PENALTY} 47 | frequency-penalty: {OL_FREQUENCY_PENALTY} 48 | temperature: {OL_TEMPERATURE} 49 | num-predict: {OL_MAX_TOKENS} 50 | model: ${OLLAMA_CHAT_MODEL} 51 | embedding: 52 | options: 53 | model: ${OLLAMA_EMBEDDING_MODEL} 54 | aims: 55 | sys_instr: ${SYS_INSTR} 56 | vectortable: 57 | name: ${VECTOR_STORE} 58 | user: ${USER_TABLE} 59 | rag_params: 60 | search_type: Similarity 61 | top_k: ${TOP_K} 62 | -------------------------------------------------------------------------------- /src/client/spring_ai/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Oracle and/or its affiliates. 2 | 3 | The Universal Permissive License (UPL), Version 1.0 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any 6 | person obtaining a copy of this software, associated documentation and/or data 7 | (collectively the "Software"), free of charge and under any and all copyright 8 | rights in the Software, and any and all patent rights owned or freely 9 | licensable by each licensor hereunder covering either (i) the unmodified 10 | Software as contributed to or provided by such licensor, or (ii) the Larger 11 | Works (as defined below), to deal in both 12 | 13 | (a) the Software, and 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if 15 | one is included with the Software (each a "Larger Work" to which the Software 16 | is contributed by such licensors), 17 | 18 | without restriction, including without limitation the rights to copy, create 19 | derivative works of, display, perform, and distribute the Software and make, 20 | use, sell, offer for sale, import, export, have made, and have sold the 21 | Software and the Larger Work(s), and to sublicense the foregoing rights on 22 | either these or other terms. 23 | 24 | This license is subject to the following condition: 25 | The above copyright notice and either this complete permission notice or at 26 | a minimum a reference to the UPL must be included in all copies or 27 | substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | -------------------------------------------------------------------------------- /helm/templates/server/database/auth-secret.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent freepdb1 4 | 5 | # Database Authentication Secret 6 | {{- if .Values.server.database }} 7 | {{- include "server.database.validateOtherType" . }} 8 | {{- $secretName := include "server.databaseSecret" . }} 9 | {{- $secret_existing := lookup "v1" "Secret" .Release.Namespace $secretName }} 10 | {{- if not $secret_existing }} 11 | apiVersion: v1 12 | kind: Secret 13 | metadata: 14 | name: {{ $secretName }} 15 | labels: 16 | app.kubernetes.io/component: database 17 | {{- include "global.labels" . | nindent 4 }} 18 | annotations: 19 | helm.sh/resource-policy: keep 20 | type: Opaque 21 | stringData: 22 | {{ default "username" .Values.server.database.authN.usernameKey }}: "AI_OPTIMIZER" 23 | {{ default "password" .Values.server.database.authN.passwordKey }}: {{ include "server.randomPassword" . | quote }} 24 | {{- if eq (include "server.database.isSIDB" .) "true" }} 25 | {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Release.Name }}-{{ include "server.database.dbName" . }}-1521:1521/FREEPDB1" 26 | {{- else if eq (include "server.database.isADBFree" .) "true" }} 27 | {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Release.Name }}-{{ include "server.database.dbName" . }}-1521:1521/FREEPDB1" 28 | {{- else if eq (include "server.database.isOther" .) "true" }} 29 | {{- if and .Values.server.database.other.dsn (ne (.Values.server.database.other.dsn | trim) "") }} 30 | {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Values.server.database.other.dsn }}" 31 | {{- else }} 32 | {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Values.server.database.other.host }}:{{ .Values.server.database.other.port }}/{{ .Values.server.database.other.service_name }}" 33 | {{- end }} 34 | {{- end }} 35 | {{- end }} 36 | {{- end }} 37 | -------------------------------------------------------------------------------- /helm/templates/server/ingress.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if .Values.server.ingress.enabled -}} 6 | {{- if and .Values.server.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 7 | {{- if not (hasKey .Values.server.ingress.annotations "kubernetes.io/ingress.class") }} 8 | {{- $_ := set .Values.server.ingress.annotations "kubernetes.io/ingress.class" .Values.server.ingress.className}} 9 | {{- end }} 10 | {{- end }} 11 | apiVersion: networking.k8s.io/v1 12 | kind: Ingress 13 | metadata: 14 | name: {{ include "server.serviceName" . }} 15 | labels: 16 | app.kubernetes.io/component: server 17 | {{- include "global.labels" . | nindent 4 }} 18 | {{- with .Values.server.ingress.annotations }} 19 | annotations: 20 | {{- toYaml . | nindent 4 }} 21 | {{- end }} 22 | spec: 23 | {{- if and .Values.server.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 24 | ingressClassName: {{ .Values.server.ingress.className }} 25 | {{- end }} 26 | {{- if .Values.server.ingress.tls }} 27 | tls: 28 | {{- range .Values.server.ingress.tls }} 29 | - hosts: 30 | {{- range .hosts }} 31 | - {{ . | quote }} 32 | {{- end }} 33 | secretName: {{ .secretName }} 34 | {{- end }} 35 | {{- end }} 36 | rules: 37 | - http: 38 | paths: 39 | - pathType: Prefix 40 | path: {{ include "global.getPath" . }}v1 41 | backend: 42 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 43 | service: 44 | name: {{ include "server.serviceName" . }} 45 | port: 46 | number: 8000 47 | {{- else }} 48 | serviceName: {{ include "server.serviceName" . }} 49 | servicePort: 8000 50 | {{- end }} 51 | {{- end }} -------------------------------------------------------------------------------- /tests/unit/server/bootstrap/test_bootstrap_module_config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Consolidated tests for bootstrap module configuration (loggers). 6 | These parameterized tests replace individual boilerplate tests in each module file. 7 | """ 8 | 9 | import pytest 10 | 11 | from server.bootstrap import bootstrap 12 | from server.bootstrap import configfile 13 | from server.bootstrap import databases as databases_module 14 | from server.bootstrap import models as models_module 15 | from server.bootstrap import oci as oci_module 16 | from server.bootstrap import settings as settings_module 17 | 18 | 19 | # Module configurations for parameterized tests 20 | BOOTSTRAP_MODULES = [ 21 | pytest.param(bootstrap, "bootstrap", id="bootstrap"), 22 | pytest.param(configfile, "bootstrap.configfile", id="configfile"), 23 | pytest.param(databases_module, "bootstrap.databases", id="databases"), 24 | pytest.param(models_module, "bootstrap.models", id="models"), 25 | pytest.param(oci_module, "bootstrap.oci", id="oci"), 26 | pytest.param(settings_module, "bootstrap.settings", id="settings"), 27 | ] 28 | 29 | 30 | class TestLoggerConfiguration: 31 | """Parameterized tests for logger configuration across all bootstrap modules.""" 32 | 33 | @pytest.mark.parametrize("module,_logger_name", BOOTSTRAP_MODULES) 34 | def test_logger_exists(self, module, _logger_name): 35 | """Each bootstrap module should have a logger configured.""" 36 | assert hasattr(module, "logger"), f"{module.__name__} should have 'logger'" 37 | 38 | @pytest.mark.parametrize("module,expected_name", BOOTSTRAP_MODULES) 39 | def test_logger_name(self, module, expected_name): 40 | """Each bootstrap module logger should have the correct name.""" 41 | assert module.logger.name == expected_name, ( 42 | f"{module.__name__} logger name should be '{expected_name}', got '{module.logger.name}'" 43 | ) 44 | -------------------------------------------------------------------------------- /docs/content/help/troubleshooting/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = 'Troubleshooting' 3 | +++ 4 | 5 | 9 | 10 | ## Startup Time 11 | 12 | **_Problem_**: 13 | After starting the {{< short_app_ref >}}, it takes a long time to load the first page. 14 | 15 | **_Solution_**: 16 | This is normally the result of a configured database that is inaccessible. Depending on how you've configured the database, if `retry_count`, and `retry_delay` is set but the database is inaccessible, the {{< short_app_ref >}} will appear to hang for the duration of `retry_count * retry_delay` during the startup. 17 | 18 | ## Embedding Rate Limits 19 | 20 | **_Problem_**: 21 | During embedding, especially when using trial keys, you may experience a failure due to rate limits. For example: 22 | 23 | ``` 24 | Operation Failed: Unexpected error: status_code: 429, body: 25 | data=None message='trial token rate limit exceeded, limit is 100000 tokens per minute'. 26 | ``` 27 | 28 | **_Solution_**: 29 | Set a rate limit based on the API Key restrictions. 30 | 31 | 32 | ## Testbed Evaluation 33 | 34 | **_Problem_**: 35 | During the Evaluation in the **Testbed**, a database error occurs: `DPY-4011: the database or network closed the connection` 36 | 37 | **_Solution_**: 38 | Increase the memory of the vector_memory_size. If this is an Oracle Autonomous Database, scale up the CPU. 39 | 40 | ## Autonomous Database behind VPN 41 | 42 | **_Problem_**: 43 | Connection to an Autonomous database while inside a VPN fails. 44 | 45 | **_Solution_**: 46 | Update the database connection string to include a `https_proxy` and `https_proxy_port`. 47 | 48 | For example: 49 | 50 | ```text 51 | myadb_high = ( 52 | description=( 53 | address= 54 | (protocol=tcps)(port=1522) 55 | (https_proxy=)(https_proxy_port=) # <-- Add 56 | (host=) 57 | )(connect_data=(service_name=s))(security=(ssl_server_dn_match=yes)) 58 | )``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-feature_request.yml: -------------------------------------------------------------------------------- 1 | name: ✨ Feature request 2 | description: Suggest a feature or enhancement for the AI Optimizer and Toolkit 3 | labels: ["type:enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thanks for taking the time to suggest a feature or enhancement for the AI Optimizer and Toolkit! 9 | We really appreciate the community's efforts to improve the AI Optimizer and Toolkit ❤️ 10 | - type: checkboxes 11 | attributes: 12 | label: Checklist 13 | description: Please confirm and check all the following options. 14 | options: 15 | - label: I have searched the [existing issues](https://github.com/oracle/ai-optimizer/issues) for similar feature requests. 16 | required: true 17 | - label: I added a descriptive title and summary to this issue. 18 | required: true 19 | - type: textarea 20 | attributes: 21 | label: Summary 22 | description: Type here a clear and concise description of the feature or enhancement request. Aim for 2-3 sentences. 23 | validations: 24 | required: true 25 | - type: textarea 26 | attributes: 27 | label: Why? 28 | description: Please outline the problem, motivation, or use case related to this feature request. 29 | placeholder: | 30 | It would be really cool to ... 31 | validations: 32 | required: false 33 | - type: textarea 34 | attributes: 35 | label: How? 36 | description: | 37 | Please describe the solution or implementation you'd like to see. 38 | Don't worry if you don't have a clear solution in mind; any input helps! 39 | placeholder: | 40 | ... 41 | validations: 42 | required: false 43 | - type: textarea 44 | attributes: 45 | label: Additional Context 46 | description: | 47 | Links? References? Anything that will give us more context about the feature request here! 48 | 49 | _Tip: You can attach images by clicking this area to highlight it and then dragging files in._ 50 | validations: 51 | required: false 52 | -------------------------------------------------------------------------------- /src/server/bootstrap/configfile.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore configfile 6 | 7 | import json 8 | from pathlib import Path 9 | from threading import Lock 10 | 11 | from common.schema import Configuration 12 | from common import logging_config 13 | 14 | logger = logging_config.logging.getLogger("bootstrap.configfile") 15 | 16 | 17 | class ConfigStore: 18 | """Store the Contents of the configfile""" 19 | 20 | _config = None 21 | _lock = Lock() 22 | 23 | @classmethod 24 | def load_from_file(cls, config_path: Path): 25 | """Load Configuration file""" 26 | if not config_path.exists(): 27 | logger.warning("Config file %s does not exist. Using empty config.", config_path) 28 | return # leave _config as None 29 | 30 | if config_path.suffix != ".json": 31 | logger.warning("Config file %s should be a .json file", config_path) 32 | 33 | with cls._lock: 34 | if cls._config is not None: 35 | return # already loaded 36 | 37 | with open(config_path, "r", encoding="utf-8") as f: 38 | config_data = json.load(f) 39 | cls._config = Configuration(**config_data) 40 | logger.info("Loaded Configuration file.") 41 | #logger.debug("Loaded Configuration: %s", cls._config) 42 | 43 | @classmethod 44 | def get(cls): 45 | """Return the configuration stored in memory""" 46 | return cls._config 47 | 48 | @classmethod 49 | def reset(cls): 50 | """Reset the configuration state. Used for testing.""" 51 | with cls._lock: 52 | cls._config = None 53 | 54 | 55 | def config_file_path() -> str: 56 | """Return the path where settings should be stored.""" 57 | script_dir = Path(__file__).resolve().parent.parent 58 | config_file = str(script_dir / "etc" / "configuration.json") 59 | logger.debug("Config File path: %s", config_file) 60 | return config_file 61 | -------------------------------------------------------------------------------- /docs/content/client/api_server/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = '📡 API Server' 3 | weight = 35 4 | +++ 5 | 9 | 10 | The {{< full_app_ref >}} is powered by an API Server to allow for any client to access its features. The API Server can be run as part of the provided {{< short_app_ref >}} GUI client (referred to as the "All-in-One" deployment) or as a separate, independent process. 11 | 12 | Each client connected to the API Server, including those from the {{< short_app_ref >}} GUI client, share the same configuration but maintain their own settings. Database, Model, OCI, and Prompt configurations are used across all clients; but which database, models, OCI profile, and prompts set are specific to each client. 13 | 14 | When started as part of the {{< short_app_ref >}} "All-in-One" deployment, by setting `API_SERVER_CONTROL=TRUE` before startup, you can change the Port it listens on and the API Server Key. 15 | 16 | ![Server Configuration](images/api_server_config.png) 17 | 18 | If the API Server is started independently of the {{< short_app_ref >}} client, the configuration is shown, but cannot be modified from the client. 19 | 20 | ## Server Configuration 21 | 22 | During the startup of the API Server, a `server` client is created and populated with minimal settings. The `server` client is the default when calling the API Server outside of the {{< short_app_ref >}} GUI client. To copy your {{< short_app_ref >}} GUI client settings to the `server` client for use with external application clients, click the "Copy Client Settings". 23 | 24 | ![Server Settings](images/api_server_settings.png) 25 | 26 | You can review how the `server` client is configured by expanding the `{...}` brackets. 27 | 28 | ## Server Activity 29 | 30 | All interactions with the API Server using the `server` client can be seen in the Server Activity. Toggle the "Auto Refresh" or manually refresh the Activity to see interactions from outside the {{< short_app_ref >}} GUI client. 31 | 32 | ![Server Settings](images/api_server_activity.png) -------------------------------------------------------------------------------- /helm/templates/client/ingress.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent 4 | 5 | {{- if and .Values.client.enabled .Values.client.ingress.enabled -}} 6 | {{- if and .Values.client.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 7 | {{- if not (hasKey .Values.client.ingress.annotations "kubernetes.io/ingress.class") }} 8 | {{- $_ := set .Values.client.ingress.annotations "kubernetes.io/ingress.class" .Values.client.ingress.className}} 9 | {{- end }} 10 | {{- end }} 11 | apiVersion: networking.k8s.io/v1 12 | kind: Ingress 13 | metadata: 14 | name: {{ include "global.fullname" . }}-client-http 15 | labels: 16 | app.kubernetes.io/component: client 17 | {{- include "global.labels" . | nindent 4 }} 18 | annotations: 19 | nginx.ingress.kubernetes.io/proxy-body-size: 200m 20 | {{- with .Values.client.ingress.annotations }} 21 | {{- toYaml . | nindent 4 }} 22 | {{- end }} 23 | spec: 24 | {{- if and .Values.client.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 25 | ingressClassName: {{ .Values.client.ingress.className }} 26 | {{- end }} 27 | {{- if .Values.client.ingress.tls }} 28 | tls: 29 | {{- range .Values.client.ingress.tls }} 30 | - hosts: 31 | {{- range .hosts }} 32 | - {{ . | quote }} 33 | {{- end }} 34 | secretName: {{ .secretName }} 35 | {{- end }} 36 | {{- end }} 37 | rules: 38 | - http: 39 | paths: 40 | - pathType: ImplementationSpecific 41 | path: {{ include "global.getPath" . }} 42 | backend: 43 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 44 | service: 45 | name: {{ include "global.fullname" . }}-client-http 46 | port: 47 | number: 80 48 | {{- else }} 49 | serviceName: {{ include "global.fullname" . }}-client-http 50 | servicePort: 80 51 | {{- end }} 52 | {{- end }} -------------------------------------------------------------------------------- /docs/layouts/partials/menu-footer.html: -------------------------------------------------------------------------------- 1 | 7 |

Built with by ORACLE

8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /opentofu/modules/vm/data.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | data "oci_core_images" "images" { 6 | compartment_id = var.compartment_id 7 | operating_system = "Oracle Linux" 8 | shape = local.vm_compute_shape 9 | 10 | filter { 11 | name = "display_name" 12 | values = [ 13 | var.vm_is_gpu_shape ? "Oracle-Linux-${var.compute_os_ver}-.*(GPU|NVIDIA|A10).*" : "Oracle-Linux-${var.compute_os_ver}-.*" 14 | ] 15 | regex = true 16 | } 17 | 18 | sort_by = "TIMECREATED" 19 | sort_order = "DESC" 20 | } 21 | 22 | data "oci_core_vcn" "vcn" { 23 | vcn_id = var.vcn_id 24 | } 25 | 26 | data "cloudinit_config" "workers" { 27 | gzip = true 28 | base64_encode = true 29 | 30 | # Expand root filesystem to fill available space on volume 31 | part { 32 | content_type = "text/cloud-config" 33 | content = jsonencode({ 34 | # https://cloudinit.readthedocs.io/en/latest/reference/modules.html#growpart 35 | growpart = { 36 | mode = "auto" 37 | devices = ["/"] 38 | ignore_growroot_disabled = false 39 | } 40 | 41 | # https://cloudinit.readthedocs.io/en/latest/reference/modules.html#resizefs 42 | resize_rootfs = true 43 | 44 | # Resize logical LVM root volume when utility is present 45 | bootcmd = ["if [[ -f /usr/libexec/oci-growfs ]]; then /usr/libexec/oci-growfs -y; fi"] 46 | }) 47 | filename = "10-growpart.yml" 48 | merge_type = "list(append)+dict(no_replace,recurse_list)+str(append)" 49 | } 50 | 51 | # Custom Startup Initialisation (compute and database) 52 | part { 53 | content_type = "text/x-shellscript" 54 | content = local.cloud_init_compute 55 | filename = "50-custom-compute-init.sh" 56 | merge_type = "list(append)+dict(no_replace,recurse_list)+str(append)" 57 | } 58 | part { 59 | content_type = "text/x-shellscript" 60 | content = local.cloud_init_database 61 | filename = "51-custom-database-init.sh" 62 | merge_type = "list(append)+dict(no_replace,recurse_list)+str(append)" 63 | } 64 | } -------------------------------------------------------------------------------- /tests/unit/server/api/utils/test_utils_module_config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Consolidated tests for API utils module configuration (loggers). 6 | These parameterized tests replace individual boilerplate tests in each module file. 7 | """ 8 | 9 | import pytest 10 | 11 | from server.api.utils import chat as utils_chat 12 | from server.api.utils import databases as utils_databases 13 | from server.api.utils import embed as utils_embed 14 | from server.api.utils import mcp 15 | from server.api.utils import models as utils_models 16 | from server.api.utils import oci as utils_oci 17 | from server.api.utils import settings as utils_settings 18 | from server.api.utils import testbed as utils_testbed 19 | 20 | 21 | # Module configurations for parameterized tests 22 | API_UTILS_MODULES = [ 23 | pytest.param(utils_chat, "api.utils.chat", id="chat"), 24 | pytest.param(utils_databases, "api.utils.database", id="databases"), 25 | pytest.param(utils_embed, "api.utils.embed", id="embed"), 26 | pytest.param(mcp, "api.utils.mcp", id="mcp"), 27 | pytest.param(utils_models, "api.utils.models", id="models"), 28 | pytest.param(utils_oci, "api.utils.oci", id="oci"), 29 | pytest.param(utils_settings, "api.core.settings", id="settings"), 30 | pytest.param(utils_testbed, "api.utils.testbed", id="testbed"), 31 | ] 32 | 33 | 34 | class TestLoggerConfiguration: 35 | """Parameterized tests for logger configuration across all API utils modules.""" 36 | 37 | @pytest.mark.parametrize("module,_logger_name", API_UTILS_MODULES) 38 | def test_logger_exists(self, module, _logger_name): 39 | """Each API utils module should have a logger configured.""" 40 | assert hasattr(module, "logger"), f"{module.__name__} should have 'logger'" 41 | 42 | @pytest.mark.parametrize("module,expected_name", API_UTILS_MODULES) 43 | def test_logger_name(self, module, expected_name): 44 | """Each API utils module logger should have the correct name.""" 45 | assert module.logger.name == expected_name, ( 46 | f"{module.__name__} logger name should be '{expected_name}', got '{module.logger.name}'" 47 | ) 48 | -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/templates/ai-optimizer-values.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | global: 6 | api: 7 | secretName: "${label}-optimizer-api-key" 8 | 9 | # -- API Server configuration 10 | server: 11 | image: 12 | repository: ${repository_base}/ai-optimizer-server 13 | tag: "latest" 14 | pullPolicy: Always 15 | 16 | ingress: 17 | enabled: true 18 | className: native-ic 19 | annotations: 20 | nginx.ingress.kubernetes.io/upstream-vhost: "${lb_ip}" 21 | oci-native-ingress.oraclecloud.com/http-listener-port: "8000" 22 | oci-native-ingress.oraclecloud.com/protocol: TCP 23 | 24 | service: 25 | type: "NodePort" 26 | 27 | # -- Enable Workload Identity 28 | oci_config: 29 | oke: true 30 | region: "${oci_region}" 31 | 32 | # -- Oracle Database Configuration 33 | database: 34 | %{ if db_type == "OTHER" ~} 35 | type: "OTHER" 36 | other: 37 | dsn: "${db_dsn}" 38 | %{ else ~} 39 | type: "ADB-S" 40 | oci: 41 | ocid: "${db_ocid}" 42 | %{ endif ~} 43 | authN: 44 | secretName: "${db_name}-optimizer-db-authn" 45 | privAuthN: 46 | secretName: "${db_name}-db-priv-authn" 47 | 48 | client: 49 | enable: true 50 | image: 51 | repository: ${repository_base}/ai-optimizer-client 52 | tag: "latest" 53 | pullPolicy: Always 54 | 55 | ingress: 56 | enabled: true 57 | className: native-ic 58 | annotations: 59 | nginx.ingress.kubernetes.io/upstream-vhost: "${lb_ip}" 60 | oci-native-ingress.oraclecloud.com/http-listener-port: "80" 61 | oci-native-ingress.oraclecloud.com/protocol: TCP 62 | 63 | service: 64 | type: "NodePort" 65 | 66 | features: 67 | disableTestbed: "false" 68 | disableApi: "false" 69 | disableTools: "false" 70 | disableDbCfg: "false" 71 | disableModelCfg: "false" 72 | disableOciCfg: "false" 73 | disableSettings: "false" 74 | 75 | ollama: 76 | enabled: ${node_pool_gpu_deploy} 77 | models: 78 | enabled: true 79 | modelPullList: 80 | - llama3.1 81 | - mxbai-embed-large 82 | resources: 83 | limits: 84 | nvidia.com/gpu: 1 85 | -------------------------------------------------------------------------------- /opentofu/examples/README.md: -------------------------------------------------------------------------------- 1 | # OpenTofu Example Variable Files 2 | 3 | This directory contains example `.tfvars` files for different deployment scenarios. 4 | 5 | ## Quick Start 6 | 7 | ```bash 8 | # Load credentials from ~/.oci/config and run all tests 9 | cd /path/to/your/project/opentofu/ 10 | examples/manual-test.sh 11 | ``` 12 | 13 | The test script automatically loads credentials from `~/.oci/config`, sets compartment to your tenancy root, and runs `tofu plan` on all testable examples. 14 | 15 | ## Example Scenarios 16 | 17 | | File | Description | Infrastructure | Database | 18 | |------|-------------|----------------|----------| 19 | | `vm-new-adb.tfvars` | VM deployment with new Autonomous Database | VM | New ADB | 20 | | `k8s-new-adb.tfvars` | Kubernetes deployment with new ADB | Kubernetes (OKE) | New ADB | 21 | | `vm-arm-shape.tfvars` | VM with ARM (Ampere) compute shape | VM | New ADB (BYOL) | 22 | | `vm-byo-adb.tfvars` | VM with bring-your-own ADB | VM | BYO ADB-S | 23 | | `vm-byo-other-db.tfvars` | VM with BYO other database | VM | BYO OTHER | 24 | | `k8s-byo-other-db.tfvars` | Kubernetes with BYO other database | Kubernetes (OKE) | BYO OTHER | 25 | 26 | ## Manual Setup (Without Helper Script) 27 | 28 | If you prefer not to use the helper script: 29 | 30 | 1. Copy an example: 31 | ```bash 32 | cd /path/to/your/project/opentofu/ 33 | cp examples/vm-new-adb.tfvars terraform.tfvars 34 | ``` 35 | 36 | 2. Edit `terraform.tfvars` and uncomment/set the authentication variables: 37 | ```hcl 38 | tenancy_ocid = "ocid1.tenancy.oc1..aaa..." 39 | compartment_ocid = "ocid1.compartment.oc1..aaa..." 40 | user_ocid = "ocid1.user.oc1..aaa..." 41 | fingerprint = "xx:xx:xx:..." 42 | private_key_path = "~/.oci/oci_api_key.pem" 43 | region = "us-phoenix-1" 44 | ``` 45 | 46 | 3. Run OpenTofu: 47 | ```bash 48 | tofu init 49 | tofu plan 50 | tofu apply 51 | ``` 52 | 53 | ## OCI Config File Format 54 | 55 | The helper script, `examples/manual-test.sh`, reads from `~/.oci/config` which should look like: 56 | 57 | ```ini 58 | [DEFAULT] 59 | user=ocid1.user.oc1..aaa... 60 | tenancy=ocid1.tenancy.oc1..aaa... 61 | region=us-phoenix-1 62 | fingerprint=xx:xx:xx:... 63 | key_file=~/.oci/oci_api_key.pem 64 | ``` 65 | 66 | If you don't have this file, run: `oci setup config` 67 | -------------------------------------------------------------------------------- /.github/workflows/pytest.yml: -------------------------------------------------------------------------------- 1 | # Workflow for running tests on server code 2 | name: Test Suite 3 | 4 | on: 5 | pull_request: 6 | types: 7 | - opened 8 | - synchronize 9 | - reopened 10 | - ready_for_review 11 | 12 | # Allows running this workflow manually 13 | workflow_dispatch: 14 | 15 | jobs: 16 | check: 17 | if: github.event.pull_request.draft == false 18 | runs-on: ubuntu-latest 19 | # Block merging if the job fails 20 | permissions: 21 | pull-requests: write 22 | 23 | steps: 24 | - name: Checkout Code 25 | uses: actions/checkout@v4 26 | 27 | - uses: actions/setup-python@v5 28 | with: 29 | python-version: "3.11" 30 | 31 | - name: Cache dependencies 32 | uses: actions/cache@v4 33 | with: 34 | path: | 35 | ~/.cache/pip 36 | src/.tox 37 | key: ${{ runner.os }}-pip-${{ hashFiles('src/pyproject.toml') }} 38 | restore-keys: | 39 | ${{ runner.os }}-pip- 40 | 41 | - name: Install dependencies 42 | run: | 43 | python -m pip install --upgrade pip wheel setuptools uv 44 | uv pip install torch==2.9.1+cpu -f https://download.pytorch.org/whl/cpu/torch --system 45 | uv pip install -e ".[all-test]" --system 46 | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash 47 | 48 | - name: Run yamllint on Code 49 | run: yamllint . 50 | 51 | - name: Run Helm Lint (basic structure) 52 | run: helm lint helm/ 53 | 54 | - name: Run Helm Lint (with required values) 55 | run: helm lint helm/ --set global.api.apiKey=test-api-key 56 | 57 | - name: Run Pylint on IaC Code 58 | run: pylint opentofu 59 | 60 | - name: Run Pylint on Source Code 61 | run: pylint src 62 | 63 | - name: Run Pylint on Tests 64 | run: pylint tests 65 | 66 | - name: Run All Tests 67 | run: pytest tests -v --junitxml=test-results.xml --cov=src --cov-report=xml --cov-report=term 68 | 69 | - name: Upload Test Results 70 | if: always() 71 | uses: actions/upload-artifact@v4 72 | with: 73 | name: test-results 74 | path: | 75 | test-results.xml 76 | coverage.xml 77 | .coverage 78 | -------------------------------------------------------------------------------- /tests/integration/client/utils/test_st_footer.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=protected-access,import-error,import-outside-toplevel 2 | """ 3 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 4 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 5 | """ 6 | # spell-checker: disable 7 | 8 | import streamlit.components.v1 as components 9 | from client.utils.st_footer import render_chat_footer 10 | 11 | 12 | ############################################################################# 13 | # Test Streamlit UI 14 | ############################################################################# 15 | class TestStreamlit: 16 | """Test the Streamlit UI""" 17 | 18 | # Streamlit File path 19 | ST_FILE = "../src/client/utils/st_footer.py" 20 | 21 | def test_chat_page_disclaimer(self, app_server, app_test, monkeypatch): 22 | """Verify disclaimer appears on chat page""" 23 | assert app_server is not None 24 | 25 | # Mock components.html to capture rendered content 26 | def mock_html(html, **_kwargs): 27 | assert "LLMs can make mistakes. Always verify important information." in html 28 | 29 | monkeypatch.setattr(components, "html", mock_html) 30 | 31 | # Initialize app_test and run component 32 | at = app_test(self.ST_FILE) 33 | at = at.run() 34 | 35 | # Run the footer rendering 36 | render_chat_footer() 37 | 38 | def test_disclaimer_absence_on_other_pages(self, app_server, app_test, monkeypatch): 39 | """Verify disclaimer doesn't appear on non-chat/non-models pages""" 40 | assert app_server is not None 41 | 42 | # Mock components.html to capture rendered content 43 | def mock_html(html, **_kwargs): 44 | assert "LLMs can make mistakes. Always verify important information." not in html 45 | 46 | monkeypatch.setattr(components, "html", mock_html) 47 | 48 | # Initialize app_test and run component 49 | at = app_test(self.ST_FILE) 50 | 51 | # Mock session state for other page rendering 52 | at.session_state.current_page = "other" 53 | at = at.run() 54 | 55 | # Verify disclaimer doesn't appear on other pages 56 | assert "current_page" in at.session_state 57 | assert at.session_state.current_page == "other" 58 | -------------------------------------------------------------------------------- /src/server/api/v1/mcp.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | This file is being used in APIs, and not the backend.py file. 5 | """ 6 | 7 | # spell-checker:ignore noauth fastmcp healthz 8 | from fastapi import APIRouter, Request, Depends 9 | from fastmcp import FastMCP, Client 10 | 11 | import server.api.utils.mcp as utils_mcp 12 | 13 | from common import logging_config 14 | 15 | logger = logging_config.logging.getLogger("api.v1.mcp") 16 | 17 | auth = APIRouter() 18 | 19 | 20 | def get_mcp(request: Request) -> FastMCP: 21 | """Get the MCP engine from the app state""" 22 | return request.app.state.fastmcp_app 23 | 24 | 25 | @auth.get( 26 | "/client", 27 | description="Get MCP Client Configuration", 28 | response_model=dict, 29 | ) 30 | async def get_client(server: str = None, port: int = None) -> dict: 31 | "Get MCP Client Configuration" 32 | return utils_mcp.get_client(server, port) 33 | 34 | 35 | @auth.get( 36 | "/tools", 37 | description="List available MCP tools", 38 | response_model=list[dict], 39 | ) 40 | async def get_tools(mcp_engine: FastMCP = Depends(get_mcp)) -> list[dict]: 41 | """List MCP tools""" 42 | tools_info = [] 43 | try: 44 | client = Client(mcp_engine) 45 | async with client: 46 | tools = await client.list_tools() 47 | logger.debug("MCP Tools: %s", tools) 48 | for tool_object in tools: 49 | tools_info.append(tool_object.model_dump()) 50 | finally: 51 | await client.close() 52 | 53 | return tools_info 54 | 55 | 56 | @auth.get( 57 | "/resources", 58 | description="List MCP resources", 59 | response_model=list[dict], 60 | ) 61 | async def mcp_list_resources(mcp_engine: FastMCP = Depends(get_mcp)) -> list[dict]: 62 | """List MCP Resources""" 63 | resources_info = [] 64 | try: 65 | client = Client(mcp_engine) 66 | async with client: 67 | resources = await client.list_resources() 68 | logger.debug("MCP Resources: %s", resources) 69 | for resources_object in resources: 70 | resources_info.append(resources_object.model_dump()) 71 | finally: 72 | await client.close() 73 | 74 | return resources_info 75 | -------------------------------------------------------------------------------- /docs/content/client/configuration/settings.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = '💾 Settings' 3 | weight = 40 4 | +++ 5 | 6 | 10 | 11 | Once you are happy with the specific configuration of your {{< short_app_ref >}}, the settings can be exported in **.json** format. Those settings can then be loaded in later to return the {{< short_app_ref >}} to your previous configuration. The settings an also be imported into another instance of the {{< short_app_ref >}}. 12 | 13 | ## View and Download 14 | 15 | To view and download the {{< short_app_ref >}} configuration, navigate to the _Configuration_ page and _Settings_ tab: 16 | 17 | ![Download Settings](../images/settings_download.png) 18 | 19 | {{< icon "triangle-exclamation" >}} Settings contain sensitive information such as database passwords and API Keys. By default, these settings will not be exported and will have to be re-entered after uploading the settings in a new instance of the {{< short_app_ref >}}. If you have a secure way to store the settings and would would like to export the sensitive data, tick the "Include Sensitive Settings" box. 20 | 21 | ## Upload 22 | 23 | To upload previously downloaded settings, navigate to `Configuration -> Settings`: 24 | 25 | ![Upload Settings](../images/settings_upload.png) 26 | 27 | 1. Toggle to the "Upload" position 28 | 1. Browse files and select the settings file 29 | 30 | If there are differences found, you can review the differences before clicking "Apply New Settings". 31 | 32 | ## Source Code Templates 33 | 34 | You can download from the console a basic template that could help to expose as a OpenAI API compliant REST endpoint the RAG Chatbot defined in the chat console. 35 | If your configuration has both OLLAMA or OpenAI as providers for chat and embeddings LLMs, it will appear a button named “Download SpringAI”: 36 | 37 | ![SpringAI](../images/settings_spring_ai.png) 38 | 39 | {{% notice style="code" title="No Mixing!" icon="circle-info" %}} 40 | Currently mixed configurations, like Ollama for embeddings and OpenAI for chat completion are not allowed. 41 | {{% /notice %}} 42 | 43 | For more information, about the {{< short_app_ref >}} and **SpringAI**, please view the [Advanced - SpringAI](../../advanced/springai) documentation. -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0.0", "setuptools_scm", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "ai-optimizer" 7 | dynamic = ["version"] 8 | description = "Oracle AI Optimizer and Toolkit" 9 | requires-python = ">=3.11" 10 | license = "UPL-1.0" 11 | authors = [ 12 | {name = "Oracle", email = "obaas_ww@oracle.com"} 13 | ] 14 | 15 | # Common dependencies that are always needed 16 | dependencies = [ 17 | "langchain-core==0.3.80", 18 | "httpx==0.28.1", 19 | "oracledb~=3.1", 20 | "plotly==6.5.0", 21 | ] 22 | 23 | [project.optional-dependencies] 24 | # Server component dependencies 25 | server = [ 26 | "bokeh==3.8.1", 27 | "evaluate==0.4.6", 28 | "faiss-cpu==1.13.0", 29 | "fastapi==0.122.0", 30 | "fastmcp==2.13.1", 31 | "giskard==2.18.0", 32 | "langchain-aimlapi==0.1.0", 33 | "langchain-cohere==0.4.6", 34 | "langchain-community==0.3.31", 35 | #"langchain-fireworks==0.3.0", 36 | "langchain-google-genai==2.1.12", 37 | "langchain-ibm==0.3.20", 38 | "langchain-mcp-adapters==0.1.13", 39 | "langchain-mistralai==0.2.12", 40 | "langchain-nomic==0.1.5", 41 | "langchain-oci==0.1.6", 42 | "langchain-ollama==0.3.10", 43 | "langchain-openai==0.3.35", 44 | "langchain-together==0.3.1", 45 | "langgraph==1.0.1", 46 | "litellm==1.80.7", 47 | "llama-index==0.14.8", 48 | "lxml==6.0.2", 49 | "matplotlib==3.10.7", 50 | "oci~=2.0", 51 | "psutil==7.1.3", 52 | "python-multipart==0.0.20", 53 | "torch==2.9.1", 54 | "umap-learn==0.5.9.post2", 55 | "uvicorn==0.38.0", 56 | ] 57 | 58 | # GUI component dependencies 59 | client = [ 60 | "streamlit== 1.51.0", 61 | ] 62 | 63 | # Test dependencies 64 | test = [ 65 | "docker", 66 | "mypy", 67 | "types-psutil", 68 | "pandas-stubs", 69 | "pylint", 70 | "pytest", 71 | "pytest-asyncio", 72 | "pytest-cov", 73 | "types-jsonschema", 74 | "yamllint" 75 | ] 76 | 77 | # All-in-one installation (server + client) 78 | all = [ 79 | "ai-optimizer[server]", 80 | "ai-optimizer[client]", 81 | ] 82 | 83 | # All-in-one with tests 84 | all-test = [ 85 | "ai-optimizer[server]", 86 | "ai-optimizer[client]", 87 | "ai-optimizer[test]", 88 | ] 89 | 90 | [tool.setuptools] 91 | packages = ["src.server", "src.client", "src.common"] 92 | 93 | [tool.setuptools_scm] 94 | root = "." 95 | fallback_version = "0.0.0" -------------------------------------------------------------------------------- /src/server/wip/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | 6 | import json 7 | 8 | from oracledb import Connection 9 | import server.api.utils.databases as databases 10 | from common.schema import ClientIdType 11 | from common import logging_config 12 | 13 | logger = logging_config.logging.getLogger("server.api.utils.settings") 14 | 15 | 16 | def create_settings_objects(db_conn: Connection) -> None: 17 | """Create table to store Settings""" 18 | settings_tbl = """ 19 | CREATE TABLE IF NOT EXISTS oai_settings ( 20 | name VARCHAR2(255) NOT NULL, 21 | type VARCHAR2(255) NOT NULL, 22 | created TIMESTAMP(9) WITH LOCAL TIME ZONE, 23 | updated TIMESTAMP(9) WITH LOCAL TIME ZONE, 24 | settings JSON, 25 | CONSTRAINT oai_settings_pk PRIMARY KEY (name, type) 26 | ) 27 | """ 28 | logger.info("Creating settings Table") 29 | _ = databases.execute_sql(db_conn, settings_tbl) 30 | 31 | 32 | def upsert_settings( 33 | db_conn: Connection, 34 | name: ClientIdType, 35 | setting_type: str, 36 | json_data: json, 37 | ) -> None: 38 | """Upsert Q&A""" 39 | logger.info("Upsert Settings: %s - %s", name, setting_type) 40 | parsed_data = json.loads(json_data) 41 | if not isinstance(parsed_data, list): 42 | parsed_data = [parsed_data] 43 | json_data = json.dumps(parsed_data) if isinstance(parsed_data, list) else json_data 44 | binds = {"name": name, "setting_type": setting_type, "json_data": json_data} 45 | plsql = """ 46 | DECLARE 47 | l_name oai_settings.name%TYPE := :name; 48 | l_type oai_settings.type%TYPE := :setting_type; 49 | l_qa_obj JSON_OBJECT_T := :json_data; 50 | BEGIN 51 | UPDATE oai_settings SET 52 | updated = CURRENT_TIMESTAMP, 53 | settings = l_qa_object 54 | WHERE name = l_name AND type = l_type; 55 | EXCEPTION WHEN NO_DATA_FOUND 56 | INSERT INTO oai_settings (name, type, created, settings) 57 | VALUES (l_name, l_type, CURRENT_TIMESTAMP, l_qa_object); 58 | END; 59 | """ 60 | logger.debug("Upsert PLSQL: %s", plsql) 61 | return databases.execute_sql(db_conn, plsql, binds) 62 | -------------------------------------------------------------------------------- /docs/content/client/configuration/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = 'Configuration' 3 | menus = 'main' 4 | weight = 100 5 | +++ 6 | 7 | 11 | 12 | The {{< full_app_ref >}} is not configured out-of-the-box. To enable functionality, an embedding model, language model, database, and optionally, Oracle Cloud Infrastructure (OCI) will need to be configured. 13 | 14 | Once you have configured the {{< short_app_ref >}}, the settings can be exported to be imported into another deployment or after a restart. 15 | 16 | ## 🤖 Model Configuration 17 | 18 | At a minimum, a large language model (LLM) will need to be configured to experiment with the {{< short_app_ref >}}. The LLM can be a third-party LLM, such as ChatGPT or Perplexity, or an on-premises LLM. 19 | 20 | Additionally, to enable Retrieval-Augmented Generation (RAG) capabilities, an embedding model will need to be configured and enabled. 21 | 22 | For more information on the currently supported models and how to configure them, please read about [Model Configuration](model_config/). 23 | 24 | {{< icon "star" >}} _If you are experimenting with sensitive, private data_, it is recommended to run both the embedding and LLM on-premises. 25 | 26 | ## 🗄️ Database Configuration 27 | 28 | Oracle AI Database is required to store the embedding vectors to enable Retrieval-Augmented Generation (RAG). The ChatBot can be used without a configured database, but you will be unable to split/embed or experiment with RAG in the ChatBot. 29 | 30 | For more information on configuring the database, please read about [Database Configuration](db_config/). 31 | 32 | ## ☁️ OCI Configuration (Optional) 33 | 34 | Oracle Cloud Infrastructure (OCI) Object Storage buckets can be used to store documents for embedding and to store the split documents before inserting them in the Oracle Database Vector Store. 35 | 36 | Additionally, OCI GenAI services can be used for both private-cloud based LLM and Embedding Models. 37 | 38 | For more information on configuring OCI, please read about [OCI Configuration](oci_config/). 39 | 40 | ## 💾 Settings 41 | 42 | Once you have configured the {{< short_app_ref >}}, you can export the settings and import them after a restart or new deployment. 43 | 44 | For more information on importing (and exporting) settings, please read about [Settings](settings/). 45 | -------------------------------------------------------------------------------- /src/Dockerfile: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker:disable 4 | ################################################## 5 | # Base - All-In-One 6 | # Build from the project root directory: 7 | # podman build -f src/Dockerfile -t ai-optimizer-aio:latest . 8 | ################################################## 9 | FROM container-registry.oracle.com/os/oraclelinux:8 AS all_in_one_pyenv 10 | ENV RUNUSER=oracleai \ 11 | VIRTUAL_ENV=/opt/.venv 12 | 13 | RUN groupadd -g 10001 $RUNUSER && \ 14 | useradd -u 10001 -g $RUNUSER -md /app $RUNUSER && \ 15 | dnf config-manager --add-repo https://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/\$basearch && \ 16 | dnf --nodocs -y install python3.11 python3.11-pip sqlcl java-21-openjdk-headless --nogpgcheck && \ 17 | dnf clean all && \ 18 | python3.11 -m venv --symlinks --upgrade-deps $VIRTUAL_ENV 19 | 20 | COPY --chown=$RUNUSER:$RUNUSER src /opt/package/src 21 | COPY pyproject.toml /opt/package/pyproject.toml 22 | 23 | RUN ${VIRTUAL_ENV}/bin/pip install --upgrade pip wheel setuptools uv && \ 24 | ${VIRTUAL_ENV}/bin/uv pip install torch==2.9.1+cpu -f https://download.pytorch.org/whl/cpu/torch && \ 25 | ${VIRTUAL_ENV}/bin/uv pip install "/opt/package[all]" 26 | 27 | ################################################## 28 | # Application 29 | ################################################## 30 | FROM all_in_one_pyenv AS oai_application 31 | ENV PATH=$VIRTUAL_ENV/bin:$PATH \ 32 | TEMP=/app/tmp \ 33 | TNS_ADMIN=/app/tns_admin \ 34 | OCI_CLI_CONFIG_FILE=/app/runtime/.oci/config \ 35 | TOKENIZERS_PARALLELISM=true \ 36 | NUMBA_CACHE_DIR=/app/tmp \ 37 | MPLCONFIGDIR=/app/tmp \ 38 | TIKTOKEN_CACHE_DIR=/app/tmp \ 39 | NLTK_DATA=/app/tmp \ 40 | API_SERVER_CONTROL="TRUE" 41 | 42 | # Expect the .oci directory to be mounted to /app/.oci 43 | VOLUME ["/app/.oci"] 44 | # Expect the TNS_ADMIN directory to be mounted to /app/tns_admin 45 | VOLUME ["/app/tns_admin"] 46 | 47 | # Prep the app directory 48 | RUN for dir in $TEMP $TNS_ADMIN $(dirname $OCI_CLI_CONFIG_FILE); do \ 49 | install -d -m 0700 -o $RUNUSER -g $RUNUSER $dir; \ 50 | done 51 | COPY --chown=$RUNUSER:$RUNUSER src /app/ 52 | 53 | # Set user and working directory 54 | USER $RUNUSER 55 | WORKDIR /app/ 56 | 57 | RUN chmod +x /app/entrypoint.sh 58 | ENTRYPOINT ["/app/entrypoint.sh"] 59 | -------------------------------------------------------------------------------- /src/client/content/config/config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | 6 | import inspect 7 | import streamlit as st 8 | from streamlit import session_state as state 9 | 10 | from client.content.config.tabs.settings import get_settings, display_settings 11 | from client.content.config.tabs.oci import get_oci, display_oci 12 | from client.content.config.tabs.databases import get_databases, display_databases 13 | from client.content.config.tabs.models import get_models, display_models 14 | from client.content.config.tabs.mcp import get_mcp, display_mcp 15 | from client.content.tools.tabs.prompt_eng import get_prompts 16 | 17 | 18 | def main() -> None: 19 | """Streamlit GUI""" 20 | # Ensure all our configs exist 21 | get_settings() 22 | get_databases() 23 | get_models() 24 | get_oci() 25 | get_mcp() 26 | get_prompts() 27 | 28 | tabs_list = [] 29 | if not state.disabled["settings"]: 30 | tabs_list.append("💾 Settings") 31 | if not state.disabled["db_cfg"]: 32 | tabs_list.append("🗄️ Databases") 33 | if not state.disabled["model_cfg"]: 34 | tabs_list.append("🤖 Models") 35 | if not state.disabled["oci_cfg"]: 36 | tabs_list.append("☁️ OCI") 37 | if not state.disabled["mcp_cfg"]: 38 | tabs_list.append("🔗 MCP") 39 | 40 | # Only create tabs if there is at least one 41 | tab_index = 0 42 | if tabs_list: 43 | tabs = st.tabs(tabs_list) 44 | 45 | # Map tab objects to content conditionally 46 | if not state.disabled["settings"]: 47 | with tabs[tab_index]: 48 | display_settings() 49 | tab_index += 1 50 | if not state.disabled["db_cfg"]: 51 | with tabs[tab_index]: 52 | display_databases() 53 | tab_index += 1 54 | if not state.disabled["model_cfg"]: 55 | with tabs[tab_index]: 56 | display_models() 57 | tab_index += 1 58 | if not state.disabled["oci_cfg"]: 59 | with tabs[tab_index]: 60 | display_oci() 61 | tab_index += 1 62 | if not state.disabled["mcp_cfg"]: 63 | with tabs[tab_index]: 64 | display_mcp() 65 | tab_index += 1 66 | 67 | 68 | if __name__ == "__main__" or "page.py" in inspect.stack()[1].filename: 69 | main() 70 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | *Detailed instructions on how to contribute to the project, if applicable. Must include section about Oracle Contributor Agreement with link and instructions* 2 | 3 | # Contributing to this repository 4 | 5 | We welcome your contributions! There are multiple ways to contribute. 6 | 7 | ## Opening issues 8 | 9 | For bugs or enhancement requests, please file a GitHub issue unless it's 10 | security related. When filing a bug remember that the better written the bug is, 11 | the more likely it is to be fixed. If you think you've found a security 12 | vulnerability, do not raise a GitHub issue and follow the instructions in our 13 | [security policy](./SECURITY.md). 14 | 15 | ## Contributing code 16 | 17 | We welcome your code contributions. Before submitting code via a pull request, 18 | you will need to have signed the [Oracle Contributor Agreement][OCA] (OCA) and 19 | your commits need to include the following line using the name and e-mail 20 | address you used to sign the OCA: 21 | 22 | ```text 23 | Signed-off-by: Your Name 24 | ``` 25 | 26 | This can be automatically added to pull requests by committing with `--sign-off` 27 | or `-s`, e.g. 28 | 29 | ```text 30 | git commit --signoff 31 | ``` 32 | 33 | Only pull requests from committers that can be verified as having signed the OCA 34 | can be accepted. 35 | 36 | ## Pull request process 37 | 38 | 1. Ensure there is an issue created to track and discuss the fix or enhancement 39 | you intend to submit. 40 | 1. Fork this repository. 41 | 1. Create a branch in your fork to implement the changes. We recommend using 42 | the issue number as part of your branch name, e.g. `1234-fixes`. 43 | 1. Ensure that any documentation is updated with the changes that are required 44 | by your change. 45 | 1. Ensure that any samples are updated if the base image has been changed. 46 | 1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly 47 | what your changes are meant to do and provide simple steps on how to validate. 48 | your changes. Ensure that you reference the issue you created as well. 49 | 1. We will assign the pull request to 2-3 people for review before it is merged. 50 | 51 | ## Code of conduct 52 | 53 | Follow the [Golden Rule](https://en.wikipedia.org/wiki/Golden_Rule). If you'd 54 | like more specific guidelines, see the [Contributor Covenant Code of Conduct][COC]. 55 | 56 | [OCA]: https://oca.opensource.oracle.com 57 | [COC]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 58 | -------------------------------------------------------------------------------- /src/client/mcp/rag/rag_base_optimizer_config_mcp.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | 6 | import json # pylint: disable=unused-import 7 | import logging 8 | import os # pylint: disable=unused-import 9 | from typing import List # pylint: disable=unused-import 10 | 11 | from dotenv import load_dotenv # pylint: disable=unused-import 12 | from langchain_core.output_parsers import StrOutputParser # pylint: disable=unused-import 13 | from langchain_core.prompts import PromptTemplate # pylint: disable=unused-import 14 | from langchain_core.runnables import RunnablePassthrough # pylint: disable=unused-import 15 | from mcp.server.fastmcp import FastMCP 16 | 17 | from optimizer_utils import rag # pylint: disable=import-error 18 | 19 | logger = logging.getLogger(__name__) 20 | 21 | logging.basicConfig(level=logging.INFO, format="%(name)s - %(levelname)s - %(message)s") 22 | 23 | 24 | logging.info("Successfully imported libraries and modules") 25 | 26 | CHUNKS_DIR = "chunks_temp" 27 | data = {} 28 | 29 | # Initialize FastMCP server 30 | mcp = FastMCP("rag", host="0.0.0.0", port=9090) # Remote client 31 | # mcp = FastMCP("rag") #Local 32 | 33 | 34 | @mcp.tool() 35 | def rag_tool(question: str) -> str: 36 | """ 37 | Use this tool to answer any question that may benefit from up-to-date or domain-specific information. 38 | 39 | Args: 40 | question: the question for which are you looking for an answer 41 | 42 | Returns: 43 | JSON string with answer 44 | """ 45 | 46 | answer = rag.rag_tool_base(question) 47 | 48 | return f"{answer}" 49 | 50 | 51 | if __name__ == "__main__": 52 | # To dinamically change Tool description: not used but in future maybe 53 | rag_tool_desc = [ 54 | """ 55 | Use this tool to answer any question that may benefit from up-to-date or domain-specific information. 56 | 57 | Args: 58 | question: the question for which are you looking for an answer 59 | 60 | Returns: 61 | JSON string with answer 62 | """ 63 | ] 64 | 65 | # Initialize and run the server 66 | 67 | # Set optimizer_settings.json file ABSOLUTE path 68 | rag.set_optimizer_settings_path("optimizer_settings.json") 69 | 70 | # Change according protocol type 71 | 72 | # mcp.run(transport='stdio') 73 | # mcp.run(transport='sse') 74 | mcp.run(transport="streamable-http") 75 | -------------------------------------------------------------------------------- /src/server/Dockerfile: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | ############################################################# 4 | # Base - API Server 5 | # Build from the project root directory: 6 | # podman build -f src/server/Dockerfile -t ai-optimizer-server:latest . 7 | ############################################################# 8 | # spell-checker: disable 9 | FROM container-registry.oracle.com/os/oraclelinux:8 AS optimizer_base 10 | 11 | ENV RUNUSER=oracleai 12 | ENV RUNUSER=oracleai \ 13 | VIRTUAL_ENV=/opt/.venv 14 | 15 | RUN groupadd -g 10001 $RUNUSER && \ 16 | useradd -u 10001 -g $RUNUSER -md /app $RUNUSER && \ 17 | dnf config-manager --add-repo https://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/\$basearch && \ 18 | dnf --nodocs -y install python3.11 python3.11-pip && \ 19 | dnf clean all && \ 20 | python3.11 -m venv --symlinks --upgrade-deps $VIRTUAL_ENV 21 | 22 | COPY --chown=$RUNUSER:$RUNUSER src /opt/package/src 23 | COPY pyproject.toml /opt/package/pyproject.toml 24 | 25 | RUN ${VIRTUAL_ENV}/bin/pip install --upgrade pip wheel setuptools uv && \ 26 | ${VIRTUAL_ENV}/bin/uv pip install torch==2.9.1+cpu -f https://download.pytorch.org/whl/cpu/torch && \ 27 | ${VIRTUAL_ENV}/bin/uv pip install "/opt/package[server]" 28 | 29 | ################################################## 30 | # Server Application 31 | ################################################## 32 | FROM optimizer_base AS server 33 | ENV PATH=$VIRTUAL_ENV/bin:$PATH \ 34 | TEMP=/app/tmp \ 35 | TNS_ADMIN=/app/tns_admin \ 36 | OCI_CLI_CONFIG_FILE=/app/runtime/.oci/config \ 37 | TOKENIZERS_PARALLELISM=true \ 38 | NUMBA_CACHE_DIR=/app/tmp \ 39 | MPLCONFIGDIR=/app/tmp \ 40 | TIKTOKEN_CACHE_DIR=/app/tmp \ 41 | NLTK_DATA=/app/tmp 42 | 43 | # Expect the .oci directory to be mounted to /app/.oci 44 | VOLUME ["/app/.oci"] 45 | # Expect the TNS_ADMIN directory to be mounted to /app/tns_admin 46 | VOLUME ["/app/tns_admin"] 47 | 48 | # Prep the app directory 49 | RUN for dir in $TEMP $TNS_ADMIN $(dirname $OCI_CLI_CONFIG_FILE); do \ 50 | install -d -m 0700 -o $RUNUSER -g $RUNUSER $dir; \ 51 | done 52 | COPY --chown=$RUNUSER:$RUNUSER src /app/ 53 | RUN rm -rf /app/client /app/.streamlit /app/launch_client.py 54 | 55 | # Set user and working directory 56 | USER $RUNUSER 57 | WORKDIR /app/ 58 | 59 | RUN chmod +x /app/entrypoint.sh 60 | ENTRYPOINT ["/app/entrypoint.sh"] 61 | -------------------------------------------------------------------------------- /opentofu/modules/vm/nsgs.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | resource "oci_core_network_security_group" "compute" { 6 | compartment_id = var.compartment_id 7 | vcn_id = var.vcn_id 8 | display_name = format("%s-compute", var.label_prefix) 9 | lifecycle { 10 | ignore_changes = [defined_tags, freeform_tags] 11 | } 12 | } 13 | 14 | // Rules 15 | resource "oci_core_network_security_group_security_rule" "vcn_tcp_ingress" { 16 | network_security_group_id = oci_core_network_security_group.compute.id 17 | description = "Compute VCN Access - TCP Ingress." 18 | direction = "INGRESS" 19 | protocol = "6" 20 | source = data.oci_core_vcn.vcn.cidr_block 21 | source_type = "CIDR_BLOCK" 22 | } 23 | 24 | resource "oci_core_network_security_group_security_rule" "vcn_icmp_ingress" { 25 | network_security_group_id = oci_core_network_security_group.compute.id 26 | description = "Compute Path Discovery - ICMP Ingress." 27 | direction = "INGRESS" 28 | protocol = "1" 29 | source = data.oci_core_vcn.vcn.cidr_block 30 | source_type = "CIDR_BLOCK" 31 | } 32 | 33 | resource "oci_core_network_security_group_security_rule" "vcn_services_egress" { 34 | network_security_group_id = oci_core_network_security_group.compute.id 35 | description = "Compute OCI Services - All Ingress." 36 | direction = "INGRESS" 37 | protocol = "all" 38 | source = var.oci_services.cidr_block 39 | source_type = "SERVICE_CIDR_BLOCK" 40 | } 41 | 42 | resource "oci_core_network_security_group_security_rule" "vcn_icmp_egress" { 43 | network_security_group_id = oci_core_network_security_group.compute.id 44 | description = "Compute Path Discovery - ICMP Egress." 45 | direction = "EGRESS" 46 | protocol = "1" 47 | destination = "0.0.0.0/0" 48 | destination_type = "CIDR_BLOCK" 49 | } 50 | 51 | resource "oci_core_network_security_group_security_rule" "vcn_tcp_egress" { 52 | network_security_group_id = oci_core_network_security_group.compute.id 53 | description = "Compute Anywhere - TCP Egress." 54 | direction = "EGRESS" 55 | protocol = "6" 56 | destination = "0.0.0.0/0" 57 | destination_type = "CIDR_BLOCK" 58 | } -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/cfgmgt.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | locals { 6 | k8s_manifest = templatefile("${path.module}/templates/k8s-manifest.yaml", { 7 | label = var.label_prefix 8 | repository_host = local.repository_host 9 | repository_base = local.repository_base 10 | compartment_ocid = var.lb.compartment_id 11 | lb_ocid = var.lb.id 12 | lb_subnet_ocid = var.public_subnet_id 13 | lb_ip_ocid = var.lb.ip_address_details[0].ip_address 14 | lb_nsgs = var.lb_nsg_id 15 | lb_min_shape = var.lb.shape_details[0].minimum_bandwidth_in_mbps 16 | lb_max_shape = var.lb.shape_details[0].maximum_bandwidth_in_mbps 17 | db_name = lower(var.db_name) 18 | db_username = var.db_conn.username 19 | db_password = var.db_conn.password 20 | db_service = var.db_conn.service 21 | optimizer_api_key = random_string.optimizer_api_key.result 22 | deploy_buildkit = var.byo_ocir_url == "" 23 | deploy_optimizer = var.deploy_optimizer 24 | optimizer_version = var.optimizer_version 25 | }) 26 | } 27 | 28 | resource "local_sensitive_file" "kubeconfig" { 29 | content = data.oci_containerengine_cluster_kube_config.default_cluster_kube_config.content 30 | filename = "${path.root}/cfgmgt/stage/kubeconfig" 31 | file_permission = 0600 32 | } 33 | 34 | resource "local_sensitive_file" "k8s_manifest" { 35 | content = local.k8s_manifest 36 | filename = "${path.root}/cfgmgt/stage/k8s-manifest.yaml" 37 | file_permission = 0600 38 | } 39 | 40 | resource "null_resource" "apply" { 41 | count = var.run_cfgmgt ? 1 : 0 42 | triggers = { 43 | always_run = "${timestamp()}" 44 | } 45 | 46 | lifecycle { 47 | precondition { 48 | condition = local.can_apply_cfgmgt 49 | error_message = local.cfgmgt_error_message 50 | } 51 | } 52 | 53 | provisioner "local-exec" { 54 | command = < '*.oraclevcn.com', 53 | ace => xs\$ace_type( 54 | privilege_list => xs\$name_list('http', 'connect', 'resolve'), 55 | principal_name => '$DB_USERNAME', 56 | principal_type => xs_acl.ptype_db 57 | ) 58 | ); 59 | END; 60 | / 61 | {{- end }} 62 | {{- if eq (include "server.database.isSIDB" .) "true" }} 63 | STARTUP FORCE; 64 | ALTER SYSTEM REGISTER; 65 | {{- end }} 66 | EOF 67 | {{- end }} 68 | -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/data.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | data "oci_identity_regions" "identity_regions" {} 6 | 7 | data "oci_objectstorage_namespace" "objectstorage_namespace" { 8 | compartment_id = var.compartment_id 9 | } 10 | 11 | data "oci_core_vcn" "vcn" { 12 | vcn_id = var.vcn_id 13 | } 14 | 15 | data "oci_core_subnet" "public" { 16 | subnet_id = var.public_subnet_id 17 | } 18 | data "oci_core_subnet" "private" { 19 | subnet_id = var.private_subnet_id 20 | } 21 | 22 | data "oci_limits_limit_values" "gpu_ad_limits" { 23 | compartment_id = var.tenancy_id 24 | service_name = "compute" 25 | scope_type = "AD" 26 | name = "gpu-a10-count" 27 | } 28 | 29 | # https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/cloudinit_config.html 30 | data "cloudinit_config" "workers" { 31 | gzip = true 32 | base64_encode = true 33 | 34 | # Expand root filesystem to fill available space on volume 35 | part { 36 | content_type = "text/cloud-config" 37 | content = jsonencode({ 38 | # https://cloudinit.readthedocs.io/en/latest/reference/modules.html#growpart 39 | growpart = { 40 | mode = "auto" 41 | devices = ["/"] 42 | ignore_growroot_disabled = false 43 | } 44 | 45 | # https://cloudinit.readthedocs.io/en/latest/reference/modules.html#resizefs 46 | resize_rootfs = true 47 | 48 | # Resize logical LVM root volume when utility is present 49 | bootcmd = ["if [[ -f /usr/libexec/oci-growfs ]]; then /usr/libexec/oci-growfs -y; fi"] 50 | }) 51 | filename = "10-growpart.yml" 52 | merge_type = "list(append)+dict(no_replace,recurse_list)+str(append)" 53 | } 54 | 55 | # OKE startup initialization 56 | part { 57 | content_type = "text/x-shellscript" 58 | content = file("${path.module}/templates/cloudinit-oke.sh") 59 | filename = "50-oke.sh" 60 | merge_type = "list(append)+dict(no_replace,recurse_list)+str(append)" 61 | } 62 | } 63 | 64 | data "oci_containerengine_cluster_kube_config" "default_cluster_kube_config" { 65 | cluster_id = oci_containerengine_cluster.default_cluster.id 66 | } 67 | 68 | data "oci_containerengine_node_pool_option" "images" { 69 | node_pool_option_id = oci_containerengine_cluster.default_cluster.id 70 | compartment_id = var.compartment_id 71 | } 72 | 73 | data "oci_resourcemanager_private_endpoint_reachable_ip" "orm_pe_reachable_ip" { 74 | count = local.create_orm_pe ? 1 : 0 75 | private_endpoint_id = oci_resourcemanager_private_endpoint.orm_pe[0].id 76 | private_ip = split(":", oci_containerengine_cluster.default_cluster.endpoints[0].private_endpoint)[0] 77 | } -------------------------------------------------------------------------------- /tests/integration/server/api/v1/test_probes.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | 5 | Integration tests for server/api/v1/probes.py 6 | 7 | Tests the Kubernetes probe endpoints (liveness, readiness, MCP health). 8 | These endpoints do not require authentication. 9 | """ 10 | 11 | 12 | class TestLivenessProbe: 13 | """Integration tests for the liveness probe endpoint.""" 14 | 15 | def test_liveness_returns_200(self, client): 16 | """GET /v1/liveness should return 200 with status alive.""" 17 | response = client.get("/v1/liveness") 18 | 19 | assert response.status_code == 200 20 | assert response.json() == {"status": "alive"} 21 | 22 | def test_liveness_no_auth_required(self, client): 23 | """GET /v1/liveness should not require authentication.""" 24 | # No auth headers provided 25 | response = client.get("/v1/liveness") 26 | 27 | assert response.status_code == 200 28 | 29 | 30 | class TestReadinessProbe: 31 | """Integration tests for the readiness probe endpoint.""" 32 | 33 | def test_readiness_returns_200(self, client): 34 | """GET /v1/readiness should return 200 with status ready.""" 35 | response = client.get("/v1/readiness") 36 | 37 | assert response.status_code == 200 38 | assert response.json() == {"status": "ready"} 39 | 40 | def test_readiness_no_auth_required(self, client): 41 | """GET /v1/readiness should not require authentication.""" 42 | response = client.get("/v1/readiness") 43 | 44 | assert response.status_code == 200 45 | 46 | 47 | class TestMcpHealthz: 48 | """Integration tests for the MCP health check endpoint.""" 49 | 50 | def test_mcp_healthz_returns_200(self, client): 51 | """GET /v1/mcp/healthz should return 200 with MCP status.""" 52 | response = client.get("/v1/mcp/healthz") 53 | 54 | assert response.status_code == 200 55 | data = response.json() 56 | assert data["status"] == "ready" 57 | assert "name" in data 58 | assert "version" in data 59 | assert "available_tools" in data 60 | 61 | def test_mcp_healthz_no_auth_required(self, client): 62 | """GET /v1/mcp/healthz should not require authentication.""" 63 | response = client.get("/v1/mcp/healthz") 64 | 65 | assert response.status_code == 200 66 | 67 | def test_mcp_healthz_returns_server_info(self, client): 68 | """GET /v1/mcp/healthz should return MCP server information.""" 69 | response = client.get("/v1/mcp/healthz") 70 | 71 | data = response.json() 72 | assert data["name"] == "Oracle AI Optimizer and Toolkit MCP Server" 73 | assert isinstance(data["available_tools"], int) 74 | assert data["available_tools"] >= 0 75 | -------------------------------------------------------------------------------- /src/server/bootstrap/databases.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore configfile 6 | 7 | import os 8 | from server.bootstrap.configfile import ConfigStore 9 | 10 | from common.schema import Database 11 | from common import logging_config 12 | 13 | logger = logging_config.logging.getLogger("bootstrap.databases") 14 | 15 | 16 | def main() -> list[Database]: 17 | """Define Default Database""" 18 | logger.debug("*** Bootstrapping Database - Start") 19 | configuration = ConfigStore.get() 20 | db_configs = configuration.database_configs if configuration and configuration.database_configs else [] 21 | 22 | # Check for Duplicates from Configfile 23 | seen = set() 24 | for db in db_configs: 25 | db_name_lower = db.name.lower() 26 | if db_name_lower in seen: 27 | raise ValueError(f"Duplicate database name found in config: '{db.name}'") 28 | seen.add(db_name_lower) 29 | 30 | database_objects = [] 31 | default_found = False 32 | 33 | for db in db_configs: 34 | if db.name.upper() == "DEFAULT": 35 | default_found = True 36 | updated = db.model_copy( 37 | update={ 38 | "user": os.getenv("DB_USERNAME", db.user), 39 | "password": os.getenv("DB_PASSWORD", db.password), 40 | "dsn": os.getenv("DB_DSN", db.dsn), 41 | "wallet_password": os.getenv("DB_WALLET_PASSWORD", db.wallet_password), 42 | "config_dir": os.getenv("TNS_ADMIN", db.config_dir or "tns_admin"), 43 | } 44 | ) 45 | if updated.wallet_password: 46 | updated.wallet_location = updated.config_dir 47 | logger.info("Setting WALLET_LOCATION: %s", updated.config_dir) 48 | database_objects.append(updated) 49 | else: 50 | database_objects.append(db) 51 | 52 | # If DEFAULT wasn't in config, create it from env vars 53 | if not default_found: 54 | data = { 55 | "name": "DEFAULT", 56 | "user": os.getenv("DB_USERNAME"), 57 | "password": os.getenv("DB_PASSWORD"), 58 | "dsn": os.getenv("DB_DSN"), 59 | "wallet_password": os.getenv("DB_WALLET_PASSWORD"), 60 | "config_dir": os.getenv("TNS_ADMIN", "tns_admin"), 61 | } 62 | if data["wallet_password"]: 63 | data["wallet_location"] = data["config_dir"] 64 | logger.info("Setting WALLET_LOCATION: %s", data["config_dir"]) 65 | database_objects.append(Database(**data)) 66 | 67 | logger.debug("Bootstrapped Databases: %s", database_objects) 68 | logger.debug("*** Bootstrapping Database - End") 69 | return database_objects 70 | 71 | 72 | if __name__ == "__main__": 73 | main() 74 | -------------------------------------------------------------------------------- /src/server/mcp/proxies/sqlcl.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore sqlcl fastmcp connmgr noupdates savepwd 6 | 7 | import os 8 | import shutil 9 | import subprocess 10 | 11 | import server.api.utils.databases as utils_databases 12 | 13 | from common import logging_config 14 | 15 | logger = logging_config.logging.getLogger("mcp.proxies.sqlcl") 16 | 17 | 18 | async def register(mcp): 19 | """Register the SQLcl MCP Server as Local (via Proxy)""" 20 | tool_name = "SQLclProxy" 21 | 22 | sqlcl_binary = shutil.which("sql") 23 | if sqlcl_binary: 24 | env_vars = os.environ.copy() 25 | env_vars["TNS_ADMIN"] = os.getenv("TNS_ADMIN", "tns_admin") 26 | config = { 27 | "mcpServers": { 28 | tool_name: { 29 | "name": tool_name, 30 | "command": f"{sqlcl_binary}", 31 | "args": ["-mcp", "-daemon=start", "-thin", "-noupdates"], 32 | "env": env_vars, 33 | } 34 | } 35 | } 36 | databases = utils_databases.get_databases(validate=False) 37 | for database in databases: 38 | # Start sql in no-login mode 39 | try: 40 | proc = subprocess.Popen( 41 | [sqlcl_binary, "/nolog"], 42 | stdin=subprocess.PIPE, 43 | stdout=subprocess.PIPE, 44 | stderr=subprocess.PIPE, 45 | text=True, 46 | env=env_vars, 47 | ) 48 | 49 | # Prepare commands: connect, then exit 50 | commands = [ 51 | f"connmgr delete -conn OPTIMIZER_{database.name}", 52 | ( 53 | f"conn -savepwd -save OPTIMIZER_{database.name} " 54 | f"-user {database.user} -password {database.password} " 55 | f"-url {database.dsn}" 56 | ), 57 | "exit", 58 | ] 59 | 60 | # Send commands joined by newlines 61 | proc.communicate("\n".join(commands) + "\n") 62 | logger.info("Established Connection Store for: %s", database.name) 63 | except subprocess.SubprocessError as ex: 64 | logger.error("Failed to create connection store: %s", ex) 65 | except Exception as ex: 66 | logger.error("Unexpected error creating connection store: %s", ex) 67 | 68 | # Create a proxy to the configured server (auto-creates ProxyClient) 69 | proxy = mcp.as_proxy(config, name=tool_name) 70 | mcp.mount(proxy, as_proxy=False, prefix="sqlcl") 71 | else: 72 | logger.warning("Not enabling SQLcl MCP server, sqlcl not found in PATH.") 73 | -------------------------------------------------------------------------------- /helm/templates/server/database/init-job.yaml: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | ## Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 3 | # spell-checker: ignore nindent sqlcl sqlplus 4 | 5 | # Database Initialization Job 6 | {{- if .Values.server.database }} 7 | {{- if .Values.server.database.privAuthN }} 8 | apiVersion: batch/v1 9 | kind: Job 10 | metadata: 11 | name: {{ include "global.fullname" . }}-run-sql-{{ .Release.Revision }} 12 | labels: 13 | app.kubernetes.io/component: database 14 | {{- include "global.labels" . | nindent 4 }} 15 | spec: 16 | ttlSecondsAfterFinished: 300 # 5 minutes 17 | template: 18 | spec: 19 | restartPolicy: Never 20 | containers: 21 | - name: oracle-sqlcl-runner 22 | image: container-registry.oracle.com/database/sqlcl:latest 23 | env: 24 | - name: TNS_ADMIN 25 | value: /app/tns_admin 26 | - name: API_SERVER_HOST 27 | value: {{ include "server.serviceName" . }} 28 | - name: API_SERVER_KEY 29 | valueFrom: 30 | secretKeyRef: 31 | name: {{ include "global.apiSecretName" . }} 32 | key: {{ include "global.apiSecretKey" . }} 33 | - name: PRIV_USERNAME 34 | valueFrom: 35 | secretKeyRef: 36 | name: {{ .Values.server.database.privAuthN.secretName }} 37 | key: {{ default "username" .Values.server.database.privAuthN.usernameKey }} 38 | - name: PRIV_PASSWORD 39 | valueFrom: 40 | secretKeyRef: 41 | name: {{ .Values.server.database.privAuthN.secretName }} 42 | key: {{ default "password" .Values.server.database.privAuthN.passwordKey }} 43 | {{- include "server.database.authN" . | nindent 8 }} 44 | command: ["/bin/sh", "-c"] 45 | args: 46 | - | 47 | attempt=1 48 | while [ "$attempt" -lt 360 ]; do 49 | sh /opt/oracle/scripts/startup/init.sh 50 | if [ $? -eq 0 ]; then 51 | exit 0 52 | fi 53 | echo "Waiting for connectivity to ${DB_DSN} ($attempt/360)" 54 | sleep 10 55 | attempt=$((attempt + 1)) 56 | done 57 | volumeMounts: 58 | - name: db-init-scripts 59 | mountPath: /opt/oracle/scripts/startup 60 | {{- if eq (include "server.database.isADBS" .) "true" }} 61 | - name: tns-admin 62 | mountPath: /app/tns_admin 63 | {{- end }} 64 | volumes: 65 | - name: db-init-scripts 66 | configMap: 67 | name: {{ include "global.fullname" . }}-db-init 68 | {{- if eq (include "server.database.isADBS" .) "true" }} 69 | - name: tns-admin 70 | secret: 71 | secretName: {{ .Release.Name }}-adb-tns-admin-{{ .Release.Revision }} 72 | {{- end }} 73 | {{- end }} 74 | {{- end }} 75 | -------------------------------------------------------------------------------- /opentofu/modules/kubernetes/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, 2025, Oracle and/or its affiliates. 2 | # All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl 3 | # spell-checker: disable 4 | 5 | variable "tenancy_id" { 6 | type = string 7 | } 8 | 9 | variable "compartment_id" { 10 | type = string 11 | } 12 | 13 | variable "vcn_id" { 14 | type = string 15 | } 16 | 17 | variable "oci_services" { 18 | description = "OCI Services Network object containing id, name, and cidr_block" 19 | type = object({ 20 | cidr_block = string 21 | id = string 22 | name = string 23 | }) 24 | } 25 | 26 | variable "public_subnet_id" { 27 | type = string 28 | } 29 | 30 | variable "private_subnet_id" { 31 | type = string 32 | } 33 | 34 | variable "orm_install" { 35 | type = bool 36 | } 37 | 38 | variable "lb" { 39 | type = object({ 40 | id = string 41 | compartment_id = string 42 | ip_address_details = list(object({ 43 | ip_address = string 44 | })) 45 | shape_details = list(object({ 46 | minimum_bandwidth_in_mbps = number 47 | maximum_bandwidth_in_mbps = number 48 | })) 49 | }) 50 | } 51 | 52 | variable "region" { 53 | type = string 54 | } 55 | 56 | variable "availability_domains" { 57 | type = list(any) 58 | } 59 | 60 | variable "label_prefix" { 61 | type = string 62 | } 63 | 64 | variable "db_ocid" { 65 | type = string 66 | } 67 | variable "db_name" { 68 | type = string 69 | } 70 | 71 | variable "db_conn" { 72 | type = object({ 73 | db_type = string 74 | username = string 75 | password = string 76 | service = string 77 | }) 78 | } 79 | 80 | variable "kubernetes_version" { 81 | type = string 82 | } 83 | 84 | variable "api_is_public" { 85 | type = bool 86 | } 87 | 88 | variable "node_pool_gpu_deploy" { 89 | type = bool 90 | } 91 | 92 | variable "cpu_node_pool_size" { 93 | type = number 94 | } 95 | 96 | variable "gpu_node_pool_size" { 97 | type = number 98 | } 99 | 100 | variable "compute_gpu_shape" { 101 | type = string 102 | } 103 | 104 | variable "compute_os_ver" { 105 | type = string 106 | } 107 | 108 | variable "compute_cpu_shape" { 109 | type = string 110 | } 111 | 112 | variable "compute_cpu_ocpu" { 113 | type = number 114 | } 115 | 116 | variable "lb_nsg_id" { 117 | type = string 118 | } 119 | 120 | variable "api_endpoint_allowed_cidrs" { 121 | type = string 122 | default = "" 123 | } 124 | 125 | variable "run_cfgmgt" { 126 | type = bool 127 | } 128 | 129 | variable "byo_ocir_url" { 130 | type = string 131 | } 132 | 133 | variable "use_cluster_addons" { 134 | type = bool 135 | default = true 136 | } 137 | 138 | variable "optimizer_version" { 139 | type = string 140 | } 141 | 142 | variable "deploy_optimizer" { 143 | type = bool 144 | default = true 145 | } -------------------------------------------------------------------------------- /src/server/mcp/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | """ 5 | # spell-checker:ignore fastapi fastmcp 6 | 7 | import importlib 8 | import pkgutil 9 | 10 | from fastapi import APIRouter 11 | from fastmcp import FastMCP 12 | 13 | from common import logging_config 14 | 15 | logger = logging_config.logging.getLogger("mcp.__init__.py") 16 | 17 | 18 | async def _discover_and_register( 19 | package: str, 20 | mcp: FastMCP = None, 21 | auth: APIRouter = None, 22 | ): 23 | """Import all modules in a package and call their register function.""" 24 | try: 25 | pkg = importlib.import_module(package) 26 | except ImportError: 27 | logger.warning("Package %s not found, skipping.", package) 28 | return 29 | 30 | for module_info in pkgutil.walk_packages(pkg.__path__, prefix=f"{package}."): 31 | if module_info.name.endswith("__init__"): 32 | continue 33 | 34 | try: 35 | module = importlib.import_module(module_info.name) 36 | except (ImportError, ModuleNotFoundError, AttributeError, SyntaxError, ValueError) as ex: 37 | logger.error("Failed to import %s: %s", module_info.name, ex) 38 | continue 39 | 40 | # Decide what to register based on available functions 41 | if hasattr(module, "register"): 42 | logger.info("Registering via %s.register()", module_info.name) 43 | if ".prompts." in module.__name__: 44 | logger.info("Registering prompt via %s.register_prompt()", module_info.name) 45 | await module.register(mcp) 46 | if ".tools." in module.__name__: 47 | logger.info("Registering tool via %s.register_tool()", module_info.name) 48 | await module.register(mcp, auth) 49 | if ".proxies." in module.__name__: 50 | logger.info("Registering proxy via %s.register_proxy()", module_info.name) 51 | await module.register(mcp) 52 | if ".resources." in module.__name__: 53 | logger.info("Registering resource via %s.register_resource()", module_info.name) 54 | await module.register(mcp) 55 | else: 56 | logger.debug("No register function in %s, skipping.", module_info.name) 57 | 58 | 59 | async def register_all_mcp(mcp: FastMCP, auth: APIRouter): 60 | """ 61 | Auto-discover and register all MCP tools, prompts, resources, and proxies. 62 | """ 63 | logger.info("Starting Registering MCP Components") 64 | await _discover_and_register("server.mcp.tools", mcp=mcp, auth=auth) 65 | await _discover_and_register("server.mcp.proxies", mcp=mcp) 66 | await _discover_and_register("server.mcp.prompts", mcp=mcp) 67 | await _discover_and_register("server.mcp.resources", mcp=mcp) 68 | logger.info("Finished Registering MCP Components") 69 | -------------------------------------------------------------------------------- /widget/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024, 2025, Oracle and/or its affiliates. 3 | Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. 4 | */ 5 | 6 | const chatBotUrl = 'http://127.0.0.1:8000/v1/chat/completions'; 7 | const api_key = "abc"; 8 | 9 | document.addEventListener('DOMContentLoaded', () => { 10 | const openChatBtn = document.getElementById('open-chat-btn'); 11 | const closeChatBtn = document.getElementById('close-chat-btn'); 12 | const chatWidget = document.getElementById('chat-widget'); 13 | const sendBtn = document.getElementById('send-btn'); 14 | const chatInput = document.getElementById('chat-input'); 15 | const chatMessages = document.getElementById('chat-messages'); 16 | 17 | openChatBtn.addEventListener('click', () => { 18 | chatWidget.classList.remove('chat-hidden'); 19 | openChatBtn.style.display = 'none'; 20 | }); 21 | 22 | closeChatBtn.addEventListener('click', () => { 23 | chatWidget.classList.add('chat-hidden'); 24 | openChatBtn.style.display = 'block'; 25 | }); 26 | 27 | 28 | sendBtn.addEventListener('click', async () => { 29 | const userMessage = chatInput.value; 30 | if (userMessage.trim()) { 31 | appendMessage(userMessage, 'user-message'); 32 | chatInput.value = ''; 33 | 34 | const botResponse = await getBotResponse(userMessage); 35 | appendMessage(botResponse, 'bot-message'); 36 | } 37 | }); 38 | 39 | 40 | function appendMessage(message, className) { 41 | const messageElement = document.createElement('div'); 42 | messageElement.classList.add('message', className); 43 | messageElement.textContent = message; 44 | chatMessages.appendChild(messageElement); 45 | chatMessages.scrollTop = chatMessages.scrollHeight; // Auto-scroll to the bottom 46 | } 47 | 48 | async function getBotResponse(userMessage) { 49 | const apiUrl = chatBotUrl; 50 | const messagePayload = { 51 | model: "", 52 | messages: [ 53 | { 54 | role: "user", 55 | content: userMessage 56 | } 57 | ] 58 | }; 59 | 60 | 61 | 62 | try { 63 | const response = await fetch(apiUrl, { 64 | method: 'POST', 65 | headers: { 66 | 'Content-Type': 'application/json', 67 | 'Authorization': 'Bearer ' + api_key 68 | }, 69 | body: JSON.stringify(messagePayload) 70 | }); 71 | 72 | const data = await response.json(); 73 | //return data.answer; 74 | return data.choices[0].text + "\n Source: " + data.sources[0]; 75 | } catch (error) { 76 | console.error('Error fetching API:', error); 77 | return "Sorry, I couldn't connect to the server."; 78 | } 79 | } 80 | }); 81 | 82 | 83 | 84 | 85 | 86 | --------------------------------------------------------------------------------