├── .github └── workflows │ ├── banned_file_changes_pr.yml │ ├── cla.yml │ ├── license_audit.yml │ ├── release-zip-file.yml │ ├── repolinter.yml │ └── sonarcloud.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── data ├── oci_format.jsonl └── your_data_goes_here ├── img ├── arch.PNG ├── available_finetuning_models.png ├── bucket_1.PNG ├── bucket_2.PNG ├── cluster_created.png ├── cluster_creation.png ├── create_model.PNG ├── create_model_2.PNG ├── finetuning.png ├── finished_hosting.PNG ├── hosting.PNG ├── hosting_2.PNG ├── likelihoods.PNG ├── model_performance.PNG ├── new_model_1.PNG ├── new_model_2.PNG ├── new_model_3.PNG ├── playground_1.PNG └── playground_generations.PNG ├── license_policy.yml ├── release_files.json ├── repolinter.json ├── requirements.txt ├── scripts └── preprocess_json.py └── sonar-project.properties /.github/workflows/banned_file_changes_pr.yml: -------------------------------------------------------------------------------- 1 | name: Banned file changes (PR) 2 | on: 3 | # pull_request: 4 | # branches: [ "**/*" ] 5 | pull_request_target: 6 | 7 | jobs: 8 | check_for_banned_file_changes: 9 | name: Look for unsupported (banned) file modifications on PRs 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: 'Get number of git commits' 13 | uses: oracle-devrel/action-git-num-commits@v0.1-alpha6 14 | id: num_commits 15 | with: 16 | pull_url: ${{ github.event.pull_request.url }} 17 | - name: 'Checkout repo' 18 | uses: actions/checkout@v2 19 | with: 20 | ref: ${{ github.event.pull_request.head.ref }} 21 | repository: ${{ github.event.pull_request.head.repo.full_name }} 22 | fetch-depth: ${{ steps.num_commits.outputs.fetch_depth }} 23 | - name: Get file changes 24 | uses: oracle-devrel/action-git-files-changed@v0.1-alpha2 25 | id: files 26 | with: 27 | pull_url: ${{ github.event.pull_request.url }} 28 | - name: Look for changes to .github 29 | if: contains(steps.files.outputs.all_files_changed, '.github') 30 | run: | 31 | echo 'Changes to files in .github are not allowed.' 32 | - name: Comment if .github changed 33 | if: contains(steps.files.outputs.all_files_changed, '.github') 34 | uses: mshick/add-pr-comment@v1 35 | with: 36 | message: | 37 | :no_entry: **Banned Files Modified** 38 | Changes to files in `.github` are not permitted. Please revert your changes and re-submit a new PR. Simply changing the file back to its original state and re-committing won't work (you must revert the changes made to it). 39 | repo-token: ${{ secrets.GITHUB_TOKEN }} 40 | - name: Look for changes to license_policy.yml 41 | if: contains(steps.files.outputs.all_files_changed, '"license_policy.yml"') 42 | run: | 43 | echo 'Changes to license_policy.yml are not allowed.' 44 | - name: Comment if license_policy.yml changed 45 | if: contains(steps.files.outputs.all_files_changed, '"license_policy.yml"') 46 | uses: mshick/add-pr-comment@v1 47 | with: 48 | message: | 49 | :no_entry: **Banned Files Modified** 50 | Changes to `license_policy.yml` are not permitted. Please revert your changes and re-submit a new PR. Simply changing the file back to its original state and re-committing won't work (you must revert the changes made to it). 51 | repo-token: ${{ secrets.GITHUB_TOKEN }} 52 | - name: Look for changes to repolinter.json 53 | if: contains(steps.files.outputs.all_files_changed, '"repolinter.json"') 54 | uses: mshick/add-pr-comment@v1 55 | with: 56 | message: | 57 | :no_entry: **Banned Files Modified** 58 | Changes to `repolinter.json` are not permitted. Please revert your changes and re-submit a new PR. Simply changing the file back to its original state and re-committing won't work (you must revert the changes made to it). 59 | repo-token: ${{ secrets.GITHUB_TOKEN }} 60 | - name: Comment if repolinter.json changed 61 | if: contains(steps.files.outputs.all_files_changed, '"repolinter.json"') 62 | run: | 63 | echo 'Changes to repolinter.json are not allowed.' 64 | - name: Look for changes to sonar-project.properties 65 | if: contains(steps.files.outputs.all_files_changed, '"sonar-project.properties"') 66 | uses: mshick/add-pr-comment@v1 67 | with: 68 | message: | 69 | :no_entry: **Banned Files Modified** 70 | Changes to `sonar-project.properties` are not permitted. Please revert your changes and re-submit a new PR. Simply changing the file back to its original state and re-committing won't work (you must revert the changes made to it). 71 | repo-token: ${{ secrets.GITHUB_TOKEN }} 72 | - name: Comment if sonar-project.properties changed 73 | if: contains(steps.files.outputs.all_files_changed, '"sonar-project.properties"') 74 | run: | 75 | echo 'Changes to sonar-project.properties are not allowed.' 76 | - name: Fail on banned file changes 77 | if: contains(steps.files.outputs.all_files_changed, '.github') || contains(steps.files.outputs.all_files_changed, '"license_policy.yml"') || contains(steps.files.outputs.all_files_changed, '"repolinter.json"') || contains(steps.files.outputs.all_files_changed, '"sonar-project.properties"') 78 | run: | 79 | exit 1 -------------------------------------------------------------------------------- /.github/workflows/cla.yml: -------------------------------------------------------------------------------- 1 | name: "CLA Assistant" 2 | on: 3 | issue_comment: 4 | types: [created] 5 | pull_request_target: 6 | types: [opened,closed,synchronize] 7 | 8 | jobs: 9 | CLAssistant: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: "CLA Assistant" 13 | if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' 14 | # Beta Release 15 | uses: cla-assistant/github-action@v2.1.2-beta 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | # the below token should have repo scope and must be manually added by you in the repository's secret 19 | PERSONAL_ACCESS_TOKEN : ${{ secrets.PERSONAL_ACCESS_TOKEN }} 20 | with: 21 | # for per-repo CLA-acceptance: 22 | # path-to-signatures: 'signatures/oca-20210504/${{ github.repository }}' 23 | # for per-GHO CLA-acceptance: 24 | path-to-signatures: 'signatures/oca-20210504/oracledevrel' 25 | path-to-document: 'https://github.com/oracledevrel/devrel-oca-mgmt/blob/main/oca-20210504.md' # e.g. a CLA or a DCO document 26 | # branch should not be protected 27 | branch: 'main' 28 | allowlist: bot* 29 | 30 | #below are the optional inputs - If the optional inputs are not given, then default values will be taken 31 | remote-organization-name: "oracledevrel" # enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) 32 | remote-repository-name: "devrel-oca-mgmt" # enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) 33 | #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' 34 | #signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo' 35 | #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' 36 | #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' 37 | #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' 38 | #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) 39 | #use-dco-flag: true - If you are using DCO instead of CLA 40 | -------------------------------------------------------------------------------- /.github/workflows/license_audit.yml: -------------------------------------------------------------------------------- 1 | name: Audit licenses 2 | on: 3 | pull_request_target: 4 | 5 | jobs: 6 | run_scancode_toolkit: 7 | name: Get inventory of licenses used in project 8 | runs-on: ubuntu-latest 9 | container: 10 | image: ghcr.io/oracledevrel/scancode-toolkit:v21.3.31 11 | credentials: 12 | username: ${{ github.actor }} 13 | password: ${{ secrets.GHCR_PAT }} 14 | steps: 15 | - name: 'Checkout repo' 16 | uses: actions/checkout@v2 17 | with: 18 | ref: ${{ github.event.pull_request.head.ref }} 19 | repository: ${{ github.event.pull_request.head.repo.full_name }} 20 | - name: Run Scancode-toolkit 21 | run: | 22 | scancode -l --ignore licenses.json --ignore .github/**/* --ignore license_policy.yml --license-policy license_policy.yml --only-findings --summary --json-pp licenses.json * 23 | echo "\n\nHere is the licenses.json:\n" 24 | echo $(cat licenses.json) 25 | - name: Look for non-approved licenses 26 | uses: oracle-devrel/action-license-audit@1.0.2 27 | id: analysis 28 | with: 29 | licenses_file: '/github/workspace/licenses.json' 30 | - name: Analysis results 31 | run: echo "${{ steps.analysis.outputs.unapproved_licenses }}" 32 | - name: Comment if analysis finds unapproved licenses 33 | if: steps.analysis.outputs.unapproved_licenses == 'true' 34 | uses: mshick/add-pr-comment@v1 35 | with: 36 | message: | 37 | :no_entry: **License Inspection** 38 | Requires manual inspection. There are some licenses which dictate further analysis and review. 39 | repo-token: ${{ secrets.GITHUB_TOKEN }} 40 | - name: Halt pipeline on unapproved licenses 41 | if: steps.analysis.outputs.unapproved_licenses == 'true' 42 | run: exit 1 43 | -------------------------------------------------------------------------------- /.github/workflows/release-zip-file.yml: -------------------------------------------------------------------------------- 1 | name: Release ZIP file packaging 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | create_zip: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: 'Checkout repo' 12 | uses: actions/checkout@v2 13 | - name: 'Make (and upload) ZIP file(s)' 14 | uses: oracle-devrel/action-release-zip-maker@v0.5 15 | id: zip_maker 16 | with: 17 | github_token: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/repolinter.yml: -------------------------------------------------------------------------------- 1 | name: Repolinter 2 | on: 3 | pull_request_target: 4 | jobs: 5 | run_repolinter: 6 | name: Run Repolinter on pull request 7 | runs-on: ubuntu-latest 8 | container: 9 | image: ghcr.io/oracledevrel/repolinter:v0.11.1 10 | credentials: 11 | username: ${{ github.actor }} 12 | password: ${{ secrets.GHCR_PAT }} 13 | steps: 14 | - name: 'Checkout repo' 15 | uses: actions/checkout@v2 16 | with: 17 | ref: ${{ github.event.pull_request.head.ref }} 18 | repository: ${{ github.event.pull_request.head.repo.full_name }} 19 | - name: Run Repolinter 20 | run: | 21 | set +e 22 | bundle exec /app/bin/repolinter.js lint --format json --rulesetFile repolinter.json . > repolinter_results.json 23 | echo "\n\nHere is the repolinter_results.json:\n" 24 | echo $(cat repolinter_results.json) 25 | exit 0 26 | - name: Analyze the Repolinter results 27 | uses: oracle-devrel/action-repolinter-audit@v0.1-alpha2 28 | id: analysis 29 | with: 30 | json_results_file: '/github/workspace/repolinter_results.json' 31 | - name: Overall analysis results 32 | run: | 33 | echo "Passed: ${{ steps.analysis.outputs.passed }}" 34 | echo "Errored: ${{ steps.analysis.outputs.errored }}" 35 | - name: Comment if analysis finds missing disclaimer 36 | if: steps.analysis.outputs.disclaimer_found == 'false' 37 | uses: mshick/add-pr-comment@v1 38 | with: 39 | message: | 40 | :no_entry: **FAILURE: Missing Disclaimer** 41 | The standard Oracle Disclaimer seems to be missing from the readme. Please add it: 42 | 43 | ORACLE AND ITS AFFILIATES DO NOT PROVIDE ANY WARRANTY WHATSOEVER, EXPRESS OR IMPLIED, FOR ANY SOFTWARE, MATERIAL OR CONTENT OF ANY KIND CONTAINED OR PRODUCED WITHIN THIS REPOSITORY, AND IN PARTICULAR SPECIFICALLY DISCLAIM ANY AND ALL IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. FURTHERMORE, ORACLE AND ITS AFFILIATES DO NOT REPRESENT THAT ANY CUSTOMARY SECURITY REVIEW HAS BEEN PERFORMED WITH RESPECT TO ANY SOFTWARE, MATERIAL OR CONTENT CONTAINED OR PRODUCED WITHIN THIS REPOSITORY. IN ADDITION, AND WITHOUT LIMITING THE FOREGOING, THIRD PARTIES MAY HAVE POSTED SOFTWARE, MATERIAL OR CONTENT TO THIS REPOSITORY WITHOUT ANY REVIEW. USE AT YOUR OWN RISK. 44 | 45 | Details: 46 | ${{ steps.analysis.outputs.disclaimer_details }} 47 | repo-token: ${{ secrets.GITHUB_TOKEN }} 48 | - name: Comment if analysis finds missing readme 49 | if: steps.analysis.outputs.readme_file_found == 'false' 50 | uses: mshick/add-pr-comment@v1 51 | with: 52 | message: | 53 | :no_entry: **FAILURE: Missing README** 54 | The README file seems to be missing. Please add it. 55 | 56 | Details: 57 | ${{ steps.analysis.outputs.readme_file_details }} 58 | repo-token: ${{ secrets.GITHUB_TOKEN }} 59 | - name: Comment if analysis finds missing license 60 | if: steps.analysis.outputs.license_file_found == 'false' 61 | uses: mshick/add-pr-comment@v1 62 | with: 63 | message: | 64 | :no_entry: **FAILURE: Missing LICENSE** 65 | The LICENSE file seems to be missing. Please add it. 66 | 67 | Details: 68 | ${{ steps.analysis.outputs.license_file_details }} 69 | repo-token: ${{ secrets.GITHUB_TOKEN }} 70 | - name: Comment if analysis finds copyright notice missing 71 | if: steps.analysis.outputs.copyright_found == 'false' 72 | uses: mshick/add-pr-comment@v1 73 | with: 74 | message: | 75 | :warning: **WARNING: Missing Copyright Notice(s)** 76 | It's a good idea to have copyright notices at the top of each file. It looks like at least one file was missing this (though it might be further down in the file - this might be a false-positive). 77 | 78 | Details: 79 | ${{ steps.analysis.outputs.copyright_details }} 80 | repo-token: ${{ secrets.GITHUB_TOKEN }} 81 | - name: Halt pipeline if README is missing 82 | if: steps.analysis.outputs.readme_file_found == 'false' 83 | run: exit 1 84 | - name: Halt pipeline if LICENSE is missing 85 | if: steps.analysis.outputs.license_file_found == 'false' 86 | run: exit 1 87 | - name: Halt pipeline if disclaimer is missing 88 | if: steps.analysis.outputs.disclaimer_found == 'false' 89 | run: exit 1 90 | -------------------------------------------------------------------------------- /.github/workflows/sonarcloud.yml: -------------------------------------------------------------------------------- 1 | name: SonarCloud Scan 2 | on: 3 | pull_request_target: 4 | jobs: 5 | sonarcloud: 6 | name: SonarCloud 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout repo 10 | uses: actions/checkout@v2 11 | with: 12 | ref: ${{ github.event.pull_request.head.ref }} 13 | repository: ${{ github.event.pull_request.head.repo.full_name }} 14 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 15 | - name: SonarCloud Scan 16 | uses: SonarSource/sonarcloud-github-action@master 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 19 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two \r 7 | Icon 8 | 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | .com.apple.timemachine.donotpresent 21 | 22 | # Directories potentially created on remote AFP share 23 | .AppleDB 24 | .AppleDesktop 25 | Network Trash Folder 26 | Temporary Items 27 | .apdisk 28 | 29 | # ignore common security keys 30 | .key 31 | .crt 32 | .csr 33 | .pem 34 | 35 | # ignore finance data (read how-to instructions on how to download it) 36 | data/finance_data.json 37 | data/output.jsonl -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to this repository 2 | 3 | We welcome your contributions! There are multiple ways to contribute. 4 | 5 | ## Opening issues 6 | 7 | For bugs or enhancement requests, please file a GitHub issue unless it's 8 | security related. When filing a bug remember that the better written the bug is, 9 | the more likely it is to be fixed. If you think you've found a security 10 | vulnerability, do not raise a GitHub issue and follow the instructions in our 11 | [security policy](./SECURITY.md). 12 | 13 | ## Contributing code 14 | 15 | We welcome your code contributions. Before submitting code via a pull request, 16 | you will need to have signed the [Oracle Contributor Agreement][OCA] (OCA) and 17 | your commits need to include the following line using the name and e-mail 18 | address you used to sign the OCA: 19 | 20 | ```text 21 | Signed-off-by: Your Name 22 | ``` 23 | 24 | This can be automatically added to pull requests by committing with `--sign-off` 25 | or `-s`, e.g. 26 | 27 | ```text 28 | git commit --signoff 29 | ``` 30 | 31 | Only pull requests from committers that can be verified as having signed the OCA 32 | can be accepted. 33 | 34 | ## Pull request process 35 | 36 | 1. Ensure there is an issue created to track and discuss the fix or enhancement 37 | you intend to submit. 38 | 1. Fork this repository. 39 | 1. Create a branch in your fork to implement the changes. We recommend using 40 | the issue number as part of your branch name, e.g. `1234-fixes`. 41 | 1. Ensure that any documentation is updated with the changes that are required 42 | by your change. 43 | 1. Ensure that any samples are updated if the base image has been changed. 44 | 1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly 45 | what your changes are meant to do and provide simple steps on how to validate. 46 | your changes. Ensure that you reference the issue you created as well. 47 | 1. We will assign the pull request to 2-3 people for review before it is merged. 48 | 49 | ## Code of conduct 50 | 51 | Follow the [Golden Rule](https://en.wikipedia.org/wiki/Golden_Rule). If you'd 52 | like more specific guidelines, see the [Contributor Covenant Code of Conduct][COC]. 53 | 54 | [OCA]: https://oca.opensource.oracle.com 55 | [COC]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 56 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OCI LLM Finetuning with OCI Generative AI Service 2 | 3 | [![License: UPL](https://img.shields.io/badge/license-UPL-green)](https://img.shields.io/badge/license-UPL-green) [![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=oracle-devrel_oci-genai-finetuning)](https://sonarcloud.io/dashboard?id=oracle-devrel_oci-genai-finetuning) 4 | 5 | ## Introduction 6 | 7 | When we are working with Large Language Models (LLMs) we typically have the model respond to the training data it has been given. However, training these models is difficult; not only do they use **a lot** of resources (which increases the amount of $$ you need to spend on electricity and hardware), but modifying these behaviors can be quite complex and isn't always straightforward. 8 | 9 | Thankfully, there are some Neural Network implementation optimizations that allow us to do a "smaller training" version of the model with some custom data. This is called **finetuning**. 10 | 11 | Finetuning is ideal when you want to do one of these three things: 12 | 13 | - Change the behavior of the base model in some way (e.g. make this base model behave like a specific celebrity). 14 | - Change the interactions with the model (e.g. let the model know we want short/long answers, telling the model how to interact with the user). 15 | - In some cases, adding **vast** amounts of information that the base model didn't have (e.g. giving the model 5,000 prompt-response interactions so it learns about a specific topic very deeply). We would need as much data as possible (like [this question + answering model](https://www.kaggle.com/datasets/stanfordu/stanford-question-answering-dataset)) to do this. 16 | 17 | > **Note**: If you're interested in Q&A dataset, check out [this guide's annex](https://github.com/jasperan/llm-discord/blob/main/hands-on/guide.md) that I wrote with a compiled list of the best datasets for this task. 18 | 19 | In our case, we will show this demo focusing on option 3: we have lots of prompt-response key-value pairs, and we will modify the behavior of one of the available base models (like `meta.llama-3.1-70b-instruct`) to hyper-specialize it. With the help of the OCI Generative AI Service, we will create custom models by fine-tuning the base models with our own prompt-response dataset. We can create new custom models or create new versions of existing custom models. 20 | 21 | Here is the process we will follow to perform finetuning: 22 | 23 | ![Process for finetuning](./img/finetuning.png) 24 | 25 | ## 0. Prerequisites and setup 26 | 27 | - Oracle Cloud Infrastructure (OCI) Account - [sign up page](https://signup.cloud.oracle.com/) 28 | - [Oracle Cloud Infrastructure Documentation - Generative AI Service](https://docs.oracle.com/en-us/iaas/Content/generative-ai/overview.htm) 29 | - [Oracle Cloud Infrastructure Documentation - GenAI Finetuning](https://docs.oracle.com/en-us/iaas/Content/generative-ai/fine-tune-models.htm) 30 | - [Python 3.10](https://www.python.org/downloads/release/python-3100/) 31 | - [Conda](https://conda.io/projects/conda/en/latest/user-guide/install/index.html) 32 | 33 | For this demo, we will use the OCI Console to access the service and interact with the Finetuning AI Cluster to perform finetuning operations. (You don't need Python or to install the OCI SDK for Python.) 34 | 35 | ## 1. Create the training dataset 36 | 37 | In our case, we are going to create a finetuned, hyper-knowledgeable version of `Llama 3.1` about Finance. Take a look at the introduction if you want to discover [how I found the original dataset.](https://huggingface.co/datasets/gbharti/finance-alpaca/raw/main/Cleaned_date.json) 38 | 39 | Since the AI community has a lot of open-source projects and resources, we don't need to manually curate the finance dataset ourselves: We'll reuse someone elses' finance dataset and finetune on top of it. 40 | 41 | To download the Finance dataset, run the following command in a terminal: 42 | 43 | ```bash 44 | curl -O https://huggingface.co/datasets/gbharti/finance-alpaca/resolve/main/Cleaned_date.json?download=true 45 | ``` 46 | 47 | Now that we have our data, we need to modify it into the expected format by OCI. As per the instructions in the docs, the proper structure for the data is a JSONL file (or JSON Lines), which is a file that contains a new JSON value or object on each line. The file isn't evaluated as a whole, like a regular JSON file, but rather, each line is treated as if it was a separate JSON file. This format lends itself well for storing a set of inputs in JSON format. The OCI Generative AI service accepts a JSONL file for fine-tuning custom models in the following format: 48 | 49 | ```json 50 | {"prompt": "", "completion": ""} 51 | {"prompt": "", "completion": ""} 52 | ``` 53 | 54 | I have created a script to perform this conversion. To run the converter, execute the following command: 55 | 56 | ```bash 57 | cd scripts/ 58 | python preprocess_json.py 59 | ``` 60 | 61 | > **Note**: make sure you have your `data/` directory with the `finance_data.json` file within it. 62 | 63 | Now that we have our training dataset, we're ready for the next step. 64 | 65 | ## 2. Add dataset to Object Storage bucket 66 | 67 | After creating a Bucket in our OCI tenancy: 68 | 69 | ![Bucket Status](./img/bucket_1.PNG) 70 | 71 | We can now upload objects into it. In our case, we put our JSONL-formatted data into this bucket: 72 | 73 | ![Uploading Item](./img/bucket_2.PNG) 74 | 75 | ## 3. Create a fine-tuning dedicated AI cluster 76 | 77 | 1. In the navigation bar of the Console, choose a region that hosts Generative AI, for example, US Midwest (Chicago). If you don't know which region to choose, see Regions with Generative AI. 78 | 2. Open the navigation menu and click **Analytics & AI**. Under **AI Services**, click **Generative AI**. 79 | 3. In the left navigation, choose a compartment that you have permission to work in. 80 | 4. Click **Dedicated AI clusters**. 81 | 5. Click **Create** dedicated AI cluster. 82 | 6. Select a compartment to create the dedicated AI cluster in. The default compartment is the one you selected in step 3, but you can select any compartment that you have permission to work in. 83 | 84 | For **Cluster** type, click Fine-tuning. 85 | 86 | For **Base** model, in the drop-down menu, you'll be able to select the model you desire. For development, I recommend you use a lighter model with a lower context size (like `command-r-16k`) and then scale up for production (and use `llama-3.1-70b-instruct`). Here's the current list of available models: 87 | 88 | ![available models for finetuning](./img/available_finetuning_models.png) 89 | 90 | After selecting the appropriate model that fits your needs best, let's create the dedicated AI cluster: 91 | 92 | ![Cluster creation](./img/cluster_creation.png) 93 | 94 | > **Note**: When you create a dedicated AI cluster for fine-tuning, two units are created for the base model that you choose. Hosting a model requires at least one unit and fine-tuning requires two units, because fine-tuning a model requires more GPUs than hosting a model. The number of units for fine-tuning is hard-coded to two and you can't change it. You can use the same fine-tuning cluster to fine-tune several models. 95 | 96 | ![Cluster created](./img/cluster_created.png) 97 | 98 | ## 4. Create a new custom model on the fine-tuning dedicated AI cluster 99 | 100 | ![New Model Creation](./img/new_model_1.PNG) 101 | 102 | With our finetuning cluster, let's create a custom model. There are two training methods for finetuning available: 103 | 104 | - **T-Few**: recommended for small datasets (<100,000 samples). Also, the most typical use case here is finetuning the base model to follow a different prompt format, or follow different instructions. 105 | - **Vanilla**: for large datasets (>100,000-1M+ samples). Usually applied for complicated semantical understanding improvement (e.g. enhancing the model's understanding about a topic). This is the recommended type of training for our finance example. 106 | 107 | > **Note**: Using small datasets for the Vanilla method might cause overfitting. Overfitting happens when the trained model gives great results for the training data, but can't generalize outputs for unseen data. (Meaning, it didn't really learn a lot, it just hyperspecialized for the test data, but can't transfer that knowledge to all data in the dataset). 108 | 109 | ![New Model Creation](./img/new_model_2.PNG) 110 | 111 | Finally, after we select our dataset from Object Storage, we can create our model. This will take a while, as the model will be trained on the dataset we provided, in our case, containing *67.000+* prompt-response completions. Also, we've decided to run the finetuning cluster for 5 finetuning epochs (the more epochs you specify, the more the LLM will learn and reinforce its knowledge about the content; but it will also take longer). 112 | 113 | ![New Model last step](./img/new_model_3.PNG) 114 | 115 | After creation, we can observe the model's performance here: 116 | 117 | ![Model Performance](./img/model_performance.PNG) 118 | 119 | ## 5. Create endpoint for the custom model 120 | 121 | In order to consume our newly created model, we need to create a hosting dedicated AI cluster. This will expose the model as if it was an API - this means, we're using OCI as an API server that runs inference on our finetuned model. 122 | 123 | > **Note**: Take a look at [these docs](https://docs.oracle.com/en-us/iaas/api/#/en/generative-ai-inference/20231130/) to learn about invoking the model through the Inference API. 124 | 125 | The first time you run the creation of an endpoint, it will check whether you already have a dedicated hosting AI Cluster created. If you don't, it will prompt you to create one: 126 | 127 | ![Hosting AI Cluster](./img/hosting.PNG) 128 | 129 | After creation, we can proceed to create the endpoint: 130 | 131 | ![Hosting AI Cluster - 2](./img/hosting_2.PNG) 132 | 133 | > **Note**: You can enable or disable a content moderation filter. This is useful if you want to filter out any potentially harmful or sensitive content from your model. Also, you'll be able to see how many requests left you have available in your hosting endpoint by looking at its remaining capacity. 134 | 135 | ![Finished Hosting](./img/finished_hosting.PNG) 136 | 137 | We're now ready to interact with the model, either through the endpoint, or via the OCI GenAI Playground. 138 | 139 | ## 6. Run the custom model in the playground 140 | 141 | We can click the following button to launch it in the playground: 142 | 143 | ![Playground - 1](./img/playground_1.PNG) 144 | 145 | Once we're in the playground, we can also modify the model's hyperparameters dynamically with the menu in the right side of the screen. [Have a look at these docs](https://docs.oracle.com/en-us/iaas/Content/generative-ai/concepts.htm) if you want to learn more about all customization options for the model. 146 | 147 | After selecting the newly created `finance_expert`, we can start making generations with our new LLM: 148 | 149 | ![Playground - Generations](./img/playground_generations.PNG) 150 | 151 | If you're wondering why the text is highlighted, it's due to the "show likelihoods" hyperparameter setting: 152 | 153 | ![Likelihoods](./img/likelihoods.PNG) 154 | 155 | We've successfully finetuned a model to adapt a new behavior to its knowledge base! 156 | 157 | ## Demo 158 | 159 | TODO 160 | 161 | [Watch the demo here](https://www.youtube.com/watch?v=XD9u5Dn04WI&list=PLPIzp-E1msraY9To-BB-vVzPsK08s4tQD&index=12) 162 | 163 | ## Tutorial 164 | 165 | TODO 166 | 167 | ## Physical Architecture 168 | 169 | ![arch](./img/arch.PNG) 170 | 171 | ## Contributing 172 | 173 | This project is open source. Please submit your contributions by forking this repository and submitting a pull request! Oracle appreciates any contributions that are made by the open source community. 174 | 175 | ## License 176 | 177 | Copyright (c) 2024 Oracle and/or its affiliates. 178 | 179 | Licensed under the Universal Permissive License (UPL), Version 1.0. 180 | 181 | See [LICENSE](LICENSE) for more details. 182 | 183 | ORACLE AND ITS AFFILIATES DO NOT PROVIDE ANY WARRANTY WHATSOEVER, EXPRESS OR IMPLIED, FOR ANY SOFTWARE, MATERIAL OR CONTENT OF ANY KIND CONTAINED OR PRODUCED WITHIN THIS REPOSITORY, AND IN PARTICULAR SPECIFICALLY DISCLAIM ANY AND ALL IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. FURTHERMORE, ORACLE AND ITS AFFILIATES DO NOT REPRESENT THAT ANY CUSTOMARY SECURITY REVIEW HAS BEEN PERFORMED WITH RESPECT TO ANY SOFTWARE, MATERIAL OR CONTENT CONTAINED OR PRODUCED WITHIN THIS REPOSITORY. IN ADDITION, AND WITHOUT LIMITING THE FOREGOING, THIRD PARTIES MAY HAVE POSTED SOFTWARE, MATERIAL OR CONTENT TO THIS REPOSITORY WITHOUT ANY REVIEW. USE AT YOUR OWN RISK. 184 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /data/oci_format.jsonl: -------------------------------------------------------------------------------- 1 | {"prompt": "", "completion": ""} -------------------------------------------------------------------------------- /data/your_data_goes_here: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/data/your_data_goes_here -------------------------------------------------------------------------------- /img/arch.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/arch.PNG -------------------------------------------------------------------------------- /img/available_finetuning_models.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/available_finetuning_models.png -------------------------------------------------------------------------------- /img/bucket_1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/bucket_1.PNG -------------------------------------------------------------------------------- /img/bucket_2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/bucket_2.PNG -------------------------------------------------------------------------------- /img/cluster_created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/cluster_created.png -------------------------------------------------------------------------------- /img/cluster_creation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/cluster_creation.png -------------------------------------------------------------------------------- /img/create_model.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/create_model.PNG -------------------------------------------------------------------------------- /img/create_model_2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/create_model_2.PNG -------------------------------------------------------------------------------- /img/finetuning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/finetuning.png -------------------------------------------------------------------------------- /img/finished_hosting.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/finished_hosting.PNG -------------------------------------------------------------------------------- /img/hosting.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/hosting.PNG -------------------------------------------------------------------------------- /img/hosting_2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/hosting_2.PNG -------------------------------------------------------------------------------- /img/likelihoods.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/likelihoods.PNG -------------------------------------------------------------------------------- /img/model_performance.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/model_performance.PNG -------------------------------------------------------------------------------- /img/new_model_1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/new_model_1.PNG -------------------------------------------------------------------------------- /img/new_model_2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/new_model_2.PNG -------------------------------------------------------------------------------- /img/new_model_3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/new_model_3.PNG -------------------------------------------------------------------------------- /img/playground_1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/playground_1.PNG -------------------------------------------------------------------------------- /img/playground_generations.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-devrel/oci-genai-finetuning/ae857076cfa50c8ebaefe8e6c772330cf6edb0c7/img/playground_generations.PNG -------------------------------------------------------------------------------- /license_policy.yml: -------------------------------------------------------------------------------- 1 | license_policies: 2 | - license_key: upl-1.0 3 | label: Approved License 4 | color_code: '#00800' 5 | icon: icon-ok-circle 6 | - license_key: bsd-simplified 7 | label: Approved License 8 | color_code: '#00800' 9 | icon: icon-ok-circle 10 | - license_key: bsd-new 11 | label: Approved License 12 | color_code: '#00800' 13 | icon: icon-ok-circle 14 | - license_key: mit 15 | label: Approved License 16 | color_code: '#00800' 17 | icon: icon-ok-circle 18 | - license_key: apache-1.1 19 | label: Approved License 20 | color_code: '#00800' 21 | icon: icon-ok-circle 22 | - license_key: apache-2.0 23 | label: Approved License 24 | color_code: '#00800' 25 | icon: icon-ok-circle 26 | -------------------------------------------------------------------------------- /release_files.json: -------------------------------------------------------------------------------- 1 | // see https://github.com/oracle-devrel/action-release-zip-maker for docs 2 | [ 3 | ] 4 | -------------------------------------------------------------------------------- /repolinter.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/todogroup/repolinter/master/rulesets/schema.json", 3 | "version": 2, 4 | "axioms": {}, 5 | "rules": { 6 | "readme-file-exists" : { 7 | "level": "error", 8 | "rule": { 9 | "type": "file-existence", 10 | "options": { 11 | "globsAny": ["README*"] 12 | } 13 | } 14 | }, 15 | "disclaimer-present" : { 16 | "level": "error", 17 | "rule": { 18 | "type": "file-contents", 19 | "options": { 20 | "globsAll": ["README*"], 21 | "noCase": true, 22 | "fail-on-non-existent": true, 23 | "content": "ORACLE AND ITS AFFILIATES DO NOT PROVIDE ANY WARRANTY WHATSOEVER, EXPRESS OR IMPLIED, FOR ANY SOFTWARE, MATERIAL OR CONTENT OF ANY KIND" 24 | } 25 | } 26 | }, 27 | "license-file-exists" : { 28 | "level": "error", 29 | "rule": { 30 | "type": "file-existence", 31 | "options": { 32 | "globsAny": ["LICENSE*"] 33 | } 34 | } 35 | }, 36 | "copyright-notice-present" : { 37 | "level": "warning", 38 | "rule": { 39 | "type": "file-starts-with", 40 | "options": { 41 | "globsAll": ["**/*"], 42 | "skip-binary-files": true, 43 | "skip-paths-matching": { 44 | "extensions": ["yaml","yml","md","json","xml","tpl","ipynb","pickle","joblib","properties"], 45 | "patterns": ["\\.github"], 46 | "flags": "" 47 | }, 48 | "lineCount": 2, 49 | "patterns": [ 50 | "Copyright \\([cC]\\) [12][90]\\d\\d(\\-[12][90]\\d\\d)? Oracle and/or its affiliates\\." 51 | ], 52 | "succeed-on-non-exist": true 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ujson -------------------------------------------------------------------------------- /scripts/preprocess_json.py: -------------------------------------------------------------------------------- 1 | import ujson as json 2 | import ast 3 | ''' 4 | @author jasperan 5 | this script reads finance_data.json, and changes the format to 6 | adapt to what OCI Generative AI Service expects, an object with type 7 | { 8 | 'prompt': str(), 9 | 'completion': str(), 10 | 'url': str() 11 | } 12 | ''' 13 | 14 | # this list will store all objects before writing into the output file. 15 | json_list = list() 16 | 17 | with open('../data/finance_data.json', 'r', encoding='utf-8') as file: 18 | data = json.load(file) 19 | 20 | for x in data: 21 | # this is the new structure we want to use for OCI Generative AI Service 22 | new_object = { 23 | "prompt": x['instruction'].replace("""'""", """"""), 24 | "completion": x['output'].replace("""'""", """""") 25 | } 26 | if new_object['prompt'] != "" and new_object['completion'] != "": 27 | json_list.append(new_object) 28 | 29 | print('Converting {} prompt-response pairs'.format(len(json_list))) 30 | # for every element in json_list, write everything into a txt file line by line 31 | with open('../data/output.jsonl', 'w') as output_file: 32 | for x in json_list: 33 | # avoid those elements with non-utf8 characters. e.g. 🐥 34 | # we have a huge dataset so these cases are not that important. 35 | try: 36 | output_file.write("{}\n".format(json.dumps(x))) 37 | except Exception as e: 38 | print(e) 39 | pass 40 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=oracle-devrel_oci-genai-finetuning 2 | sonar.organization=oracle-devrel 3 | 4 | # This is the name and version displayed in the SonarCloud UI. 5 | #sonar.projectName=test 6 | #sonar.projectVersion=1.0 7 | 8 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. 9 | #sonar.sources=. 10 | 11 | # Encoding of the source code. Default is default system encoding 12 | #sonar.sourceEncoding=UTF-8 --------------------------------------------------------------------------------