├── .github ├── ISSUE_TEMPLATE │ ├── bug-issue-template.md │ └── feature-request-template.md ├── PULL_REQUEST_TEMPLATE.md ├── labeler.yml └── workflows │ ├── deploy.yml │ └── pull-request.yml ├── .gitignore ├── .pre-commit-config.yaml ├── README.md ├── babel.config.js ├── community ├── contributors.md ├── discussion.md └── how-to-contribute.md ├── docs ├── api-serving │ ├── _category_.json │ ├── img │ │ ├── api-serving-1.png │ │ ├── api-serving-2.png │ │ ├── api-serving-3.png │ │ ├── api-serving-4.png │ │ └── api-serving-5.png │ ├── model-api-on-docker-compose.mdx │ ├── model-api.mdx │ └── overview.mdx ├── database │ ├── _category_.json │ ├── data-generator-docker-compose.mdx │ ├── data-generator-docker.mdx │ ├── data-insertion-loop.mdx │ ├── data-insertion.mdx │ ├── db-server-creation.mdx │ ├── img │ │ ├── db-1.png │ │ ├── db-2.png │ │ ├── db-3.png │ │ ├── db-4.png │ │ └── db-5.png │ ├── overview.mdx │ └── table-creation.mdx ├── fastapi │ ├── _category_.json │ ├── fasapi-crud-pydantic.mdx │ ├── fastapi-crud.mdx │ ├── fastapi-on-docker.mdx │ ├── fastapi-tutorial.mdx │ ├── img │ │ ├── fastapi-1.png │ │ ├── fastapi-2.png │ │ ├── fastapi-3.png │ │ ├── fastapi-4.png │ │ ├── fastapi-5.png │ │ ├── fastapi-6.png │ │ ├── fastapi-7.png │ │ ├── fastapi-8.png │ │ └── fastapi-9.png │ └── overview.mdx ├── img │ ├── architecture.png │ ├── google-trend.png │ ├── mlops-level-0.png │ ├── pipeline.png │ └── rest-api.png ├── intro.mdx ├── kafka │ ├── _category_.json │ ├── connect-connector.mdx │ ├── img │ │ ├── kafka-1.png │ │ ├── kafka-10.png │ │ ├── kafka-11.png │ │ ├── kafka-12.png │ │ ├── kafka-13.png │ │ ├── kafka-14.png │ │ ├── kafka-15.png │ │ ├── kafka-2.png │ │ ├── kafka-3.png │ │ ├── kafka-4.png │ │ ├── kafka-5.png │ │ ├── kafka-6.png │ │ ├── kafka-7.png │ │ ├── kafka-8.png │ │ ├── kafka-9.png │ │ └── kafka-gif-1.gif │ ├── kafka-introduction.mdx │ ├── kafka-system.mdx │ ├── overview.mdx │ ├── producer-consumer.mdx │ ├── sink-connector.mdx │ └── source-connector.mdx ├── model-deployment.mdx ├── model-development │ ├── _category_.json │ ├── base-model-development.mdx │ ├── base-model-pipeline.mdx │ ├── img │ │ ├── model-development-1.png │ │ └── model-development-2.png │ ├── load-data-from-database.mdx │ └── overview.mdx ├── model-registry │ ├── _category_.json │ ├── img │ │ ├── model-registry-1.png │ │ ├── model-registry-10.png │ │ ├── model-registry-11.png │ │ ├── model-registry-2.png │ │ ├── model-registry-3.png │ │ ├── model-registry-4.png │ │ ├── model-registry-5.png │ │ ├── model-registry-6.png │ │ ├── model-registry-7.png │ │ ├── model-registry-8.png │ │ └── model-registry-9.png │ ├── load-model-from-registry.mdx │ ├── mlflow-setup.mdx │ ├── overview.mdx │ └── save-model-to-registry.mdx └── stream │ ├── _category_.json │ ├── dashboard.mdx │ ├── img │ ├── grafana-add-panel-1.png │ ├── grafana-add-panel-2.png │ ├── grafana-add-panel2.png │ ├── grafana-after-login.png │ ├── grafana-after-save.png │ ├── grafana-click-gear.png │ ├── grafana-click-new.png │ ├── grafana-dashboard-setup.png │ ├── grafana-data-source-1.png │ ├── grafana-data-source-2.png │ ├── grafana-data-source-3.png │ ├── grafana-data-source-4.png │ ├── grafana-data-source-5.png │ ├── grafana-data-source-6.png │ ├── grafana-data-source2-1.png │ ├── grafana-data-source2-2.png │ ├── grafana-final-result.gif │ ├── grafana-init-setup.png │ ├── grafana-initial-dashboard.png │ ├── grafana-intro.png │ ├── grafana-move-to-board-1.png │ ├── grafana-move-to-board-2.png │ ├── grafana-panel-1.png │ ├── grafana-panel-2.png │ ├── grafana-panel-3.png │ ├── grafana-save-dashboard.png │ ├── grafana-save-panel-1.png │ ├── grafana-save-panel2.png │ ├── grafana-set-panel-1.png │ ├── grafana-set-panel2.png │ ├── grafana-set-time-1.png │ ├── grafana-set-time-2.png │ ├── grafana-set-time-3.png │ ├── grafana-shape.png │ ├── stream-1.png │ └── stream-2.png │ ├── overview.mdx │ └── stream-serving.mdx ├── docusaurus.config.js ├── i18n ├── en │ ├── code.json │ ├── docusaurus-plugin-content-blog │ │ └── options.json │ ├── docusaurus-plugin-content-docs-community │ │ └── current.json │ ├── docusaurus-plugin-content-docs │ │ ├── current.json │ │ └── current │ │ │ ├── api-serving │ │ │ ├── _category_.json │ │ │ ├── img │ │ │ │ ├── api-serving-1.png │ │ │ │ ├── api-serving-2.png │ │ │ │ ├── api-serving-3.png │ │ │ │ ├── api-serving-4.png │ │ │ │ └── api-serving-5.png │ │ │ ├── model-api-on-docker-compose.mdx │ │ │ ├── model-api.mdx │ │ │ └── overview.mdx │ │ │ ├── database │ │ │ ├── _category_.json │ │ │ ├── data-generator-docker-compose.mdx │ │ │ ├── data-generator-docker.mdx │ │ │ ├── data-insertion-loop.mdx │ │ │ ├── data-insertion.mdx │ │ │ ├── db-server-creation.mdx │ │ │ ├── img │ │ │ │ ├── db-1.png │ │ │ │ ├── db-2.png │ │ │ │ ├── db-3.png │ │ │ │ ├── db-4.png │ │ │ │ └── db-5.png │ │ │ ├── overview.mdx │ │ │ └── table-creation.mdx │ │ │ ├── fastapi │ │ │ ├── _category_.json │ │ │ ├── fasapi-crud-pydantic.mdx │ │ │ ├── fastapi-crud.mdx │ │ │ ├── fastapi-on-docker.mdx │ │ │ ├── fastapi-tutorial.mdx │ │ │ ├── img │ │ │ │ ├── fastapi-1.png │ │ │ │ ├── fastapi-2.png │ │ │ │ ├── fastapi-3.png │ │ │ │ ├── fastapi-4.png │ │ │ │ ├── fastapi-5.png │ │ │ │ ├── fastapi-6.png │ │ │ │ ├── fastapi-7.png │ │ │ │ ├── fastapi-8.png │ │ │ │ └── fastapi-9.png │ │ │ └── overview.mdx │ │ │ ├── img │ │ │ ├── architecture.png │ │ │ ├── google-trend.png │ │ │ ├── mlops-level-0.png │ │ │ ├── pipeline.png │ │ │ └── rest-api.png │ │ │ ├── intro.mdx │ │ │ ├── kafka │ │ │ ├── _category_.json │ │ │ ├── connect-connector.mdx │ │ │ ├── img │ │ │ │ ├── kafka-1.png │ │ │ │ ├── kafka-10.png │ │ │ │ ├── kafka-11.png │ │ │ │ ├── kafka-12.png │ │ │ │ ├── kafka-13.png │ │ │ │ ├── kafka-14.png │ │ │ │ ├── kafka-15.png │ │ │ │ ├── kafka-2.png │ │ │ │ ├── kafka-3.png │ │ │ │ ├── kafka-4.png │ │ │ │ ├── kafka-5.png │ │ │ │ ├── kafka-6.png │ │ │ │ ├── kafka-7.png │ │ │ │ ├── kafka-8.png │ │ │ │ ├── kafka-9.png │ │ │ │ └── kafka-gif-1.gif │ │ │ ├── kafka-introduction.mdx │ │ │ ├── kafka-system.mdx │ │ │ ├── overview.mdx │ │ │ ├── producer-consumer.mdx │ │ │ ├── sink-connector.mdx │ │ │ └── source-connector.mdx │ │ │ ├── model-deployment.mdx │ │ │ ├── model-development │ │ │ ├── _category_.json │ │ │ ├── base-model-development.mdx │ │ │ ├── base-model-pipeline.mdx │ │ │ ├── img │ │ │ │ ├── model-development-1.png │ │ │ │ └── model-development-2.png │ │ │ ├── load-data-from-database.mdx │ │ │ └── overview.mdx │ │ │ ├── model-registry │ │ │ ├── _category_.json │ │ │ ├── img │ │ │ │ ├── model-registry-1.png │ │ │ │ ├── model-registry-10.png │ │ │ │ ├── model-registry-11.png │ │ │ │ ├── model-registry-2.png │ │ │ │ ├── model-registry-3.png │ │ │ │ ├── model-registry-4.png │ │ │ │ ├── model-registry-5.png │ │ │ │ ├── model-registry-6.png │ │ │ │ ├── model-registry-7.png │ │ │ │ ├── model-registry-8.png │ │ │ │ └── model-registry-9.png │ │ │ ├── load-model-from-registry.mdx │ │ │ ├── mlflow-setup.mdx │ │ │ ├── overview.mdx │ │ │ └── save-model-to-registry.mdx │ │ │ └── stream │ │ │ ├── _category_.json │ │ │ ├── dashboard.mdx │ │ │ ├── img │ │ │ ├── grafana-add-panel-1.png │ │ │ ├── grafana-add-panel-2.png │ │ │ ├── grafana-add-panel2.png │ │ │ ├── grafana-after-login.png │ │ │ ├── grafana-after-save.png │ │ │ ├── grafana-click-gear.png │ │ │ ├── grafana-click-new.png │ │ │ ├── grafana-dashboard-setup.png │ │ │ ├── grafana-data-source-1.png │ │ │ ├── grafana-data-source-2.png │ │ │ ├── grafana-data-source-3.png │ │ │ ├── grafana-data-source-4.png │ │ │ ├── grafana-data-source-5.png │ │ │ ├── grafana-data-source-6.png │ │ │ ├── grafana-data-source2-1.png │ │ │ ├── grafana-data-source2-2.png │ │ │ ├── grafana-final-result.gif │ │ │ ├── grafana-init-setup.png │ │ │ ├── grafana-initial-dashboard.png │ │ │ ├── grafana-intro.png │ │ │ ├── grafana-move-to-board-1.png │ │ │ ├── grafana-move-to-board-2.png │ │ │ ├── grafana-panel-1.png │ │ │ ├── grafana-panel-2.png │ │ │ ├── grafana-panel-3.png │ │ │ ├── grafana-save-dashboard.png │ │ │ ├── grafana-save-panel-1.png │ │ │ ├── grafana-save-panel2.png │ │ │ ├── grafana-set-panel-1.png │ │ │ ├── grafana-set-panel2.png │ │ │ ├── grafana-set-time-1.png │ │ │ ├── grafana-set-time-2.png │ │ │ ├── grafana-set-time-3.png │ │ │ ├── grafana-shape.png │ │ │ ├── stream-1.png │ │ │ └── stream-2.png │ │ │ ├── overview.mdx │ │ │ └── stream-serving.mdx │ ├── docusaurus-plugin-content-pages │ │ ├── components │ │ │ └── HomepageFeatures │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.css │ │ ├── index.module.css │ │ └── index.tsx │ └── docusaurus-theme-classic │ │ ├── footer.json │ │ └── navbar.json └── ko │ ├── code.json │ ├── docusaurus-plugin-content-blog │ └── options.json │ ├── docusaurus-plugin-content-docs-community │ └── current.json │ ├── docusaurus-plugin-content-docs │ └── current.json │ └── docusaurus-theme-classic │ ├── footer.json │ └── navbar.json ├── package-lock.json ├── package.json ├── sidebars.js ├── sidebarsCommunity.js ├── src ├── components │ ├── BrowserWindow │ │ ├── index.tsx │ │ └── styles.module.css │ ├── CodeDescription │ │ ├── index.tsx │ │ └── styles.module.css │ ├── Highlight.tsx │ ├── HomepageFeatures │ │ ├── index.tsx │ │ └── styles.module.css │ ├── PreviewDescription │ │ ├── index.tsx │ │ └── styles.module.css │ └── TeamProfileCards │ │ └── index.tsx ├── css │ └── custom.css └── pages │ ├── index.module.css │ └── index.tsx ├── static ├── .nojekyll ├── googlee5904fe980148e9b.html └── img │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── docusaurus.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── logo.png │ ├── logo.svg │ ├── makinarocks.png │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ └── undraw_docusaurus_tree.svg └── tsconfig.json /.github/ISSUE_TEMPLATE/bug-issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug issue template 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | A clear and concise description of what the bug is. 12 | 13 | ## To Reproduce 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | ## Expected behavior 21 | A clear and concise description of what you expected to happen. 22 | 23 | ## Additional context 24 | Add any other context about the problem here. 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request template 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Is your feature request related to a problem? Please describe. 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | ## Describe the solution you'd like 14 | A clear and concise description of what you want to happen. 15 | 16 | ## Additional context 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Changes? 2 | 3 | 4 | ## Why we need? 5 | 6 | 7 | ## Test? 8 | 9 | 10 | ## Related issues? 11 | 12 | 13 | ## Anything Else? (Optional) 14 | 15 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | labels: 3 | - label: "WIP" 4 | title: "^WIP:.*" 5 | - label: "feature" 6 | branch: "^feature/.*" 7 | - label: "bugfix" 8 | branch: "^bugfix/.*" 9 | - label: "hotfix" 10 | branch: "^hotfix/.*" 11 | - label: "enhancement" 12 | branch: "^enhance/.*" 13 | - label: "need-to-change-branch-name" 14 | branch: "^(?!^feature/.*$)(?!^bugfix/.*$)(?!^hotfix/.*$)(?!^enhance/.*$)(?!^style/.*$)(?!^docs/.*$).*$" 15 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | # Review gh actions docs if you want to further define triggers, paths, etc 8 | # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on 9 | workflow_dispatch: 10 | 11 | 12 | jobs: 13 | deploy: 14 | name: Deploy to GitHub Pages 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | - uses: actions/setup-node@v3 19 | with: 20 | node-version: 18 21 | cache: npm 22 | 23 | - name: Install dependencies 24 | run: npm ci 25 | - name: Build website 26 | run: npm run build 27 | 28 | # Popular action to deploy to GitHub Pages: 29 | # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus 30 | - name: Deploy to GitHub Pages 31 | uses: peaceiris/actions-gh-pages@v3 32 | with: 33 | github_token: ${{ secrets.GITHUB_TOKEN }} 34 | # Build output to publish to the `gh-pages` branch: 35 | publish_dir: ./build 36 | # The following lines assign commit authorship to the official 37 | # GH-Actions bot for deploys to `gh-pages` branch: 38 | # https://github.com/actions/checkout/issues/13#issuecomment-724415212 39 | # The GH actions bot is used by default if you didn't specify the two fields. 40 | # You can swap them out with your own user credentials. 41 | user_name: github-actions[bot] 42 | user_email: 41898282+github-actions[bot]@users.noreply.github.com 43 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request" 2 | on: 3 | pull_request: 4 | types: [opened, synchronize, edited, reopened, closed] 5 | 6 | jobs: 7 | label: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: anencore94/labeler@v1.1.0 11 | 12 | pre-commit: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: pre-commit/action@v2.0.0 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | 2 | # See https://pre-commit.com for more information 3 | # See https://pre-commit.com/hooks.html for more hooks 4 | repos: 5 | - repo: https://github.com/pre-commit/pre-commit-hooks 6 | rev: v2.5.0 7 | hooks: 8 | - id: end-of-file-fixer 9 | - id: check-added-large-files 10 | args: ["--maxkb=30000"] 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MLOps for MLE Tutorial 2 | 3 | "머신러닝 엔지니어를 위한 MLOps" 튜토리얼 문서가 있는 레포입니다. 4 | 5 | ## How to start 6 | 7 | 본 저장소는 [Docusaurus 2](https://docusaurus.io/) 로 build 되며, Backend 는 `npm` 을 사용합니다. 8 | 9 | ### Installation 10 | 11 | MacOS 기준으로 설치는 다음과 같습니다. 12 | 13 | `npm` 을 설치합니다. 14 | ```bash 15 | $ brew install npm 16 | ``` 17 | 18 | 필요한 패키지들을 설치합니다. 19 | ```bash 20 | $ npm install 21 | ``` 22 | 23 | ### Check local build 24 | 25 | 수정한 후 로컬에서 실행이 되는지 확인합니다. 26 | 27 | ```bash 28 | $ npm run start 29 | ``` 30 | 31 | ### pre-commit 32 | 33 | pre-commit 을 통과하는지 확인합니다. 34 | 35 | ```bash 36 | $ pre-commit run --a 37 | ``` 38 | 39 | ## How to Contribute? 40 | [How to contribute](community/how-to-contribute.md) 41 | 42 | # For English 43 | 44 | Run site with below code: 45 | 46 | ```bash 47 | $ npm run start -- --locale en 48 | ``` 49 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /community/contributors.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Contributors 6 | 7 | ## Main Authors 8 | 9 | import { 10 | MainAuthorRow, 11 | } from '@site/src/components/TeamProfileCards'; 12 | 13 | 14 | 15 | 16 | ## Reviewers 17 | Thank you for reviewing our tutorials! 18 | 19 | import { 20 | ReviewersRow, 21 | } from '@site/src/components/TeamProfileCards'; 22 | 23 | 24 | -------------------------------------------------------------------------------- /community/discussion.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Discussion 6 | 7 | MLOps for MLE 는 게시판으로 [Github Discussion](https://github.com/mlops-for-mle/tutorial/discussions) 과 [Github Issue](https://github.com/mlops-for-mle/tutorial/issues) 를 이용하고 있습니다. 8 | 9 | ## Question 10 | 학습 중 생기는 궁금증은 [Q&A](https://github.com/mlops-for-mle/tutorial/discussions/categories/q-a) 게시판에 남겨주세요. 11 | 빠른 시일 내에 확인 후 답변하도록 하겠습니다. 12 | 13 | ## Idea 14 | 프로젝트에 추가하면 좋을 것 같은 아이디어는 [IDEA](https://github.com/mlops-for-mle/tutorial/discussions/categories/ideas) 게시판에 남겨주세요. 15 | 16 | ## Issue 17 | 오타 및 오류를 발견하시는 경우에는 [Github Issue](https://github.com/mlops-for-mle/tutorial/issues) 에 제보해주세요! 18 | 19 | 혹은 직접 Pull Request를 요청하셔도 됩니다. 20 | PR 과 관련된 사항은 [How to Contribute](/community/how-to-contribute.md) 를 참고해주세요. 21 | 22 | ## Copyright 23 | 24 | 1. 본 문서를 “비상업적 목적” 사용 시 하기와 같이 출처를 반드시 표시해주세요. 25 | - MLOps for MLE, https://mlops-for-mle.github.io 26 | 2. 상업적 용도로 인용/사용/차용하고자 하는 경우 마키나락스(contact@makinarocks.ai)로 사전에 문의주시기 바랍니다. 27 | -------------------------------------------------------------------------------- /community/how-to-contribute.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # How to Contribute 6 | 7 | ## Code Sync 8 | 9 | ML Engineer 를 위한 MLOps 는 전체 코드를 두 레포에서 관리합니다. 10 | 11 | 코드의 수정이 있을 경우 양 레포 모두에 수정하는 PR을 작성해주셔야 합니다. 12 | - [Code Repo](https://github.com/mlops-for-mle/mlops-for-mle) 13 | - [Tutorial Repo](https://github.com/mlops-for-mle/tutorial) 14 | 15 | ## Table of Contents 16 | 17 | 1. 전체 단위는 파트, 챕터 순으로 작아집니다. 18 | - 파트는 `01.` , `02.` 와 같이 `XX.` 으로 작성합니다. 19 | - 챕터는 `1)`, `2)` 와 같이 `X)` 로 작성합니다. 20 | 2. 이전 파트 혹은 챕터를 언급해야 할 경우 다음과 같이 작성합니다. 21 | - 문서 최상단에 `import { Chapter, Part } from '@site/src/components/Highlight';` 를 입력합니다. 22 | - 파트의 경우 `01. Database` 와 같이 작성합니다. 23 | - 챕터의 경우 `2) Save Model to Registry` 와 같이 작성합니다. 24 | 3. 파트의 구성은 다음과 같이 합니다. 25 | - 모든 파트의 시작 챕터는 `0) Overview` 입니다. 26 | - 여기서는 파트 전체에서 배울 내용의 전반적이 셜명과 구조에 대한 이미지를 작성합니다. 27 | - 단, 실습 코드가 없는 경우에는 `0) Overview` 가 없어도 됩니다. 28 | - 각 챕터의 이름은 영어 명사구로 작성합니다. 29 | 4. 챕터의 구성은 다음과 같이 작성합니다. 30 | - 목표: 여기서 무엇을 배울 건지? 31 | - 목표는 1,2,3 으로 넘버링합니다. 32 | - 스펙 명세서 33 | - 스펙 명세서는 다음과 같이 작성합니다. 34 | 1. 스펙 1 35 | - 스펙 1의 구체적인 내용 A 36 | - 스펙 1의 구체적인 내용 B 37 | 2. 스펙 2 38 | 3. 스펙 3 39 | - e.g) DB 이름은 `mydatabase` 로 하겠습니다. 40 | - 해설 41 | 42 | ## Tone & Manner 43 | 44 | 1. 한글로 작성했을 때 어색한 영어 단어는 최대한 영어로 작성합니다. 이 때 영어 단어 이후 한 칸을 띈 후에 한글을 작성한다. 45 | - ~~영어한글 → API에서~~ 🙅🏻‍♂️ 46 | - 영어 한글 → API 에서 🙆🏻‍♂️ 47 | 2. 코드 스타일 48 | - Python code 는 복붙해서 주피터 노트북에서 실행되는 형태로 합니다. 49 | - `print(df)` 50 | - Bash 코드는 앞에 `$` 붙여 명시합니다. 51 | - 다음과 같이 작성하여 명시할 수 있습니다. 52 | ```md 53 | # terminal-command 54 | your-command 55 | ``` 56 | - 출력은 다음과 같이 됩니다. 57 | ```bash 58 | $ your-command 59 | ``` 60 | - 코드는 해설에 적당한 크기로 끊어서 설명하되 마지막에 코드를 모아서 작성합니다. 61 | 3. 변수에 대한 해석 62 | - 변수에 대한 해석 및 설명은 최초에 한번만 진행합니다. 63 | - 예를 들어, Docker Network 에 대한 설명이 앞장에 있다면 다시 설명하지 않고 넘어갑니다. 64 | - 단, 앞장에서의 상황과 차이점이 발생하는 경우 설명을 추가합니다. 65 | 4. 글꼴 및 문법 66 | - **bold** 는 사용하지 않습니다. 67 | - *Italic* 는 * 또는 <var>key</var> 태그로 단어나 문장을 감싸 표현합니다. 68 | - `코드 블럭` 을 사용하는 경우 69 | - Python, shell script, Dockerfile, 파일 제목 등 실제로 코드에 작성되는 내용들은 모두 `코드 블럭` 으로 표현합니다. 70 | - DB 테이블 이름, MLflow 의 구성요소 이름과 같이 시스템을 구성하는 요소의 이름도 `코드 블럭` 으로 표현합니다. 71 | - `코드 블럭` 은 ` 또는 <code>value</code> 태그로 단어나 문장을 감싸 표현합니다. 72 | - 단 colon(`:`)을 사용하는 경우 colon 을 기준으로 왼쪽은 *Italic* 오른쪽은 `코드 블럭` 을 사용합니다. 73 | - 영어 단어를 사용하는 경우, 일반 명사는 문장의 시작일 경우에만 대문자로 쓰고 나머지는 소문자로 작성합니다. 74 | - 기술 스택과 같은 영어 대명사의 경우, 모두 대문자로 시작하게 작성합니다. 75 | -------------------------------------------------------------------------------- /docs/api-serving/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "06. API Serving", 3 | "position": 7, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "API Serving" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/api-serving/img/api-serving-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/api-serving/img/api-serving-1.png -------------------------------------------------------------------------------- /docs/api-serving/img/api-serving-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/api-serving/img/api-serving-2.png -------------------------------------------------------------------------------- /docs/api-serving/img/api-serving-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/api-serving/img/api-serving-3.png -------------------------------------------------------------------------------- /docs/api-serving/img/api-serving-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/api-serving/img/api-serving-4.png -------------------------------------------------------------------------------- /docs/api-serving/img/api-serving-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/api-serving/img/api-serving-5.png -------------------------------------------------------------------------------- /docs/api-serving/model-api-on-docker-compose.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 API 서버를 Docker Compose 로 띄우기 위한 내용을 다룹니다. 4 | --- 5 | 6 | # 2) Model API on Docker Compose 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import APIServingImage5 from './img/api-serving-5.png'; 12 | 13 | 14 | 15 | ## Chapter Preview 16 | --- 17 | ### 목표 18 | 19 | 1. 앞서 작성한 API 를 실행할 수 있는 Dockerfile 을 작성합니다. 20 | 2. API 서버를 띄우기 위한 Docker Compose 파일을 작성합니다. 21 | 3. API 서버에 데이터를 전달하여 제대로 작동하는지 확인합니다. 22 | 23 | ### 스펙 명세서 24 | 25 | 1. 작성한 API 를 실행하는데 필요한 모델을 이미지에 복사하는 Dockerfile 을 작성합니다. 26 | - 이미지를 실행했을 때, 별도의 모델 정보를 필요로 하지 않습니다. 27 | - Base image 는 `amd64/python:3.9-slim` 을 사용합니다. 28 | - 포트는 기본 포트인 8000번 포트를 이용합니다. 29 | 2. Model API 서버를 띄우기 위한 Docker Compose 파일을 작성합니다. 30 | - Service name: api-with-model 31 | - Image: Dockerfile 32 | - Container name: api-with-model 33 | - Port: 8000:8000 34 | 3. Docker Compose 파일을 실행하여 API 를 작동시키고 데이터를 전달하여 예측 결과를 제대로 반환하는지 확인합니다. 35 | - Swagger UI 를 통해 확인합니다. 36 | - `curl` 을 통해 확인합니다. 37 | 38 | 39 | 40 | 41 | 42 | 해당 파트의 전체 코드는 [mlops-for-mle/part6/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part6) 에서 확인할 수 있습니다. 43 | 44 | ```js 45 | part6 46 | // highlight-next-line 47 | ├── Dockerfile 48 | ├── Makefile 49 | ├── README.md 50 | ├── app.py 51 | // highlight-next-line 52 | ├── docker-compose.yaml 53 | ├── download_model.py 54 | └── schemas.py 55 | ``` 56 | 57 | 58 | 59 |
60 | 61 | 62 | [그림 6-5] Model API Diagram 63 |
64 | 65 | ## 1. Dockerfile 작성 66 | 67 | Dockerfile 을 이용하여 앞서 작성한 Model API 를 작동시킬 수 있는 API 서버의 Docker 이미지를 만들어보겠습니다. 68 | 69 | ```docker title="Dockerfile" 70 | FROM amd64/python:3.9-slim 71 | 72 | WORKDIR /usr/app 73 | 74 | RUN pip install -U pip &&\ 75 | pip install mlflow==1.30.0 pandas scikit-learn "fastapi[all]" 76 | 77 | COPY schemas.py schemas.py 78 | COPY app.py app.py 79 | COPY sk_model/ sk_model/ 80 | 81 | CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--reload"] 82 | ``` 83 | 84 | - RUN : 85 | 86 | - `pip` 를 업데이트 한 후 필요한 패키지들을 설치합니다. 87 | - COPY : 88 | 89 | - API 를 작동시키는데 필요한 `.py` 파일들과 모델이 저장된 디렉토리 `sk_model` 을 컨테이너 내부로 복사합니다. 90 | - API 에서 사용할 모델 파일을 직접 넣어줌으로써 이미지를 실행했을 때에는 별도의 모델 정보를 필요로 하지 않게 됩니다. 91 | - CMD : 92 | 93 | - 컨테이너가 실행될 때 수행할 명령어의 기본값을 적어줍니다. 94 | - 여기서는 `uvicorn` 을 이용해 `app.py` 에서 만든 FastAPI 의 객체 `app` 을 실행합니다. 95 | 96 | ## 2. Docker Compose 97 | 98 | 이제 Model API 서비스를 띄우는 Docker Compose 파일을 작성하겠습니다. 99 | 100 | 101 | 102 | ```yaml title="docker-compose.yaml" 103 | version: "3" 104 | 105 | services: 106 | api-with-model: 107 | build: 108 | context: . 109 | dockerfile: Dockerfile 110 | container_name: api-with-model 111 | ports: 112 | - 8000:8000 113 | healthcheck: 114 | test: 115 | - CMD 116 | - curl -X POST http://localhost:8000/predict 117 | - -H 118 | - "Content-Type: application/json" 119 | - -d 120 | - '{"sepal_length": 6.7, "sepal_width": 3.3, "petal_length": 5.7, "petal_width": 2.1}' 121 | interval: 10s 122 | timeout: 5s 123 | retries: 5 124 | 125 | networks: 126 | default: 127 | name: mlops-network 128 | external: true 129 | ``` 130 | - healthcheck : 131 | 132 | - curl 을 이용하여 API 서버의 동작을 테스트합니다. 133 | - 정상 동작이 확인되면 서비스를 띄웁니다. 134 | 135 | - networks : 136 | 137 | - 서비스들을 연결할 Docker 네트워크를 01. Database 파트에서 생성한 `mlops-network` 로 사용합니다. 138 | - `external: true` 옵션은 `docker compose down -v` 로 이번 파트에서 생성되는 서비스를 종료하더라도 01. Database 파트에서 생성한 `mlops-network` 를 삭제하지 않을 수 있게 됩니다. 139 | 140 | 141 | 142 | 이제 완성된 Docker Compose 파일을 다음의 명령어를 통해 실행하여 Model API 서비스를 작동시킵니다. 143 | 144 | ```bash 145 | # terminal-command 146 | docker compose up -d 147 | ``` 148 | 149 | 컨테이너가 잘 실행되고 있는지 확인해보면 다음과 같이 `api-with-model` 이라는 이름의 컨테이너가 실행되고 있음을 확인할 수 있습니다. 150 | 151 | ```bash 152 | # terminal-command 153 | docker ps 154 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 155 | a88b1a6cff44 part6-api-with-model "uvicorn app:app --h…" 5 seconds ago Up 4 seconds 156 | ``` 157 | 158 | ## 3. API 서버 작동 확인 159 | 160 | ### 3.1 Swagger UI 이용 161 | 162 | 이제 API 서버가 잘 작동하는지 확인해 보겠습니다. API 서버 컨테이너를 실행할 때 포트 포워딩을 `8000:8000` 으로 했으므로 8000번 포트로 접속하면 API 서버로 접속할 수 있습니다. 163 | 164 | [`http://localhost:8000/docs`](http://localhost:8000/docs) 에 접속하여 Request Body 의 형태에 알맞게 데이터를 전달해주면 Response Body 로 inference 결과가 잘 반환되는 것을 확인할 수 있습니다. 165 | 166 | ### 3.2 `curl` 이용 167 | 168 | FastAPI 의 Swagger UI 를 이용하지 않고 다음과 같이 `curl` 을 이용하여 API 가 잘 작동하는지 확인하는 방법도 있습니다. 169 | 170 | ```bash 171 | # terminal-command 172 | curl -X POST http://localhost:8000/predict -H "Content-Type: application/json" -d '{"sepal_length": 6.7, "sepal_width": 3.3, "petal_length": 5.7, "petal_width": 2.1}' 173 | ``` 174 | 175 | 위의 명령어를 실행하면 다음과 같이 주어진 데이터에 대한 모델의 예측 결과 (`{"iris_class":2}`) 를 잘 반환해 주는 것을 확인할 수 있습니다. 176 | 177 | ```bash 178 | # terminal-command 179 | {"iris_class":2} 180 | ``` 181 | -------------------------------------------------------------------------------- /docs/api-serving/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of API Serving Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | 9 | 10 | :::caution 11 | 12 | 📌 해당 파트는 01. Database 파트의 DB 와 03. Model Registry 파트의 모델을 이용합니다. 13 | 📌 DB 를 띄우지 않은 경우 01. Database 파트를 완료하고 DB 가 띄워진 상태에서 진행해주세요. 14 | 📌 학습된 모델을 불러올 Model Registry 를 띄우지 않은 경우 03. Model Registry 파트를 완료한 상태에서 진행해주세요. 15 | 16 | ::: 17 | 18 | 이번 파트에서는 학습한 모델을 04. Model Deployment 파트에서 소개한 Request Driven 방식을 통해 사용하는 방법을 구현해보겠습니다. 19 | 05. FastAPI 파트에서 학습한 FastAPI 를 이용하여 데이터를 입력받아 모델의 예측값을 반환하는 REST API 를 구현합니다. 20 | 21 | 이번 파트를 통해 완성되는 workflow 를 그림으로 나타내면 [그림 6-1]과 같습니다. 22 | 23 |
24 | 25 | ![basic workflow](./img/api-serving-1.png) 26 | [그림 6-1] API Serving Workflow 27 |
28 | -------------------------------------------------------------------------------- /docs/database/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "01. Database", 3 | "position": 2, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Database" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/database/data-insertion-loop.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | description: 📌 생성된 테이블 안에 데이터를 계속해서 생성하는 스크립트를 작성합니다. 4 | --- 5 | 6 | # 4) Data Insertion Loop 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | 14 | ## Chapter Preview 15 | --- 16 | ### 목표 17 | 18 | 19 | 1. 생성된 테이블 안에 데이터를 계속해서 생성하는 스크립트를 작성합니다. 20 | 2. DB 에 데이터가 계속해서 삽입되고 있는지 확인합니다. 21 | 22 | ### 스펙 명세서 23 | 24 | 1. 3) Data Insertion 챕터에서 작성한 스크립트를 이용하여 계속해서 데이터를 생성하는 스크립트를 작성합니다. 25 | 2. 생성된 `iris_data` 테이블에 `psycopg2` 를 이용하여 스크립트를 실행해 계속해서 데이터를 삽입합니다. 26 | 3. `psql` 을 이용하여 삽입되고 있는 데이터를 확인합니다. 27 | 28 | 29 | 30 | 31 | 32 | 해당 파트의 전체 코드는 [mlops-for-mle/part1/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part1) 에서 확인할 수 있습니다. 33 | 34 | ```js 35 | part1 36 | ├── Dockerfile 37 | ├── Makefile 38 | ├── data_generator.py 39 | ├── data_insertion.py 40 | // highlight-next-line 41 | ├── data_insertion_loop.py 42 | ├── docker-compose.yaml 43 | └── table_creator.py 44 | ``` 45 | 46 | 47 | 48 | ## 1. 데이터 생성 49 | 50 | ### 1.1 Loop 추가 51 | 52 | 3) Data Insertion 챕터에서 작성한 data_insertion.py 스크립트를 참고하여 계속해서 데이터를 추가하는 data_insertion_loop.py 를 작성해보겠습니다. 53 | 여기서는 추가적으로 while 문을 사용하여 코드를 작성하겠습니다. while True 를 통해 외부의 개입이 없다면 계속해서 while 문을 실행할 수 있습니다. 54 | 55 | ```python 56 | def generate_data(db_connect, df): 57 | while True: 58 | insert_data(db_connect, df.sample(1).squeeze()) 59 | ``` 60 | 61 | 다만 위와 같이 작성할 경우 너무 빠른 시간에 데이터가 추가되기 때문에 DB 에 부하가 생길 수 있습니다. 부하를 방지하기 위해서는 데이터를 삽입 후 잠시 대기하는 시간을 추가하면 됩니다. 62 | Python 의 `time` 패키지의 `sleep` 함수를 이용하여 데이터를 삽입하고 나서 다음 데이터를 삽입하기 전에 1초동안 대기하도록 다음과 같이 코드를 작성합니다. 63 | 64 | ```python 65 | import time 66 | 67 | def generate_data(db_connect, df): 68 | while True: 69 | insert_data(db_connect, df.sample(1).squeeze()) 70 | time.sleep(1) 71 | ``` 72 | 73 | ### 1.2 Query 실행 74 | 75 | #### 1.2.1 `data_insertion_loop.py` 76 | 77 | 3) Data Insertion 챕터에서 작성한 내용들과 이번 챕터에서 설명한 내용을 모아서 data_insertion_loop.py 로 작성합니다. 78 | 79 | ```python title="data_insertion_loop.py" 80 | # data_insertion_loop.py 81 | import time 82 | 83 | import pandas as pd 84 | import psycopg2 85 | from sklearn.datasets import load_iris 86 | 87 | 88 | def get_data(): 89 | X, y = load_iris(return_X_y=True, as_frame=True) 90 | df = pd.concat([X, y], axis="columns") 91 | rename_rule = { 92 | "sepal length (cm)": "sepal_length", 93 | "sepal width (cm)": "sepal_width", 94 | "petal length (cm)": "petal_length", 95 | "petal width (cm)": "petal_width", 96 | } 97 | df = df.rename(columns=rename_rule) 98 | return df 99 | 100 | 101 | def insert_data(db_connect, data): 102 | insert_row_query = f""" 103 | INSERT INTO iris_data 104 | (timestamp, sepal_length, sepal_width, petal_length, petal_width, target) 105 | VALUES ( 106 | NOW(), 107 | {data.sepal_length}, 108 | {data.sepal_width}, 109 | {data.petal_length}, 110 | {data.petal_width}, 111 | {data.target} 112 | ); 113 | """ 114 | print(insert_row_query) 115 | with db_connect.cursor() as cur: 116 | cur.execute(insert_row_query) 117 | db_connect.commit() 118 | 119 | 120 | def generate_data(db_connect, df): 121 | while True: 122 | insert_data(db_connect, df.sample(1).squeeze()) 123 | time.sleep(1) 124 | 125 | 126 | if __name__ == "__main__": 127 | db_connect = psycopg2.connect( 128 | user="myuser", 129 | password="mypassword", 130 | host="localhost", 131 | port=5432, 132 | database="mydatabase", 133 | ) 134 | df = get_data() 135 | generate_data(db_connect, df) 136 | ``` 137 | 138 | #### 1.2.2 실행 139 | 140 | 위에서 작성한 스크립트를 실행하면, 다음과 같이 출력되는 것을 확인할 수 있습니다. 141 | 142 | ```bash 143 | # terminal-command 144 | python data_insertion_loop.py 145 | 146 | INSERT INTO iris_data 147 | (timestamp, sepal_length, sepal_width, petal_length, petal_width, target) 148 | VALUES ( 149 | NOW(), 150 | 6.5, 151 | 2.8, 152 | 4.6, 153 | 1.5, 154 | 1.0 155 | ); 156 | 157 | 158 | INSERT INTO iris_data 159 | (timestamp, sepal_length, sepal_width, petal_length, petal_width, target) 160 | VALUES ( 161 | NOW(), 162 | 5.5, 163 | 4.2, 164 | 1.4, 165 | 0.2, 166 | 0.0 167 | ); 168 | 169 | 170 | INSERT INTO iris_data 171 | (timestamp, sepal_length, sepal_width, petal_length, petal_width, target) 172 | VALUES ( 173 | NOW(), 174 | 4.4, 175 | 2.9, 176 | 1.4, 177 | 0.2, 178 | 0.0 179 | ); 180 | ``` 181 | 182 | ## 2. 데이터 확인 183 | 184 | `psql` 을 이용하여 DB 에 접속하고, 계속해서 데이터가 삽입되고 있는지 확인해보겠습니다. 185 | 186 | 1. `psql` 을 이용하여 DB 에 접속합니다. 187 | 188 | ```bash 189 | # terminal-command 190 | PGPASSWORD=mypassword psql -h localhost -p 5432 -U myuser -d mydatabase 191 | psql (14.3, server 14.0 (Debian 14.0-1.pgdg110+1)) 192 | Type "help" for help. 193 | 194 | mydatabase=# 195 | ``` 196 | 197 | 2. 3) Data Insertion 챕터에서 작성한 iris_data 테이블에 있는 데이터 전체를 확인하기 위한 query 를 실행합니다. 198 | 199 | ```bash 200 | # terminal-command 201 | mydatabase=# select * from iris_data; 202 | id | sepal_length | sepal_width | petal_length | petal_width | target 203 | ----+--------------+-------------+--------------+-------------+-------- 204 | 1 | 5.6 | 3 | 4.5 | 1.5 | 1 205 | 2 | 5.9 | 3 | 5.1 | 1.8 | 2 206 | 3 | 5.5 | 2.4 | 3.8 | 1.1 | 1 207 | 4 | 5.4 | 3.9 | 1.3 | 0.4 | 0 208 | (4 rows) 209 | ``` 210 | 211 | 계속해서 데이터가 추가되고 있는 것을 확인할 수 있습니다. 212 | -------------------------------------------------------------------------------- /docs/database/db-server-creation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 Docker 를 이용하여 DB 서버를 생성합니다. 4 | --- 5 | 6 | # 1) DB Server Creation 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | 13 | ## Chapter Preview 14 | --- 15 | ### 목표 16 | 17 | 1. Docker 를 이용하여 DB 서버를 생성합니다. 18 | 2. 생성된 DB 의 role name 과 attributes 를 확인합니다. 19 | 20 | ### 스펙 명세서 21 | 22 | 1. Docker 를 설치합니다. 23 | 2. PostgreSQL DB 서버를 생성합니다. 24 | - Image : postgres:14.0 25 | - Container name : postgres-server 26 | - POSTGRES_USER : myuser 27 | - POSTGRES_PASSWORD : mypassword 28 | - POSTGRES_DB : mydatabase 29 | - Port forwarding : 5432:5432 30 | 3. 생성된 DB 서버를 확인합니다. 31 | - `psql` 로 DB 에 접근하여 role name 과 attributes 확인 32 | 33 | 34 | 35 | 36 | 37 | 38 | 해당 파트의 전체 코드는 [mlops-for-mle/part1/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part1) 에서 확인할 수 있습니다. 39 | 40 | ```js 41 | part1 42 | ├── Dockerfile 43 | ├── Makefile 44 | ├── data_generator.py 45 | ├── data_insertion.py 46 | ├── data_insertion_loop.py 47 | ├── docker-compose.yaml 48 | └── table_creator.py 49 | ``` 50 | 51 | 52 | 53 | ## 1. Docker 설치 54 | ### 1.1 Docker Desktop 55 | - 아래의 링크를 통해 각 OS 에 맞는 Docker desktop 을 설치합니다. 56 | [Docker: Accelerated, Containerized Application Development](https://www.docker.com/) 57 | 58 | ### 1.2 Docker Engine 59 | - Ubuntu 에서 desktop 형태가 아닌 engine 형태로 설치하고 싶을 경우, 아래의 방법을 통해 설치합니다. 60 | [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/) 61 | 62 | ## 2. DB 서버 생성 63 | 64 | `docker run` 명령어를 이용하면 간단한 옵션들을 통해 DB 서버를 생성할 수 있습니다. 65 | 66 | 67 | 68 | ```bash 69 | # terminal-command 70 | docker run -d \ 71 | --name postgres-server \ 72 | -p 5432:5432 \ 73 | -e POSTGRES_USER=myuser \ 74 | -e POSTGRES_PASSWORD=mypassword \ 75 | -e POSTGRES_DB=mydatabase \ 76 | postgres:14.0 77 | ``` 78 | 79 | - -d : 80 | 81 | - 컨테이너가 detached 모드로 실행하게 되며, `-d` 옵션 없이 실행했다면 해당 터미널에서 `Ctrl + C` 를 눌러서 빠져나오는 순간 해당 컨테이너는 종료됩니다. 82 | - --name : 83 | 84 | - 컨테이너의 이름을 지정합니다. 85 | - -p : 86 | 87 | - 컨테이너에서 외부로 노출할 포트 포워딩 (port forwarding) 을 설정합니다. 88 | - 형식은 `host:container` 으로 사용이 되며, 여기서는 `5432:5432` 로 설정하겠습니다. 89 | - -e : 필요한 환경 변수를 설정합니다. 90 | 91 | - POSTGRES_USER : 유저의 이름을 설정합니다. 92 | - POSTGRES_PASSWORD : 유저의 비밀번호를 설정합니다. 93 | - POSTGRES_DB : DB 의 이름을 설정합니다. 94 | - postgres:14.0 : 95 | 96 | - 사용할 이미지를 지정합니다. 97 | 98 | 99 | 100 | `docker ps` 명령어를 통해 DB 서버가 잘 생성되었는지 확인합니다. 101 | 102 | ```bash 103 | # terminal-command 104 | docker ps 105 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 106 | 13bd38add3e7 postgres:14.0 "docker-entrypoint.s…" 40 seconds ago Up 39 seconds 0.0.0.0:5432->5432/tcp postres-server 107 | ``` 108 | 109 | ## 3. DB 서버 확인 110 | 111 | ### 3.1 `psql` 설치 112 | 113 | PostgreSQL DB 서버를 확인할 때 사용하는 CLI 툴인 `psql` 설치합니다. 114 | [공식 홈페이지](https://www.postgresql.org/download/)를 참고하여 본인의 환경에 맞게 설치합니다. 115 | 116 | ### 3.2 DB 서버 확인 117 | 118 | `psql` 을 통해 생성된 PostgreSQL DB 서버로 접속합니다. 119 | 120 | 121 | 122 | ```bash 123 | # terminal-command 124 | PGPASSWORD=mypassword psql -h localhost -p 5432 -U myuser -d mydatabase 125 | ``` 126 | - PGPASSWORD= : 127 | 128 | - 접속할 유저의 비밀번호를 입력합니다. 129 | - -h : 130 | 131 | - 호스트를 지정합니다. 132 | - -p : 133 | 134 | - 포트를 지정합니다. 135 | - -U : 136 | 137 | - 접속할 유저의 이름을 입력합니다. 138 | - -d : 139 | 140 | - DB 의 이름을 입력합니다. 141 | 142 | 143 | 144 | 접속에 성공하면 다음과 같이 출력됩니다. 145 | 146 | ```sql 147 | # terminal-command 148 | PGPASSWORD=mypassword psql -h localhost -p 5432 -U myuser -d mydatabase 149 | psql (14.3, server 14.0 (Debian 14.0-1.pgdg110+1)) 150 | Type "help" for help. 151 | 152 | mydatabase=# 153 | ``` 154 | 155 | `\du` 를 통해 DB 의 role name 과 attributes 을 확인합니다. 156 | 157 | ```sql 158 | mydatabase=# \du 159 | List of roles 160 | Role name | Attributes | Member of 161 | -----------+------------------------------------------------------------+----------- 162 | myuser | Superuser, Create role, Create DB, Replication, Bypass RLS | {} 163 | ``` 164 | -------------------------------------------------------------------------------- /docs/database/img/db-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/database/img/db-1.png -------------------------------------------------------------------------------- /docs/database/img/db-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/database/img/db-2.png -------------------------------------------------------------------------------- /docs/database/img/db-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/database/img/db-3.png -------------------------------------------------------------------------------- /docs/database/img/db-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/database/img/db-4.png -------------------------------------------------------------------------------- /docs/database/img/db-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/database/img/db-5.png -------------------------------------------------------------------------------- /docs/database/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Database Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import DBImage1 from './img/db-1.png'; 8 | 9 |
10 | 11 | 12 | 13 | [그림 1-1] DB Workflow 14 |
15 | 16 | 이번 파트에서는 Docker 를 이용하여 DB server 를 생성하고, `psycopg2` 패키지를 이용하여 테이블 생성 및 데이터 삽입을 진행합니다. 17 | 또한 Dockerfile 과 Docker Compose 파일을 만들어 Docker 컨테이너 안에서 계속해서 데이터를 생성하는 서비스를 구축해보겠습니다. 18 | -------------------------------------------------------------------------------- /docs/fastapi/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "05. FastAPI", 3 | "position": 6, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "FastAPI" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/fastapi/fasapi-crud-pydantic.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 앞서 작성한 API 에서 Create 부분을 Pydantic 을 이용하여 수정합니다. 4 | --- 5 | 6 | # 3) FastAPI CRUD (Pydantic) 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | 13 | ## Chapter Preview 14 | --- 15 | ### 목표 16 | 17 | 1. 앞서 작성한 API 에서 Create 부분을 Pydantic 을 이용하여 수정합니다. 18 | 2. Pydantic 을 사용하기 전과 후에 어떠한 차이가 있는지 학습합니다. 19 | 20 | 21 | ### 스펙 명세서 22 | 1. Create API 에서 입력으로 받아야 하는 값들을 `pydantic.BaseModel` 을 이용하여 수정합니다. [[Request Body](https://fastapi.tiangolo.com/tutorial/body/)] 23 | - `Class CreateIn(BaseModel)` 을 이용 24 | - `CreateIn` 에서는 이름과 별명을 입력받을 수 있도록 `name` 과 `nickname` 변수를 만듭니다. 25 | - `Class CreateOut(BaseModel)` 을 이용 26 | - `CreateOut` 에는 `status` 와 `id` 변수를 만들어 Create 의 operation function 에서 두 변수의 값을 return 하도록 합니다. 27 | - `id` 는 create 되는 시점의 memory 에 존재하는 데이터의 개수로 정의하여 작성합니다. 28 | 2. Create 후 return 하는 값을 Response Model 을 이용하여 수정합니다. [[Response Model](https://fastapi.tiangolo.com/tutorial/response-model/)] 29 | 3. Pydantic Model 을 사용하기 전과 후에 API 가 어떻게 달라지는지 비교해 봅니다. 30 | 31 | 32 | 33 | 34 | 35 | 해당 파트의 전체 코드는 [mlops-for-mle/part5/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part5) 에서 확인할 수 있습니다. 36 | 37 | ```js 38 | part5 39 | ├── Dockerfile 40 | ├── Makefile 41 | ├── crud_path.py 42 | // highlight-next-line 43 | ├── crud_pydantic.py 44 | ├── crud_query.py 45 | ├── main.py 46 | ├── multi_param.py 47 | ├── path_param.py 48 | └── query_param.py 49 | ``` 50 | 51 | 52 | 53 | ## 1. Pydantic Model 54 | 55 | Request Body 는 client 에서 API 로 전송하는 데이터를 의미합니다. 56 | 반대로 Response Body 는 API 가 client 로 전송하는 데이터를 의미합니다. 57 | 58 | 이렇게 client 와 API 사이에 데이터를 주고 받을 때 데이터의 형식을 지정해 줄 수 있는데, 이를 위해 Pydantic Model 을 사용할 수 있습니다. 59 | 60 | ### 1.1 Base Setting 61 | 62 | 먼저, 다음과 같이 `pydantic` 으로부터 `BaseModel` 을 import 합니다. 63 | 64 | ```python 65 | from fastapi import FastAPI, HTTPException 66 | from pydantic import BaseModel 67 | ``` 68 | 69 | 앞서 작성한 API 와 마찬가지로 FastAPI 인스턴스를 생성한 후 입력받은 데이터를 저장할 수 있도록 `USER_DB` 를 생성합니다. 70 | 또한, `HTTPException` 을 이용하여 에러를 발생할 수 있도록 합니다. 71 | 72 | ```python 73 | # Create a FastAPI Instance 74 | app = FastAPI() 75 | 76 | # User database 77 | USER_DB = {} 78 | 79 | # Fail response 80 | NAME_NOT_FOUND = HTTPException(status_code=400, detail="Name not found.") 81 | ``` 82 | 83 | ### 1.2 Define Input Schema 84 | 85 | 다음으로는 입력받아야 하는 데이터의 형태를 지정해줄 수 있도록 `CreateIn` 클래스를 작성합니다. 86 | `pydantic` 의 `BaseModel` 을 상속받은 `CreateIn` 클래스에 Request Body 의 구성 요소가 될 변수들을 attribute 로 지정합니다. 87 | 여기서는 이름과 별명을 입력받아야 하므로 다음과 같이 작성합니다. 88 | 89 | ```python 90 | class CreateIn(BaseModel): 91 | name: str 92 | nickname: str 93 | ``` 94 | 95 | ### 1.3 Define Output Schema 96 | 97 | 이번에는 반환하고자 하는 데이터의 형태를 지정해줄 수 있도록 `CreateOut` 클래스를 작성합니다. 98 | 마찬가지로 `pydantic` 의 `BaseModel` 을 상속받은 `CreateOut` 클래스에 Response Body 의 구성 요소가 될 변수들을 attribute 로 지정합니다. 99 | 스펙 명세서에 맞도록 `status` 와 `id` 변수를 지정해 줍니다. 100 | 101 | ```python 102 | class CreateOut(BaseModel): 103 | status: str 104 | id: int 105 | ``` 106 | 107 | ## 2. Response Model 108 | 109 | ### 2.1 Response Model 110 | 111 | `@app.get()`, `@app.post()` 등 다양한 Path Operation 에 `response_model` 을 이용하여 Response Body 에 사용될 데이터 모델을 지정해줄 수 있습니다. 112 | 또한, output data 의 type 을 체크하여 자동으로 변환시키고, type 이 유효한지 확인해주고, response 를 위해 자동으로 JSON Schema 를 추가해주는 등의 역할을 할 수 있습니다. 113 | 114 | 그 중에서도 `response_model` 의 가장 중요한 역할은 output data 의 형태를 제한해 줄 수 있다는 것입니다. 115 | 예를 들면, `response_model=CreateOut` 과 같이 지정해주면 해당 Path Operation 이 실행되었을 때 `CreateOut` 에 존재하는 attribute 의 형태로 데이터를 반환하게 됩니다. 116 | 이를 통해, Create API 에 입력하는 데이터로는 `CreateIn` 모델을, 반환하는 데이터로는 `CreateOut` 모델을 사용하도록 지정할 수 있습니다. 117 | 118 | ### 2.2 API Code 119 | 120 | 다음과 같이 Response Model 을 활용하여 Create API 를 수정할 수 있습니다. 121 | 122 | ```python 123 | @app.post("/users", response_model=CreateOut) 124 | def create_user(user: CreateIn) -> CreateOut: 125 | USER_DB[user.name] = user.nickname 126 | return CreateOut(status="success", id=len(USER_DB)) 127 | ``` 128 | 129 | 위의 Path Operation Function 을 보면 parameter 로 `user` 를 입력 받고, type 은 `CreateIn` 인 것을 알 수 있습니다. 130 | 131 | `USER_DB[user.name] = user.nickname` 와 같이 Pydantic Model 에 선언된 변수를 사용하여 DB 에 사용자 정보를 저장해 줍니다. 132 | 133 | Response Body 에 필요한 변수는 `response_model` 로 지정된 `CreateOut` 모델의 변수인 `status` 와 `id` 이기 때문에 이 변수들의 값을 저장해 주어야 합니다. 134 | `status` 와 `id` 값을 준 `CreateOut` 의 객체를 return 하면 됩니다. 135 | 136 | 정리하면, `create_user` 함수는 입력으로 `CreateIn` 모델을 받고, `CreateOut` 모델을 반환함으로써 request 할 때와 response 할 때 주고받는 데이터에 다른 변수를 사용할 수 있는 것입니다. 137 | 138 | ### 2.3 `crud_pydantic.py` 139 | 140 | 전체 코드를 작성한 `crud_pydantic.py` 는 다음과 같습니다. 141 | 142 | ```python title="crud_pydantic.py" 143 | # crud_pydantic.py 144 | from fastapi import FastAPI, HTTPException 145 | from pydantic import BaseModel 146 | 147 | 148 | class CreateIn(BaseModel): 149 | name: str 150 | nickname: str 151 | 152 | 153 | class CreateOut(BaseModel): 154 | status: str 155 | id: int 156 | 157 | # Create a FastAPI instance 158 | app = FastAPI() 159 | 160 | # User database 161 | USER_DB = {} 162 | 163 | # Fail response 164 | NAME_NOT_FOUND = HTTPException(status_code=400, detail="Name not found.") 165 | 166 | 167 | @app.post("/users", response_model=CreateOut) 168 | def create_user(user: CreateIn): 169 | USER_DB[user.name] = user.nickname 170 | user_dict = user.dict() 171 | user_dict["status"] = "success" 172 | user_dict["id"] = len(USER_DB) 173 | return user_dict 174 | 175 | 176 | @app.get("/users") 177 | def read_user(name: str): 178 | if name not in USER_DB: 179 | raise NAME_NOT_FOUND 180 | return {"nickname": USER_DB[name]} 181 | 182 | 183 | @app.put("/users") 184 | def update_user(name: str, nickname: str): 185 | if name not in USER_DB: 186 | raise NAME_NOT_FOUND 187 | USER_DB[name] = nickname 188 | return {"status": "success"} 189 | 190 | 191 | @app.delete("/users") 192 | def delete_user(name: str): 193 | if name not in USER_DB: 194 | raise NAME_NOT_FOUND 195 | del USER_DB[name] 196 | return {"status": "success"} 197 | ``` 198 | 199 | ### 2.4 실행 200 | 작성한 코드를 다음의 명령어를 통해 실행합니다. 201 | 202 | ```bash 203 | # terminal-command 204 | uvicorn crud_pydantic:app --reload 205 | ``` 206 | 207 | 이제 [`http://localhost:8000/docs`](http://localhost:8000/docs) 에 접속하면 다음과 같은 Swagger UI 화면을 볼 수 있습니다. 208 | 209 |
210 | 211 | ![crud_pydantic.py run screen](./img/fastapi-6.png) 212 | [그림 5-6] `crud_pydantic.py` 실행 화면 213 | 214 |
215 | 216 | [그림 5-6]의 화면에서 Pydantic Model 을 사용하여 수정한 POST Method 를 클릭하여 수정하기 전후를 비교해 봅시다. 217 | 218 |
219 | 220 | ![crud_pydantic.py run screen](./img/fastapi-7.png) 221 | [그림 5-7] Pydantic Model 로 수정하기 전 POST Method 222 | 223 |
224 | 225 | Pydantic Model 로 수정하기 전에는 [그림 5-7]과 같이 parameter 를 이용하여 데이터를 전달했습니다. 226 | 227 |
228 | 229 | ![crud_pydantic.py run screen](./img/fastapi-8.png) 230 | [그림 5-8] Pydantic Model 로 수정한 후 POST Method 231 | 232 |
233 | 234 | 반면, Pydantic Model 로 수정한 후에는 [그림 5-8]과 같이 Request Body 를 통해 데이터를 전달하는 것을 확인할 수 있습니다. 235 | 236 | ## 3. Pydantic Model 사용 전후 비교 237 | 238 | 위와 같이 Pydantic Model 을 사용한 클래스를 Response Model 로 지정하여 Create API 를 수정하였습니다. 239 | 이처럼 Pydantic Model 을 통해 Response Model 을 사용하면 입력 받는 파라미터와 생성 후 반환하는 파라미터를 다르게 지정해 줄 수 있습니다. 240 | 이러한 기능은 비밀번호처럼 사용자가 필수적으로 입력해야 하지만 반환 값에는 나타나면 안 되는 파라미터를 지정할 때 유용하게 사용될 수 있습니다. 241 | -------------------------------------------------------------------------------- /docs/fastapi/fastapi-on-docker.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | description: 📌 앞서 작성한 API 를 Docker 를 이용하여 실행합니다. 4 | --- 5 | 6 | # 4) FastAPI on Docker 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | 13 | ## Chapter Preview 14 | --- 15 | ### 목표 16 | 17 | 1. 앞서 작성한 API 를 Docker 를 이용하여 실행합니다. 18 | 19 | ### 스펙 명세서 20 | 21 | 1. 앞서 Pydantic 을 이용하여 수정한 API 를 서버로 실행하기 위해 Dockerfile 을 작성합니다. 22 | - Base image는 `amd64/python:3.9-slim` 을 사용합니다. 23 | - `crud_pydantic.py` 를 이용합니다. 24 | - 포트는 기본 포트인 8000번 포트를 이용합니다. 25 | 2. [`http://localhost:8000/docs`](http://localhost:8000/docs) 에 접속하여 앞서 수행한 시나리오가 제대로 작동하는지 확인합니다. 26 | 27 | 28 | 29 | 30 | 31 | 해당 파트의 전체 코드는 [mlops-for-mle/part5/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part5) 에서 확인할 수 있습니다. 32 | 33 | ```js 34 | part5 35 | // highlight-next-line 36 | ├── Dockerfile 37 | ├── Makefile 38 | ├── crud_path.py 39 | ├── crud_pydantic.py 40 | ├── crud_query.py 41 | ├── main.py 42 | ├── multi_param.py 43 | ├── path_param.py 44 | └── query_param.py 45 | ``` 46 | 47 | 48 | 49 | ## 1. Dockerfile 작성 50 | 51 | ### 1.1 Dockerfile 52 | 53 | Dockerfile 을 이용하여 앞서 Pydantic 을 이용하여 수정한 API 를 작동시킬 수 있는 API 서버의 Docker 이미지를 만들어보겠습니다. 54 | 55 | 56 | 57 | ```docker title="Dockerfile" 58 | FROM amd64/python:3.9-slim 59 | 60 | WORKDIR /usr/app 61 | 62 | RUN pip install -U pip \ 63 | && pip install "fastapi[all]" 64 | 65 | COPY crud_pydantic.py crud_pydantic.py 66 | 67 | CMD ["uvicorn", "crud_pydantic:app", "--host", "0.0.0.0", "--reload"] 68 | ``` 69 | 70 | - RUN : 71 | 72 | - `pip` 를 먼저 업데이트한 후에 `fastapi[all]` 을 설치합니다. 73 | - COPY : 74 | 75 | - Pydantic 을 이용하여 수정한 API 의 코드가 담겨 있는 `crud_paydantic.py` 를 컨테이너 내부로 복사합니다. 76 | - CMD : 77 | 78 | - 컨테이너가 실행될 때 수행할 명령어의 기본값을 적어줍니다. 79 | - 여기서는 `uvicorn` 을 이용해 `crud_pydantic.py` 에서 만든 FastAPI 의 객체 `app` 을 실행해 줍니다. 80 | 81 | 82 | 83 | ### 1.2 Build 84 | 85 | 작성한 Dockerfile 을 이용해 이미지를 build 합니다. 86 | 87 | 이미지 이름은 `part5-api-server` 로 하겠습니다. 88 | 89 | ```bash 90 | # terminal-command 91 | docker build -t part5-api-server . 92 | ``` 93 | 94 | 이미지가 잘 생성되었는지 확인합니다. 95 | 96 | ```bash 97 | # terminal-command 98 | docker image ls 99 | ``` 100 | 101 | 다음과 같이 `part5-api-server` 이미지가 잘 생성되었음을 확인할 수 있습니다. 102 | 103 | ```bash 104 | # terminal-command 105 | docker image ls 106 | REPOSITORY TAG IMAGE ID CREATED SIZE 107 | part5-api-server latest 3dec4bf727fe 3 hours ago 249MB 108 | ``` 109 | 110 | ### 1.3 Run 111 | 112 | 이제 build 한 이미지를 실행해 보겠습니다. 113 | 114 | 115 | 116 | ```bash 117 | # terminal-command 118 | docker run -d \ 119 | --name api-server \ 120 | -p 8000:8000 \ 121 | part5-api-server 122 | ``` 123 | 124 | - --name : 125 | 126 | - 컨테이너의 이름을 api-server 로 설정합니다. 127 | - -p : 128 | 129 | - 포트 포워딩을 8000:8000 으로 설정합니다. 130 | 131 | 132 | 133 | 이제 컨테이너가 잘 실행되고 있는지 확인합니다. 134 | 135 | ```bash 136 | # terminal-command 137 | docker ps 138 | ``` 139 | 140 | 위의 명령어를 실행해보면 `api-server` 라는 이름을 가진 컨테이너가 실행되고 있음을 확인할 수 있습니다. 141 | 142 | ```bash 143 | # terminal-command 144 | docker ps 145 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 146 | fb72ccf8fb47 part5-api-server "uvicorn crud_pydant…" 13 minutes ago Up 13 minutes 0.0.0.0:8000->8000/tcp api-server 147 | ``` 148 | 149 | ## 2. API 서버 접속하여 작동 확인 150 | 151 | ### 2.1 작동 확인 152 | 이제 FastAPI 를 통해 만든 API 서버가 잘 작동하는지 확인해 보겠습니다. 153 | API 서버 컨테이너를 실행할 때 포트 포워딩을 `8000:8000` 으로 했으므로 8000번 포트로 접속하면 API 서버로 접속할 수 있습니다. 154 | 155 | [`http://localhost:8000/docs`](http://localhost:8000/docs) 에 접속하면 다음과 같이 접속이 되는 것을 확인할 수 있습니다. 156 | 157 |
158 | 159 | ![API's Swagger UI Screen](./img/fastapi-9.png) 160 | [그림 5-9] 작성한 API의 Swagger UI 화면 161 | 162 |
163 | 164 | [그림 5-6]의 화면에서 앞서 수행한 시나리오와 같은 다양한 작업을 해 보면, 만든 API 가 제대로 작동하는 것을 확인할 수 있습니다. 165 | 166 | ### 2.2 컨테이너 종료 167 | 168 | 작동이 잘 되는 것을 확인한 후에는 다음 실습을 위해 컨테이너를 종료해 줍니다. 다음의 명령어를 통해 종료할 수 있습니다. 169 | 170 | ```bash 171 | # terminal-command 172 | docker rm --force api-server 173 | ``` 174 | -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-1.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-2.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-3.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-4.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-5.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-6.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-7.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-8.png -------------------------------------------------------------------------------- /docs/fastapi/img/fastapi-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/fastapi/img/fastapi-9.png -------------------------------------------------------------------------------- /docs/fastapi/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of FastAPI Chapter 4 | --- 5 | 6 | # 0) Overview 7 | 이번 파트에서는 모델을 서빙하기에 앞서 API 의 개념에 대해 학습합니다. 8 | 실습을 위해서는 Python 을 이용해서 API 를 만들 수 있는 웹 프레임워크인 FastAPI 를 사용합니다. 9 | 10 | 이번 파트에서 구현할 workflow 는 다음과 같습니다. 11 | 12 |
13 | 14 | ![FastAPI workflow](./img/fastapi-1.png) 15 | [그림 5-1] FastAPI Workflow 16 | 17 |
18 | 19 | Docker 를 이용하여 FastAPI 로 만든 API 서버를 실행하고 client 가 서버에 request 를 보냅니다. 20 | Request 를 받은 API 서버는 다시 client 에게 response 를 주게 됩니다. 21 | -------------------------------------------------------------------------------- /docs/img/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/img/architecture.png -------------------------------------------------------------------------------- /docs/img/google-trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/img/google-trend.png -------------------------------------------------------------------------------- /docs/img/mlops-level-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/img/mlops-level-0.png -------------------------------------------------------------------------------- /docs/img/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/img/pipeline.png -------------------------------------------------------------------------------- /docs/img/rest-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/img/rest-api.png -------------------------------------------------------------------------------- /docs/intro.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 00. Introduction 6 | import CodeDescription from '@site/src/components/CodeDescription'; 7 | import PreviewDescription from '@site/src/components/PreviewDescription'; 8 | import BrowserWindow from '@site/src/components/BrowserWindow'; 9 | 10 | ## Introduction 11 | 12 | 2022년 MLOps 에 대한 관심은 폭발적으로 증가했습니다. [그림 0-1] 은 “MLOps” 키워드에 대한 구글 트랜드 그래프입니다. 2022년을 기점으로 검색량이 폭발적으로 증가한 것을 확인할 수 있습니다. 13 | 14 |
15 | 16 | ![Google Trend](./img/google-trend.png) 17 | [그림 0-1] MLOps Google Trend 18 |
19 | 20 | 21 | 이런 관심의 집중에 따라 MLOps에 관한 많은 포스팅 글들을 찾아볼 수 있습니다. 하지만 대부분은 MLOps 의 개념에 관해서만 다루고 있습니다. 22 | 또한, MLOps는 그 자체로 제품 혹은 플랫폼이 될 정도로 방대한 범위를 다루고 있습니다. 대표적인 클라우드 회사에서는 SageMaker (AWS), VertexAI (Google Cloud) 과 같이 MLOps 제품을 출시했습니다. 23 | 24 | 그런데 정작 이를 사용해야 하는 머신러닝 엔지니어 입장에서는 “그래서 어떻게 MLOps 를 할 수 있는 건데?” 라는 의문이 들 수 밖에 없습니다. 25 | 이러한 의문을 조금이라도 풀 수 있도록 “머신러닝 엔지니어를 위한 MLOps”를 집필하였습니다. 26 | 27 | ## 다루는 내용 28 | 29 | ### MLOps level: 0 30 | 31 | [그림 0-2]는 MLOps 를 설명할 때 많이 쓰이는 구글 클라우드에서 제시한 MLOps 의 0단계 입니다. MLOps 의 목표는 0단계를 자동화시키는 것과 모델 개발 환경과 모델 운영 환경을 일치시키는 것에 있습니다. 32 | 33 |
34 | 35 | ![MLOps Level 0](./img/mlops-level-0.png) 36 | [그림 0-2] MLOps Level 0 37 |
38 | 39 | “머신러닝 엔지니어를 위한 MLOps” 에서는 직접 구현해보며 각 컴포넌트들이 어떤 역할을 하는지 컴포넌트끼리는 어떻게 연결해야 하는지 설명하고자 합니다. 여기서 다루는 내용을 간단히 도식화 하면 [그림 0-3]과 같이 표시할 수 있습니다. 40 | 41 |
42 | 43 | ![Pipeline](./img/pipeline.png) 44 | [그림 0-3] Pipeline 45 |
46 | 47 | ### Chapter 48 | 49 | [그림 0-3] 의 파이프라인을 구현할 기술 스택과 관계도는 [그림 0-4]와 같습니다. 50 | 51 |
52 | 53 | ![Pipeline](./img/architecture.png) 54 | [그림 0-4] Architecture 55 |
56 | 57 | 각 컴포넌트를 구현하는데 사용하는 패키지 및 소프트웨어는 다음의 기준으로 선정하였습니다. 58 | 59 | 1. 오픈소스 60 | 2. 공식 Documentation 의 관리 여부 61 | 62 | 대표적으로 사용하는 패키지는 FastAPI, MLflow, Kafka 등이 있습니다. 63 | 단순히 따라해보는 것에 그치지 않고 본인의 업무에 필요한 방향으로 적용해 볼 수 있도록 간단한 튜토리얼을 작성하고 MLOps 에 맞게 변형하는 과정으로 진행됩니다. 64 | 65 | ### Docker 66 | 67 | “머신러닝 엔지니어를 위한 MLOps” 는 모든 컴포넌트들을 Docker 로 실행됩니다. 68 | 69 | 머신러닝의 성능 재현은 머신러닝 모델을 다룰 때 가장 중요한 부분 중 하나입니다. 70 | 이를 위해서는 OS, 파이썬 버전, 패키지 버전, 코드, 가중치 등이 모델을 학습했을 때의 환경과 동일해야 합니다. 71 | 이런 동일한 환경을 제공하기 위해서 Containerization 은 머신러닝에서 중요한 기술 중 하나이며 이를 대표하는 소프트웨어가 바로 Docker 입니다. 72 | 이러한 배경으로 머신러닝 엔지니어는 Docker 를 이해하고 다룰 수 있어야 합니다. 머신러닝 엔지니어가 Docker 를 다루고 이해할 수 있도록 본 문서에서는 로컬 환경에서 실행되는 스크립트를 작성한 후 이를 Docker 환경에서 실행하는 순서로 진행됩니다. 73 | 74 | ## 이 문서를 학습하는 방법 75 | 76 | ### Architecture 77 | 78 | 본 문서에 있는 다음과 같은 구조로 작성되어 있습니다. 79 | 80 | 1. 각 챕터에서 학습해야 할 목표 81 | 2. 목표를 구현하기 위한 스펙 명세서 82 | 3. 각 챕터의 전체 코드를 확인할 수 있는 경로 83 | 4. 스펙 명세서를 작성하기 위한 코드와 그에 대한 해설 84 | 85 | 예를 들어 다음에 학습할 챕터는 아래와 같이 작성되어 있습니다. 86 | 87 | 88 | 89 | 90 | 91 | ### Chapter Preview 92 | --- 93 | #### 목표 94 | 95 | 1. Docker 를 이용하여 DB 서버를 생성합니다. 96 | 2. 생성된 DB 의 role name 과 attributes 를 확인합니다. 97 | 98 | #### 스펙 명세서 99 | 100 | 1. Docker 를 설치합니다. 101 | 2. PostgreSQL DB 서버를 생성합니다. 102 | - Image : postgres:14.0 103 | - Container name : postgres-server 104 | - POSTGRES_USER : myuser 105 | - POSTGRES_PASSWORD : mypassword 106 | - POSTGRES_DB : mydatabase 107 | - Port forwarding : 5432:5432 108 | 3. 생성된 DB 서버를 확인합니다. 109 | - `psql` 로 DB 에 접근하여 role name 과 attributes 확인 110 | 111 | 112 | 113 | 114 | 115 | 해당 파트의 전체 코드는 [mlops-for-mle/part1/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part1) 에서 확인할 수 있습니다. 116 | 117 | ```js 118 | part1 119 | ├── Dockerfile 120 | ├── Makefile 121 | ├── data_generator.py 122 | ├── data_insertion.py 123 | ├── data_insertion_loop.py 124 | ├── docker-compose.yaml 125 | └── table_creator.py 126 | ``` 127 | 128 | 129 | 130 | 131 | 132 | 좀 더 효율적인 학습을 위해서는 해설을 먼저 보기 보다는 스펙 명세서를 직접 구현한 뒤 설명하는 내용들을 읽는 것을 권장합니다. 133 | -------------------------------------------------------------------------------- /docs/kafka/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "07. Kafka", 3 | "position": 8, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Kafka" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/kafka/connect-connector.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 Kafka 의 Connect 와 Connector 에 대해 알아봅니다. 4 | --- 5 | 6 | # 3) Connect & Connector 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import KafkaImage7 from './img/kafka-7.png'; 12 | import KafkaImage8 from './img/kafka-8.png'; 13 | 14 | 15 | 16 | ## Chapter Preview 17 | --- 18 | ### 목표 19 | 20 | 1. Kafka 의 Connect 와 Connector 에 대해 알아봅니다. 21 | 22 | 23 | 24 | 25 | 26 | 27 | 해당 파트의 전체 코드는 [mlops-for-mle/part7/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part7) 에서 확인할 수 있습니다. 28 | 29 | ```js 30 | part7 31 | ├── Makefile 32 | ├── README.md 33 | ├── connect.Dockerfile 34 | ├── create_table.py 35 | ├── kafka-docker-compose.yaml 36 | ├── naive-docker-compose.yaml 37 | ├── sink_connector.json 38 | ├── source_connector.json 39 | ├── target-docker-compose.yaml 40 | └── target.Dockerfile 41 | ``` 42 | 43 | 44 | 45 | ## 1. Connect & Connector 46 | 47 | ### 1.1 Producer & Consumer 의 한계 48 | 49 | Kafka 는 2) Producer & Consumer 챕터처럼 Producer 와 Consumer client 를 통해 메시지 파이프라인을 쉽게 구성할 수 있었습니다. 50 | 51 | 하지만 실제 시스템에서는 어떨까요? 아래의 예제를 살펴보겠습니다. 52 | [그림 7-5] 처럼 어떠한 DB server 1에서 DB server 2로 데이터를 전달하는 시스템을 가정해보겠습니다. 53 | 54 |
55 | 56 | ![Single Kafka System](./img/kafka-5.png) 57 | [그림7-5] Single Kafka System with Producer & Consumer 58 | 59 |
60 | 61 | DB server 1로부터 데이터를 가져오는 Producer 가 있고, 데이터를 브로커의 어떤 토픽으로 보낸 뒤, Consumer 가 DB server 2에 데이터를 전달하는 과정입니다. 62 | 63 | 그렇다면 이렇게 전달할 DB 들이 100개, 1000개, 10000개가 있다면 어떨까요? 아마도 아래의 과정처럼 Producer 와 Consumer 를 100개, 1000개, 10000개로 만들어야 할 것입니다. 64 | 65 |
66 | 67 | ![Multiple Kafka System](./img/kafka-6.png) 68 | [그림7-6] Multiple Kafka System with Producer & Consumer 69 | 70 |
71 | 72 | 하지만 메시지 파이프라인 구성을 위해 매번 Producer 와 Consumer 를 개발하는 것은 쉽지 않습니다. 73 | 특히, 비슷한 데이터 시스템이 많아지면 많아질수록 Producer 와 Consumer 를 개발하는 데에는 비용도 계속 들고 반복 작업이 많아질 수 있습니다. 74 | 75 | 따라서, 더 간편하고 효율적으로 메시지 파이프라인을 구축하는 방법으로 Kafka 에서는 Connect 와 Connector 라는 것이 탄생하게 되었습니다. 76 | 77 | ### 1.2 Connect & Connector 소개 78 | 79 | Connect 는 데이터 시스템과 Kafka 간의 데이터를 확장 가능하고, 안전한 방법으로 streaming 하기 위한 도구입니다. 80 | Connect 를 사용하기 위해서는 데이터를 어디로부터 가져오는지, 어디에다가 전달해야 하는지를 알려주는 Connector 를 정의해야 합니다. 81 | 여기서 Connector 란 메시지 파이프라인에 대한 추상 객체이며, task 들을 관리합니다. 82 | 83 | Connect 와 Connector 의 역할을 살펴보면, Connect 는 프레임워크이고 Connector 는 그 안에서 돌아가는 플러그인입니다. 84 | 따라서 Connect 프레임워크를 실행하고 특정 Connector 플러그인을 실행시키면 메시지 파이프라인을 쉽게 구축할 수 있습니다. 85 | 이렇게 구축된 Connect 와 Connector 를 실행함으로써 개발 비용을 줄이고 반복 작업도 줄일 수 있게 됩니다. 86 | 87 | Connector 에는 아래와 같은 두 가지 종류의 Connector 가 존재합니다. 88 | 89 | #### Source Connector : 90 | 91 | - Source system 의 데이터를 브로커의 토픽으로 publish 하는 Connector 입니다. 92 | - 즉, Producer 의 역할을 하는 Connector 입니다. 93 | 94 | #### Sink Connector : 95 | - 브로커의 토픽에 있는 데이터를 subscribe 해서 target system 에 전달하는 Connector 입니다. 96 | - 즉, Consumer 의 역할을 하는 Connector 입니다. 97 | 98 | 각각의 Connector 에 관한 설정 명세를 Connect 에 전달하면, 구성된 Connector 는 주기적으로 메시지를 확인하고 새로운 메시지가 있으면 파이프라인을 통해 흘려보냅니다. 99 | 100 | 앞서 예제로 다뤘던 [그림7-5] 에 대해서 DB server 1에서 DB server 2로 데이터를 전달하는 시스템을 다시 살펴보면 [그림 7-7]과 같은 흐름으로 생각할 수 있습니다. 101 | 102 |
103 | 104 | 105 | 106 | [그림7-7] Single Kafka System with Connect & Connector 107 | 108 |
109 | 110 | DB 들이 100개, 1000개, 10000개로 늘어난다면 어떻게 될까요? 111 | 아마도 [그림 7-8]처럼 Source Connector 와 Sink Connector 를 100개, 1000개, 10000개로 만들어야 할 것입니다. 112 | 113 | 114 |
115 | 116 | 117 | 118 | [그림7-8] Multiple Kafka System with Connect & Connector 119 | 120 |
121 | 122 | 그렇다면 앞서 다뤘던 Producer 와 Consumer 를 만드는 것보다 Source Connector 와 Sink Connector 를 만드는 것의 장점이 무엇일까요? 123 | 124 | 바로 Connector 에 대한 설정파일만 있으면 개발 비용 없이 간단하게 띄울 수 있다는 것입니다. 125 | Source Connector 의 경우, Connector 의 유형, 연결할 URL, user 와 password, 테이블 이름, 토픽의 파티션 수, Replication Factor 수 등을 설정해주면 Connect 에서 인스턴스로 생성할 수 있습니다. 126 | 이렇게 생성된 Connector 들이 100개, 1000개, 10000개의 Producer 를 개발하는 것보다는 훨씬 비용이 적고 간편합니다. 127 | 128 | ### 1.3 Schema Registry 소개 129 | 130 | 마지막으로 Connect 와 함께 쓰이는 Schema Registry 에 대해 알아보겠습니다. 131 | 앞서 1) Kafka Introduction 챕터에서 알아본 것과 같이 Kafka 는 decoupling 이라는 특징을 가지고 있습니다. 132 | Producer 와 Consumer 가 존재하고, 서로 의존적이지 않고 완벽하게 분리되어 있습니다. 133 | 또한 브로커는 메시지를 한 번 저장하면 이후에는 수정할 수 없습니다. 134 | 135 | 이처럼 Kafka 의 구조적인 특징과 내부 구조로 인해 Kafka 운영에서는 [그림 7-9]와 같은 상황이 발생할 수 있습니다. 136 | 137 |
138 | 139 | ![Consume Fail](./img/kafka-9.png) 140 | [그림7-9] Consume Fail (출처: https://always-kimkim.tistory.com/entry/kafka101-schema-registry) 141 | 142 |
143 | 144 | [그림 7-9] 상황은 다음과 같습니다. 145 | 1. Producer 1과 2는 각자 브로커의 토픽 A 에 메시지를 보냅니다. 146 | 2. Consumer 는 토픽 A 에 있는 메시지를 읽습니다. 147 | 3. 이때, Producer 2가 schema 를 변경하여 메시지 (4번)를 발행합니다. 148 | 4. 하지만 Consumer 는 이 상황을 알지 못하기 때문에, 4번 메시지를 구독하여 처리하는 과정에서 메시지를 읽어들이지 못하고 장애가 발생합니다. 149 | 150 | 위와 같은 상황처럼 결국 구조적인 결합도는 낮췄지만 내부적인 결합도 문제는 여전히 가지고 있게 됩니다. 151 | 152 | 이러한 문제에 더하여 동일한 schema 의 메시지가 계속 들어오는 경우, 같은 schema 를 계속해서 저장해야하기 때문에 메시지의 크기가 커지며, schema 가 중복이 되어 불필요한 데이터 용량을 차지하게 됩니다. 153 | 154 | 이러한 구조적인 결합도를 낮추고 불필요한 데이터 용량을 줄이기 위해 Kafka 에서는 Schema Registry 를 사용합니다. 155 | Schema Registry 란 메시지의 Schema 를 저장해주는 일종의 저장소입니다. 156 | 157 | 다음은 Kafka Connector 가 만들어 내는 메시지 구조입니다. 158 | 159 |
160 | 161 | ![Connector](./img/kafka-10.png) 162 | [그림7-10] 메시지 구조 (출처: https://scorpio-mercury.tistory.com/30) 163 | 164 |
165 | 166 | 메시지는 key 와 value 로 구성되어 있으며, 각 key 와 value 는 schema 와 payload 로 구성되어 있습니다. 167 | 여기서 key 는 PK 와 같이 데이터를 식별할 수 있는 정보가 들어있고, value 는 데이터의 전체 값이 들어있습니다. 168 | payload 는 데이터 값이 저장되며, schema 에는 이 데이터 값의 데이터 타입이 명시되어 있습니다. 169 | 170 | [그림 7-11]은 Producer, Schema Registry, Kafka 간의 관계를 나타냅니다. 171 | 172 |
173 | 174 | ![Connector](./img/kafka-11.png) 175 | [그림7-11] Schema Registry Architecture (출처: https://scorpio-mercury.tistory.com/30) 176 | 177 |
178 | 179 | [그림 7-11] 에서 각 컴포넌트가 작동하는 순서는 다음과 같습니다. 180 | 1. Producer 에서 Kafka 의 Serializer (또는 Converter) 에게 메시지를 보냅니다. 181 | 2. Serializer 는 메시지를 받아 메시지의 schema 를 Schema Registry 에 보냅니다. 182 | 3. 이어서 schema ID 를 받고, schema ID 와 데이터를 Kafka 에게 보냅니다. 183 | 184 | :::info 185 | 186 | Connect 와 Connector 를 이용할 때는 Serializer 를 직접 구현할 필요없이 Connect 를 띄울 때 환경 변수로 적어주면 됩니다. 187 | 188 | ::: 189 | 190 | 191 | 앞서 살펴봤던 schema 중복 문제는 Schema Registry 에 key 와 value 에 명시된 schema 를 따로 저장하기 때문에 Connector 가 schema 대신 Schema Registry 의 schema ID 를 명시하여 해결할 수 있게 됩니다. 192 | Schema ID 를 쓰면 메세지의 크기가 줄어들어 불필요한 데이터의 용량도 줄일 수 있습니다. 193 | 194 | 또한 앞서 발생했던 내부적인 결합도 문제는 Schema Registry 에서 제공하는 기능 중 하나인 schema 호환성 규칙 강제 기능으로 해결할 수 있습니다. 195 | Schema 호환성 규칙 강제란 schema 를 등록하여 사용할 수 있지만, schema 버전 간의 호환성을 강제함으로써 일종의 규칙을 세우는 것입니다. 196 | 197 |
198 | 199 | ![Forward](./img/kafka-12.png) 200 | [그림7-12] Forward 호환성 (출처: https://always-kimkim.tistory.com/entry/kafka101-schema-registry) 201 | 202 |
203 | 204 | [그림 7-12]은 여러 호환성 중 Forward 라는 호환성을 갖는 경우에 대한 예시입니다. 205 | 206 | 1. Consumer 는 version 1로 메시지를 처리하고 있습니다. 207 | 2. 그리고 Gender 라는 column 이 version 2에서 추가되었고, Consumer 는 version 2 의 schema 를 메시지를 구독하여 처리합니다. 208 | 3. 이때, Consumer 는 새로 추가된 column 을 제외하고, 기존 version 1에 맞춰 메시지를 처리합니다. 209 | 210 | 이렇게 schema 의 호환성 규칙을 강제하여 schema 가 다른 메시지도 읽을 수 있도록 만듭니다. 211 | -------------------------------------------------------------------------------- /docs/kafka/img/kafka-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-1.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-10.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-11.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-12.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-13.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-14.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-15.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-2.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-3.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-4.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-5.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-6.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-7.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-8.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-9.png -------------------------------------------------------------------------------- /docs/kafka/img/kafka-gif-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/kafka/img/kafka-gif-1.gif -------------------------------------------------------------------------------- /docs/kafka/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Kafka Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | 9 | 04. Model Deployment 파트에서 설명한 Stream Serving 을 구현하기 위해서는 우선 실시간으로 데이터를 전달할 수 있는 데이터 파이프라인을 구축해야 합니다. 10 | 이번 파트에서는 Kafka 를 이용하여 데이터 파이프라인을 구축해보겠습니다. 11 | 12 | 이번 파트를 통해 완성되는 workflow 를 그림으로 나타내면 [그림 7-1]과 같습니다. 13 | 14 |
15 | 16 | ![FastAPI workflow](./img/kafka-1.png) 17 | [그림 7-1] Kafka Workflow 18 | 19 |
20 | 21 | 실습에 앞서 다음과 같은 가정을 합니다. 22 | 23 | 1. Source DB: 데이터가 계속해서 쌓이고 있는 외부 DB 24 | 2. Target DB: 외부에서 가져온 데이터를 처리한 뒤 쌓이는 내부 DB 25 | 26 | 여기서 Source DB 로 사용하는 DB 서버는 01. Database 파트에서 작성한 PostgreSQL DB 서버를 사용합니다. 27 | 이번 파트에서는 Kafka 를 이용하여 Source DB 서버에 있는 데이터를 Target DB 로 전달하는 시스템을 구축해보겠습니다. 28 | -------------------------------------------------------------------------------- /docs/model-deployment.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | # 04. Model Deployment 5 | import { Chapter, Part } from '@site/src/components/Highlight'; 6 | 7 | ## Request Driven - API Serving 8 | 9 | 학습이 완료된 모델을 다른 사람이 사용할 수 있도록 하려면 어떻게 해야 할까요? 10 | 예를 들어서 개와 고양이를 분류할 수 있는 모델을 학습하고, 누군가 이 모델을 통해 개와 고양이를 분류하고 싶어하는 상황을 가정해봅시다. 11 | 12 | 단순하게 생각했을 때 저장된 모델과 추론에 사용된 코드를 사용자에게 전달하면, 사용자는 전달받은 모델과 코드를 이용해 개와 고양이를 분류할 수 있을 것입니다. 13 | 그런데 만약 추론하고자 하는 데이터가 핸드폰에서 촬영한 사진이고, 이를 핸드폰에서 바로 분류하고 싶다면 전달받은 것만으로는 사용하기 힘들 수 있습니다. 14 | 왜냐하면 전달받은 모델이 너무 커서 핸드폰에서 불러올 수 없을 가능성이 있기 때문입니다. 15 | 또한, 핸드폰에 설치되어 있는 패키지의 버전이 달라 다르게 작동할 가능성이 있습니다. 16 | 이처럼 디바이스의 환경에 따라 모델의 크기 문제, 설치되어 있는 패키지 버전 문제 등 다양한 문제에 의해 모델을 사용할 수 없는 상황이 발생합니다. 17 | 18 | 그렇다면 각기 다른 디바이스에서 모델을 직접 사용하기 어려운 문제를 해결하기 위한 방안으로써 데이터만 전달해주면 어떨까요? 19 | 위의 예시에서는 개 또는 고양이를 찍은 사진을 모델을 돌릴 수 있는 환경으로 전송하면, 그 환경에서 직접 모델을 돌려서 나온 결과를 사용자에게 전달하게 됩니다. 20 | 이렇게 하면 모델을 사용하고 싶은 사람은 모델을 직접 돌리지 않고도 원하는 결과를 얻을 수 있습니다. 21 | 이와 같이 요청을 보내고 해당 요청에 대한 응답을 받아 결과를 얻는 방식은 비단 머신러닝 모델뿐만 아니라 많은 소프트웨어에서 사용하는 방식입니다. 22 | 이러한 방식을 Request-Response 방식이라고 부릅니다. 23 | 24 |
25 | 26 | ![rest-api](./img/rest-api.png) 27 | [그림 5-1] Rest API (출처: https://phpenthusiast.com/blog/what-is-rest-api) 28 |
29 | 30 | 디바이스끼리 Request-Response 를 하기 위해서는 요청과 응답을 어떻게 할 것인지에 대해서 사전에 정의하는 절차가 필요합니다. 31 | 이러한 것 중 가장 대표적인 방법이 바로 REST API 입니다. 32 | 33 | 05. FastAPI 파트에서는 REST API 를 구현하는 오픈 소스 중 가장 대중적인 FastAPI 를 학습합니다. 34 | 그리고 06. API Serving 파트에서는 REST API 를 통해 모델을 사용하여 결과를 얻는 API Serving 에 대해서 학습합니다. 35 | 36 | ## Event Driven - Stream Serving 37 | 38 | 만약, 데이터가 계속해서 쌓이고 있는 상황이라면 어떻게 될까요? 39 | 예를 들어 공장에서 어떤 센서가 부착되어 있고 센서는 정해진 주기마다 계속해서 데이터를 수집하고 저장하고 있는 상황을 가정해 봅시다. 40 | 이렇게 지속적으로 수집되고 있는 데이터에 대해서 실시간으로 이상 탐지를 할 수 있는 모델을 서빙해야 한다면 어떻게 할 수 있을까요? 41 | 42 | 이러한 경우, 데이터를 수집하고 있는 곳에서 모델에게 계속해서 요청을 보내 결과를 받아오면 될 것 같습니다. 하지만 이 방법은 여러 문제를 가지고 있습니다. 43 | 수집하는 센서는 보통 아주 작은 단위의 업무만 처리할 수 있기에 요청을 보낼 수 없는 경우가 많습니다. 또한 요청을 통해 결과를 받는 주체가 아닌 경우가 많습니다. 44 | 이를 해결하기 위해서는 대신 요청을 보내고 결과를 수집할 수 있는 주체가 필요합니다. 45 | 46 | 위의 예시와 같이 지속적으로 데이터를 수집하고 요청을 보내 결과를 수집하는 상황을 Stream 이라고 표현합니다. 47 | 이를 위해 07. Kafka 파트에서 인프라를 주로 다루는 Kafka 를 학습합니다. 48 | 그리고 08. Stream 파트에서 모델에 요청을 보내서 결과를 수집하는 Stream Serving 을 학습하고, 이를 Dashboard 로 연결하여 시각화하는 Grafana 에 대해 학습합니다. 49 | -------------------------------------------------------------------------------- /docs/model-development/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "02. Model Development", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Model Development" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/model-development/base-model-pipeline.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 여러 개의 모델들을 하나의 파이프라인으로 작성합니다. 4 | --- 5 | 6 | # 2) Model Pipeline 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | 14 | ## Chapter Preview 15 | --- 16 | ### 목표 17 | 18 | 1. 여러 개의 모델들을 하나의 파이프라인으로 작성합니다. 19 | 20 | ### 스펙 명세서 21 | 22 | 1. 모델들의 파이프라인화 23 | - `scikit-learn` 에 있는 pipeline 을 이용합니다. 24 | 2. 저장된 파이프라인 검증 25 | - 저장된 파이프라인이 정상적으로 동작하는지 확인합니다. 26 | 27 | 28 | 29 | 30 | 31 | 해당 파트의 전체 코드는 [mlops-for-mle/part2/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part2) 에서 확인할 수 있습니다. 32 | 33 | ```js 34 | part2 35 | ├── Makefile 36 | ├── README.md 37 | ├── base_train.py 38 | ├── base_validate_save_model.py 39 | ├── db_train.py 40 | ├── db_validate_save_model.py 41 | // highlight-next-line 42 | ├── pipeline_train.py 43 | // highlight-next-line 44 | └── pipeline_validate_save_model.py 45 | ``` 46 | 47 | 48 | 49 | ## 1. Model Pipeline 50 | 51 | ### 1.1 Scaler & SVC 52 | 1) Base Model Development 챕터에서 예측을 위해 사용한 모델은 scaler 와 SVC 두 가지가 있었습니다. 53 | 또한 SVC 가 정상적으로 예측하기 위해서는 scaler 가 필요하다는 것도 알아 보았습니다. 54 | 즉 SVC 모델을 사용하기 위해서는 아래와 같이 사용해야 합니다. 55 | 56 | ```python 57 | scaled_X_train = scaler.transform(X_train) 58 | train_pred = classifier.predict(scaled_X_train) 59 | ``` 60 | 61 | 하지만 위 방법은 scaler 를 사용하지 않거나 다른 scaler 를 사용하는 경우가 발생할 수 있습니다. 62 | 이러한 실수를 막을 수 있는 방법이 모델들을 파이프라인화 시키는 것입니다. 63 | 파이프라인된 모델은 아래처럼 사용할 수 있습니다. 64 | 65 | ```python 66 | model_pipeline.predict(X_train) 67 | ``` 68 | 69 | `model_pipeline` 안에는 학습이 완료된 scaler 와 SVC 가 같이 존재하기 때문에 위에서 발생할 수 있는 실수를 없애줍니다. 70 | 71 | 물론 이 방법에도 단점이 있습니다. 한번 구축된 파이프라인은 수정하기 어렵다는 점과 scaler 처럼 한 모델에서만 쓰이는게 아니라 여러 모델에도 사용할 수 있는 것들을 중복적으로 학습해야 한다는 점이 있습니다. 72 | 73 | ### 1.2 Code 74 | 직접 모델들을 파이프라인으로 작성해 보겠습니다. 75 | 76 | `sklearn.pipeline` 의 `Pipeline` 을 통해 파이프라인을 작성할 수 있습니다. 이 때 파이프라인 안에 들어가는 값은 리스트이며 리스트 안에는 `(모델 이름, 모델 객체)` 가 값으로 들어갑니다. 77 | 78 | ```python title="pipeline_train.py" 79 | from sklearn.preprocessing import StandardScaler 80 | from sklearn.pipeline import Pipeline 81 | from sklearn.svm import SVC 82 | 83 | model_pipeline = Pipeline([("scaler", StandardScaler()), ("svc", SVC())]) 84 | ``` 85 | 86 | 이제 생성한 파이프라인을 학습해 보도록 하겠습니다. 학습 방법은 일반적인 `scikit-learn` 의 모델처럼 진행하면 됩니다. 87 | 88 | ```python title="pipeline_train.py" 89 | model_pipeline.fit(X_train, y_train) 90 | ``` 91 | 92 | 학습이 완료된 파이프라인은 바로 예측을 하거나 각 단계별로 진행해 볼 수 있습니다. 93 | 94 | 예를 들어서 scaler 만 사용하고 싶은 경우에는 아래처럼 할 수 있습니다. 95 | 96 | ```python title="pipeline_train.py" 97 | print(model_pipeline[0].transform(X_train[:1])) 98 | # [[-1.71687346 -0.1513372 -1.37527528 -1.29070478]] 99 | ``` 100 | 101 | 다음으로 파이프라인으로 예측을 하고 정확도를 계산합니다. 102 | 103 | ```python title="pipeline_train.py" 104 | from sklearn.metrics import accuracy_score 105 | 106 | train_pred = model_pipeline.predict(X_train) 107 | valid_pred = model_pipeline.predict(X_valid) 108 | 109 | train_acc = accuracy_score(y_true=y_train, y_pred=train_pred) 110 | valid_acc = accuracy_score(y_true=y_valid, y_pred=valid_pred) 111 | 112 | print("Train Accuracy :", train_acc) 113 | print("Valid Accuracy :", valid_acc) 114 | # Train Accuracy : 0.9833333333333333 115 | # Valid Accuracy : 0.9666666666666667 116 | ``` 117 | 118 | 마지막으로 모델을 저장합니다. 1) Base Model Development 챕터처럼 따로 할 필요없이 하나의 파일로 저장할 수 있습니다. 119 | 120 | ```python title="pipeline_train.py" 121 | import joblib 122 | 123 | joblib.dump(model_pipeline, "model_pipeline.joblib") 124 | ``` 125 | 126 | ### 1.3 `pipeline_train.py` 127 | 128 | 위에서 작성한 코드를 모아서 `pipeline_train.py` 로 작성합니다. 129 | 130 | ```python title="pipeline_train.py" 131 | # pipeline_train.py 132 | import joblib 133 | from sklearn.datasets import load_iris 134 | from sklearn.metrics import accuracy_score 135 | from sklearn.model_selection import train_test_split 136 | from sklearn.preprocessing import StandardScaler 137 | from sklearn.pipeline import Pipeline 138 | from sklearn.svm import SVC 139 | 140 | # 1. get data 141 | X, y = load_iris(return_X_y=True, as_frame=True) 142 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 143 | 144 | # 2. model development and train 145 | model_pipeline = Pipeline([("scaler", StandardScaler()), ("svc", SVC())]) 146 | model_pipeline.fit(X_train, y_train) 147 | 148 | train_pred = model_pipeline.predict(X_train) 149 | valid_pred = model_pipeline.predict(X_valid) 150 | 151 | train_acc = accuracy_score(y_true=y_train, y_pred=train_pred) 152 | valid_acc = accuracy_score(y_true=y_valid, y_pred=valid_pred) 153 | 154 | print("Train Accuracy :", train_acc) 155 | print("Valid Accuracy :", valid_acc) 156 | 157 | # 3. save model 158 | joblib.dump(model_pipeline, "model_pipeline.joblib") 159 | ``` 160 | 161 | ## 2. `pipeline_validate_save_model.py` 162 | 163 | 저장된 파이프라인이 정상적으로 동작하는 지 검증하기 위해 1) Base Model Development 챕터에서 작성한 `base_validate_save_model.py` 의 코드를 수정하여 `pipeline_validate_save_model.py` 로 작성합니다. 164 | 165 | ```python title="pipeline_validate_save_model.py" 166 | # pipeline_validate_save_model.py 167 | import joblib 168 | from sklearn.datasets import load_iris 169 | from sklearn.metrics import accuracy_score 170 | from sklearn.model_selection import train_test_split 171 | 172 | # 1. reproduce data 173 | X, y = load_iris(return_X_y=True, as_frame=True) 174 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 175 | 176 | # 2. load model 177 | model_pipeline_load = joblib.load("model_pipeline.joblib") 178 | 179 | # 3. validate 180 | load_train_pred = model_pipeline_load.predict(X_train) 181 | load_valid_pred = model_pipeline_load.predict(X_valid) 182 | 183 | load_train_acc = accuracy_score(y_true=y_train, y_pred=load_train_pred) 184 | load_valid_acc = accuracy_score(y_true=y_valid, y_pred=load_valid_pred) 185 | 186 | print("Load Model Train Accuracy :", load_train_acc) 187 | print("Load Model Valid Accuracy :", load_valid_acc) 188 | ``` 189 | -------------------------------------------------------------------------------- /docs/model-development/img/model-development-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-development/img/model-development-1.png -------------------------------------------------------------------------------- /docs/model-development/img/model-development-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-development/img/model-development-2.png -------------------------------------------------------------------------------- /docs/model-development/load-data-from-database.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 DB 에서 데이터를 가져오는 파이프라인을 작성합니다. 4 | --- 5 | 6 | # 3) Load Data from Database 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | 14 | ## Chapter Preview 15 | --- 16 | ### 목표 17 | 18 | 1. DB 에서 데이터를 가져오는 파이프라인을 작성합니다. 19 | 20 | ### 스펙 명세서 21 | 22 | 1. 데이터 불러오기 23 | - 01. Database 파트에서 생성한 DB 에서 데이터를 가져옵니다. 24 | - `id` column 을 기준으로 최신 데이터 100개를 추출하는 쿼리문을 작성합니다. 25 | - `pandas.read_sql` 함수를 이용해 데이터를 추출합니다. 26 | 2. 모델 파이프라인 수정 27 | - 1) Base Model Development 챕터에서 작성한 파이프라인 중 데이터를 불러오는 부분을 위에서 작성한 함수로 수정합니다. 28 | - 모델을 학습하고 저장합니다. 29 | - 저장된 모델이 정상적으로 동작하는지 확인합니다. 30 | 31 | 32 | 33 | 34 | 35 | 해당 파트의 전체 코드는 [mlops-for-mle/part2/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part2) 에서 확인할 수 있습니다. 36 | 37 | ```js 38 | part2 39 | ├── Makefile 40 | ├── README.md 41 | ├── base_train.py 42 | ├── base_validate_save_model.py 43 | // highlight-next-line 44 | ├── db_train.py 45 | // highlight-next-line 46 | ├── db_validate_save_model.py 47 | ├── pipeline_train.py 48 | └── pipeline_validate_save_model.py 49 | ``` 50 | 51 | 52 | 53 |
54 | 55 | ![database workflow](./img/model-development-2.png) 56 | [그림 2-2] Database Workflow 57 |
58 | 59 | 60 | :::caution 61 | 62 | 📌 해당 챕터는 01. Database 파트의 DB 를 이용합니다. 63 | 📌 DB 를 띄우지 않은 경우 01. Database 파트를 완료하고 DB 가 띄워진 상태에서 진행해주세요. 64 | 65 | ::: 66 | 67 | ## 1. Load Data 68 | ### 1.1 Query 69 | `id` column을 기준으로 최신 데이터 100개를 추출하는 쿼리문을 작성합니다. 70 | 71 | ```sql 72 | SELECT * FROM iris_data ORDER BY id DESC LIMIT 100; 73 | ``` 74 | 75 | `psql` 에서 해당 쿼리문을 입력하면 다음과 같이 출력됩니다. 76 | 77 | ```sql 78 | mydatabase=# SELECT * FROM iris_data ORDER BY id DESC LIMIT 100; 79 | id | timestamp | sepal_length | sepal_width | petal_length | petal_width | target 80 | -----+----------------------------+--------------+-------------+--------------+-------------+-------- 81 | 1 | 2023-01-15 06:08:58.995035 | 6.8 | 2.8 | 4.8 | 1.4 | 1 82 | 2 | 2023-01-15 06:09:00.033342 | 6.3 | 2.5 | 5 | 1.9 | 2 83 | 3 | 2023-01-15 06:09:01.063739 | 6.3 | 3.3 | 4.7 | 1.6 | 1 84 | 4 | 2023-01-15 06:09:02.098688 | 6.3 | 3.3 | 4.7 | 1.6 | 1 85 | 5 | 2023-01-15 06:09:03.131971 | 5 | 3.2 | 1.2 | 0.2 | 0 86 | (...) 87 | ``` 88 | 89 | ### 1.2 Pandas 90 | `pandas.read_sql` 는 입력 argument 로 query 와 DB connector 를 받습니다. 91 | 92 | PostgreSQL DB 에 연결할 수 있는 DB connector 를 생성 후 query 와 DB connector 를 이용하여 데이터를 불러옵니다. 93 | DB 에 연결하기 위한 정보는 01. Database 파트의 6) Data Generator on Docker Compose 챕터에서 DB 서버를 생성할 때 입력한 값입니다. 94 | 95 | 96 | 97 | ```python title="db_train.py" 98 | import pandas as pd 99 | import psycopg2 100 | 101 | db_connect = psycopg2.connect(host="localhost", database="mydatabase", user="myuser", password="mypassword") 102 | df = pd.read_sql("SELECT * FROM iris_data ORDER BY id DESC LIMIT 100", db_connect) 103 | ``` 104 | 105 | - db connect 106 | - host : localhost 107 | - database : mydatabase 108 | - user : myuser 109 | - password : mypassword 110 | 111 | 112 | 113 | 추출된 데이터를 확인하면 다음과 같습니다. 114 | 115 | ```python 116 | print(df.head(5)) 117 | # id timestamp sepal_length sepal_width petal_length petal_width target 118 | # 0 1204 2023-01-15 06:29:35.214374 7.2 3.2 6.0 1.8 2 119 | # 1 1203 2023-01-15 06:29:34.196810 5.0 3.5 1.3 0.3 0 120 | # 2 1202 2023-01-15 06:29:33.184427 5.9 3.0 4.2 1.5 1 121 | # 3 1201 2023-01-15 06:29:32.163934 6.4 3.1 5.5 1.8 2 122 | # 4 1200 2023-01-15 06:29:31.138341 5.8 2.7 5.1 1.9 2 123 | ``` 124 | 125 | 2) Model Pipeline 챕터에서 작성한 base_train.py# 1. get data 부분을 위에서 작성한 코드로 수정합니다. 126 | 127 | ```python title="db_train.py" 128 | # db_train.py 129 | import pandas as pd 130 | import psycopg2 131 | from sklearn.model_selection import train_test_split 132 | 133 | # 1. get data 134 | db_connect = psycopg2.connect(host="localhost", database="mydatabase", user="myuser", password="mypassword") 135 | df = pd.read_sql("SELECT * FROM iris_data ORDER BY id DESC LIMIT 100", db_connect) 136 | X = df.drop(["id", "timestamp", "target"], axis="columns") 137 | y = df["target"] 138 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 139 | ``` 140 | 141 | ## 2. Save Data 142 | 이어서 사용한 데이터를 저장하는 `# 4. save data` 부분을 추가합니다. 143 | 데이터를 저장하는 이유는 현재 DB 에 계속해서 데이터가 쌓이고 있기 때문에 매번 데이터를 불러올 때마다 데이터가 바뀝니다. 144 | 데이터가 바뀌면 모델이 정상적으로 불러왔는지 확인할 수 없기 때문에 사용한 데이터를 저장하여 평가하는 부분에서 사용합니다. 145 | 146 | ```python title="db_train.py" 147 | # 4. save data 148 | df.to_csv("data.csv", index=False) 149 | ``` 150 | 151 | 152 | ## 3. 전체 코드 153 | 154 | ### 3.1 `db_train.py` 155 | 위에서 작성한 내용을 모아서 `db_train.py` 로 작성하면 아래와 같습니다. 156 | 157 | ```python title="db_train.py" 158 | # db_train.py 159 | import joblib 160 | import pandas as pd 161 | import psycopg2 162 | from sklearn.metrics import accuracy_score 163 | from sklearn.model_selection import train_test_split 164 | from sklearn.preprocessing import StandardScaler 165 | from sklearn.pipeline import Pipeline 166 | from sklearn.svm import SVC 167 | 168 | # 1. get data 169 | db_connect = psycopg2.connect(host="localhost", database="mydatabase", user="myuser", password="mypassword") 170 | df = pd.read_sql("SELECT * FROM iris_data ORDER BY id DESC LIMIT 100", db_connect) 171 | X = df.drop(["id", "timestamp", "target"], axis="columns") 172 | y = df["target"] 173 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 174 | 175 | # 2. model development and train 176 | model_pipeline = Pipeline([("scaler", StandardScaler()), ("svc", SVC())]) 177 | model_pipeline.fit(X_train, y_train) 178 | 179 | train_pred = model_pipeline.predict(X_train) 180 | valid_pred = model_pipeline.predict(X_valid) 181 | 182 | train_acc = accuracy_score(y_true=y_train, y_pred=train_pred) 183 | valid_acc = accuracy_score(y_true=y_valid, y_pred=valid_pred) 184 | 185 | print("Train Accuracy :", train_acc) 186 | print("Valid Accuracy :", valid_acc) 187 | 188 | # 3. save model 189 | joblib.dump(model_pipeline, "db_pipeline.joblib") 190 | 191 | # 4. save data 192 | df.to_csv("data.csv", index=False) 193 | ``` 194 | 195 | ### 3.2 `validate_save_model.py` 196 | 197 | 다음은 2) Model Pipeline 챕터에서 저장된 모델을 검증하는 `base_validate_save_model.py` 를 수정해 `db_validate_save_model.py` 로 저장합니다. 198 | 그리고 `# 1. reproduce data` 에서 저장된 데이터를 불러오도록 수정합니다. 199 | 200 | ```python title="db_validate_save_model.py" 201 | # db_validate_save_model.py 202 | import joblib 203 | import pandas as pd 204 | from sklearn.metrics import accuracy_score 205 | from sklearn.model_selection import train_test_split 206 | 207 | # 1. reproduce data 208 | df = pd.read_csv("data.csv") 209 | X = df.drop(["id", "timestamp", "target"], axis="columns") 210 | y = df["target"] 211 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 212 | 213 | # 2. load model 214 | pipeline_load = joblib.load("db_pipeline.joblib") 215 | 216 | # 3. validate 217 | load_train_pred = pipeline_load.predict(X_train) 218 | load_valid_pred = pipeline_load.predict(X_valid) 219 | 220 | load_train_acc = accuracy_score(y_true=y_train, y_pred=load_train_pred) 221 | load_valid_acc = accuracy_score(y_true=y_valid, y_pred=load_valid_pred) 222 | 223 | print("Load Model Train Accuracy :", load_train_acc) 224 | print("Load Model Valid Accuracy :", load_valid_acc) 225 | ``` 226 | -------------------------------------------------------------------------------- /docs/model-development/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Model Development Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | import ModelDevelopmentImage1 from './img/model-development-1.png'; 9 | 10 | :::caution 11 | 12 | 📌 해당 파트는 01. Database 파트의 postgres server 와 data generator 를 이용합니다. 13 | 📌 DB 를 띄우지 않은 경우 01. Database 파트를 완료하고 postgres server 와 data generator 가 띄워진 상태에서 진행해주세요. 14 | 15 | ::: 16 | 17 | 이번 파트에서 구현할 workflow는 다음과 같습니다. 18 | 19 |
20 | 21 | 22 | [그림 2-1] Basic Workflow 23 |
24 | 25 | 데이터는 `scikit-learn` 패키지에 있는 iris 데이터를 사용합니다. 26 | 데이터를 통해 모델을 학습 후 저장하고, 저장된 모델을 불러와서 학습이 잘 되었는지 확인합니다. 27 | 28 |
29 | 30 | ![database workflow](./img/model-development-2.png) 31 | [그림 2-2] Database Workflow 32 |
33 | 34 | [그림 2-2]처럼 데이터를 불러오는 부분은 01. Database 파트에서 생성한 DB 의 iris 데이터를 사용합니다. 35 | -------------------------------------------------------------------------------- /docs/model-registry/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "03. Model Registry", 3 | "position": 4, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Model Registry" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-1.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-10.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-11.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-2.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-3.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-4.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-5.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-6.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-7.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-8.png -------------------------------------------------------------------------------- /docs/model-registry/img/model-registry-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/model-registry/img/model-registry-9.png -------------------------------------------------------------------------------- /docs/model-registry/load-model-from-registry.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 MLflow 에 저장된 모델을 불러올 수 있는 스크립트를 작성합니다. 4 | --- 5 | # 3) Load Model from Registry 6 | import CodeDescription from '@site/src/components/CodeDescription'; 7 | import PreviewDescription from '@site/src/components/PreviewDescription'; 8 | import BrowserWindow from '@site/src/components/BrowserWindow'; 9 | import WorkflowImage from './img/model-registry-9.png'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | 14 | ## Chapter Preview 15 | --- 16 | ### 목표 17 | 18 | 1. MLflow 에 저장된 모델을 불러올 수 있는 스크립트를 작성합니다. 19 | 2. 불러온 모델을 통해 추론하고 결과를 확인합니다. 20 | 21 | ### 스펙 명세서 22 | 23 | 1. 학습이 끝난 모델을 MLflow built-in method 를 사용하여 MLflow 서버에서 불러옵니다. 24 | - 2) Save Model to Registry 챕터에서 설치한 mlflow 패키지를 사용합니다. 25 | - 학습에 관련된 정보가 저장 되어있는 `run` 의 `run_id` 를 사용하여 모델을 불러옵니다. 26 | - `mlflow` 패키지를 이용하여 모델을 불러오는 방법은 두 가지가 있습니다. 27 | 1. [MLFlow built-in Model Flavors](https://www.mlflow.org/docs/latest/models.html#built-in-model-flavors) 28 | 2. [MLFLow pyfunc load_model](https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html#mlflow.pyfunc.load_model) 29 | - 이번 챕터에서는 `sklearn` 의 모델을 불러오기 위해 `mlflow.sklean.load_model` 을 사용합니다. 30 | 2. 불러온 모델을 이용하여 2) Save Model to Registry 챕터에서 저장해두었던 학습 데이터의 결과를 추론합니다. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 해당 파트의 전체 코드는 [mlops-for-mle/part3/](https://github.com/mlops-for-mle/mlops-for-mle/tree/main/part3) 에서 확인할 수 있습니다. 38 | 39 | ```js 40 | part3 41 | ├── Dockerfile 42 | ├── Makefile 43 | ├── README.md 44 | ├── docker-compose.yaml 45 | // highlight-next-line 46 | ├── load_model_from_registry.py 47 | └── save_model_to_registry.py 48 | ``` 49 | 50 | 51 | 52 | 53 |
54 | 55 | 56 | [그림 3-9] MLflow Model Load Diagram 57 |
58 | 59 | 60 | ## 1. 모델 불러오기 61 | 62 | 2) Save Model to Registry 챕터에서 작성한 코드로 학습된 모델을 서버로부터 불러오는 코드를 작성합니다. 63 | 64 | ### 1.1 환경 변수 설정 65 | 66 | 2) Save Model to Registry 챕터와 같이 MLflow 서버에 접근하기 위한 환경 변수를 설정합니다. 67 | 68 | ```python 69 | import os 70 | 71 | os.environ["MLFLOW_S3_ENDPOINT_URL"] = "http://localhost:9000" 72 | os.environ["MLFLOW_TRACKING_URI"] = "http://localhost:5001" 73 | os.environ["AWS_ACCESS_KEY_ID"] = "minio" 74 | os.environ["AWS_SECRET_ACCESS_KEY"] = "miniostorage" 75 | ``` 76 | 77 | ### 1.2 모델 불러오기 78 | 79 | #### 1.2.1 `sklearn` 모델 불러오기 80 | 81 | 2) Save Model to Registry 챕터에서 저장했던 모델을 불러오기 위해, mlflow.sklearn.load_model 함수를 사용하여 저장된 모델을 불러옵니다. 82 | 모델을 포함하고 있는 run_id 와 모델을 저장할 때 설정했던 모델 이름을 받을 수 있도록 외부 변수를 설정합니다. 83 | 84 | ```python 85 | parser = ArgumentParser() 86 | parser.add_argument("--run-id", dest="run_id", type=str) 87 | parser.add_argument("--model-name", dest="model_name", type=str, default="sk_model") 88 | args = parser.parse_args() 89 | ``` 90 | 91 | 앞서 받은 두 가지 변수를 이용해 `runs:/run_id/model_name` 의 형식으로 문자열을 만들어 줍니다. 92 | 만들어진 문자열을 `mlflow.sklearn.load_model` 의 입력으로 넣고 모델을 불러옵니다. 93 | 94 | ```python 95 | model_pipeline = mlflow.sklearn.load_model(f"runs:/{args.run_id}/{args.model_name}") 96 | ``` 97 | 98 | 불러온 모델을 확인하면 아래와 같습니다. 99 | 100 | ```python 101 | print(model_pipeline) 102 | # Pipeline(steps=[('scaler', StandardScaler()), ('svc', SVC())]) 103 | ``` 104 | 105 | #### 1.2.2 `pyfunc` 모델 불러오기 106 | 107 | MLflow 에서는 지정한 방식 [[MLFlow Storage Format](https://www.mlflow.org/docs/latest/models.html#storage-format)]에 따라 저장되어있는 모델에 대해서는 종류에 관계없이 `mlflow.pyfunc.load_model` 을 이용하여 쉽게 모델을 불러올 수 있습니다. 108 | 109 | 이 때 로드된 모델은 기존의 클래스가 아닌 `mlflow.pyfunc.PyFuncModel` 클래스로 불러와집니다. `PyFuncModel` 이란 `mlflow` 에서 정의된 새로운 클래스로, 결과 추론을 위해 학습한 모델의 `predict` method 를 호출하도록 wrapping 된 클래스입니다. 110 | 111 | ```python 112 | model_pipeline = mlflow.pyfunc.load_model(f"runs:/{args.run_id}/{args.model_name}") 113 | ``` 114 | 115 | 마찬가지로 앞서 받은 두 가지 변수를 형식에 맞춰 `mlflow.pyfunc.load_model` 의 입력으로 넣어 모델을 로드합니다. 116 | 117 | 불러와진 모델을 확인하면 아래와 같습니다. 118 | 119 | ```python 120 | print(model_pipeline) 121 | # mlflow.pyfunc.load_model: 122 | # artifact_path: sk_model 123 | # flavor: mlflow.sklearn 124 | # run_id: `RUN_ID` 125 | ``` 126 | 127 | ### 1.3 추론 코드 작성하기 128 | 129 | 2) Save Model to Registry 챕터에서 저장했던 데이터인 data.csv 파일로부터 데이터를 불러옵니다. 130 | 131 | ```python 132 | df = pd.read_csv("data.csv") 133 | ``` 134 | 135 | 학습 조건과 같도록 불필요한 columns 를 제거하고, 학습 데이터와 평가 데이터로 분리합니다. 136 | 137 | ```python 138 | X = df.drop(["id", "timestamp", "target"], axis="columns") 139 | y = df["target"] 140 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 141 | ``` 142 | 143 | 02. Model Development 파트와 같이 결과를 계산하고 출력합니다. 144 | 145 | ```python 146 | train_pred = model_pipeline.predict(X_train) 147 | valid_pred = model_pipeline.predict(X_valid) 148 | 149 | train_acc = accuracy_score(y_true=y_train, y_pred=train_pred) 150 | valid_acc = accuracy_score(y_true=y_valid, y_pred=valid_pred) 151 | 152 | print("Train Accuracy :", train_acc) 153 | print("Valid Accuracy :", valid_acc) 154 | # Train Accuracy : 0.95 155 | # Valid Accuracy : 0.95 156 | ``` 157 | 158 | ## 2. 전체 코드 완성 159 | 160 | 추가 작성한 코드를 전체 코드에 적용하여 완성합니다. 161 | 162 | ### 2.1 `load_model_from_registry.py` 163 | 164 | ```python title="load_model_from_registry.py" 165 | # load_model_from_registry.py 166 | import os 167 | from argparse import ArgumentParser 168 | 169 | import mlflow 170 | import pandas as pd 171 | from sklearn.metrics import accuracy_score 172 | from sklearn.model_selection import train_test_split 173 | 174 | # 0. set mlflow environments 175 | os.environ["MLFLOW_S3_ENDPOINT_URL"] = "http://localhost:9000" 176 | os.environ["MLFLOW_TRACKING_URI"] = "http://localhost:5001" 177 | os.environ["AWS_ACCESS_KEY_ID"] = "minio" 178 | os.environ["AWS_SECRET_ACCESS_KEY"] = "miniostorage" 179 | 180 | # 1. load model from mlflow 181 | parser = ArgumentParser() 182 | parser.add_argument("--model-name", dest="model_name", type=str, default="sk_model") 183 | parser.add_argument("--run-id", dest="run_id", type=str) 184 | args = parser.parse_args() 185 | 186 | model_pipeline = mlflow.sklearn.load_model(f"runs:/{args.run_id}/{args.model_name}") 187 | 188 | # 2. get data 189 | df = pd.read_csv("data.csv") 190 | 191 | X = df.drop(["id", "timestamp", "target"], axis="columns") 192 | y = df["target"] 193 | X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, random_state=2022) 194 | 195 | # 3. predict results 196 | train_pred = model_pipeline.predict(X_train) 197 | valid_pred = model_pipeline.predict(X_valid) 198 | 199 | train_acc = accuracy_score(y_true=y_train, y_pred=train_pred) 200 | valid_acc = accuracy_score(y_true=y_valid, y_pred=valid_pred) 201 | 202 | print("Train Accuracy :", train_acc) 203 | print("Valid Accuracy :", valid_acc) 204 | ``` 205 | 206 | ### 2.2 실행 및 결과 확인 207 | 208 | 1. [localhost:5001](http://localhost:5001) 에 접속하여 저장된 모델의 `run` 을 클릭하여 `run_id` 와 `model_name` 을 확인합니다. 209 |
210 | 211 | ![Model Download diagram](./img/model-registry-10.png) 212 | [그림 3-10] run-id 및 model-name 확인 213 |
214 | 2. 아래 코드의 `--model-name` , `--run-id` 뒤에 해당 값을 사용하여 실행합니다. 215 | 216 | ```bash 217 | # terminal-command 218 | python load_model_from_registry.py --model-name "sk_model" --run-id "RUN_ID" 219 | ``` 220 | 221 | 3. MLflow 서버의 metrics 를 확인하여 학습했던 결과와 같은지 확인합니다. 222 |
223 | 224 | ![Model Download diagram](./img/model-registry-11.png) 225 | [그림 3-11] 모델 추론 결과 확인 226 |
227 | -------------------------------------------------------------------------------- /docs/model-registry/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Model Registry Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | 9 | :::caution 10 | 11 | 📌 해당 파트는 01. Database 파트의 DB 를 이용합니다. 12 | 📌 DB 를 띄우지 않은 경우 01. Database 파트를 완료하고 DB 가 띄워진 상태에서 진행해주세요. 13 | 14 | ::: 15 | 16 | 03. Model Registry 파트에서는 02. Model development 파트를 통해 만들어진 모델을 저장, 관리 하는 방법을 학습합니다. 17 | 18 | 우선 MLflow 서버를 구축을 한 후 구축된 MLflow 서버에 저장하는 과정을 진행합니다. 19 | 이 때 코드는 02. Model Development 파트의 3) Load Data from Database 챕터에서 작성한 db_train.py 코드 중에서 `# 3. save model` 부분을 변경합니다. 20 | 21 |
22 | 23 | ![Model registry Workflow](./img/model-registry-1.png) 24 | [그림 3-1] Model Registry Workflow 25 |
26 | -------------------------------------------------------------------------------- /docs/stream/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "08. Stream", 3 | "position": 9, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Stream" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/stream/img/grafana-add-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-add-panel-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-add-panel-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-add-panel-2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-add-panel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-add-panel2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-after-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-after-login.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-after-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-after-save.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-click-gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-click-gear.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-click-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-click-new.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-dashboard-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-dashboard-setup.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source-2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source-3.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source-4.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source-5.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source-6.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source2-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-data-source2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-data-source2-2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-final-result.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-final-result.gif -------------------------------------------------------------------------------- /docs/stream/img/grafana-init-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-init-setup.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-initial-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-initial-dashboard.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-intro.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-move-to-board-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-move-to-board-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-move-to-board-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-move-to-board-2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-panel-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-panel-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-panel-2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-panel-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-panel-3.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-save-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-save-dashboard.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-save-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-save-panel-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-save-panel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-save-panel2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-set-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-set-panel-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-set-panel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-set-panel2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-set-time-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-set-time-1.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-set-time-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-set-time-2.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-set-time-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-set-time-3.png -------------------------------------------------------------------------------- /docs/stream/img/grafana-shape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/grafana-shape.png -------------------------------------------------------------------------------- /docs/stream/img/stream-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/stream-1.png -------------------------------------------------------------------------------- /docs/stream/img/stream-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/docs/stream/img/stream-2.png -------------------------------------------------------------------------------- /docs/stream/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Stream Chapter 4 | --- 5 | 6 | # 0) Overview 7 | 8 | import { Chapter, Part } from '@site/src/components/Highlight'; 9 | 10 | 11 | :::caution 12 | 13 | 📌 해당 파트는 01. Database 파트의 Source DB 를 이용합니다. 14 | 📌 해당 파트는 06. API Serving 파트의 API 서버를 이용합니다. 15 | 📌 해당 파트는 07. Kafka 파트의 Kafka System 및 Target DB 를 이용합니다. 16 | 📌 3가지 파트를 완료한 상태에서 해당 파트를 진행해 주세요. 17 | 18 | ::: 19 |

20 | 이번 파트에서는 04. Model Deployment 파트에서 소개한 Event-Driven 방식을 구현해봅니다. 21 | 07. Kafka 파트에서 생성된 Kafka System 과 Target DB 에 더하여, Consumer 를 통해 토픽으로부터 데이터를 읽어와서 06. API Serving 파트에서 생성된 API 서버의 입력으로 전달하고, inference 결과를 반환받아 Target DB 로 전달하는 Data Subscriber 를 구현합니다. 22 | 더 자세한 내용은 다음 챕터에서 알아보겠습니다. 23 |

24 |

25 | 또한, Stream Serving 뿐만 아니라 Grafana 를 이용하여 원본 데이터와 예측 결과 값을 실시간으로 시각화해주는 대시보드를 만듭니다. 26 | 대시보드를 통해 Stream Serving 이 잘 되고 있는지 확인합니다. 27 |

28 |

29 | 이번 파트를 통해 완성되는 workflow 는 다음과 같습니다. 30 |

31 |
32 | 33 | ![basic workflow](./img/stream-1.png) 34 | [그림 8-1] Stream Serving Workflow 35 |
36 | -------------------------------------------------------------------------------- /docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Note: type annotations allow type checking and IDEs autocompletion 3 | 4 | const lightCodeTheme = require('prism-react-renderer/themes/github'); 5 | const darkCodeTheme = require('prism-react-renderer/themes/dracula'); 6 | 7 | /** @type {import('@docusaurus/types').Config} */ 8 | const config = { 9 | title: 'ML Engineer를 위한 MLOps', 10 | tagline: 'Journey to build your own MLOps', 11 | url: 'https://mlops-for-mle.github.io/', 12 | baseUrl: '/tutorial/', 13 | trailingSlash: false, 14 | onBrokenLinks: 'throw', 15 | onBrokenMarkdownLinks: 'warn', 16 | favicon: 'img/favicon.ico', 17 | 18 | // GitHub pages deployment config. 19 | // If you aren't using GitHub pages, you don't need these. 20 | organizationName: 'mlops-for-mle', // Usually your GitHub org/user name. 21 | projectName: 'tutorial', // Usually your repo name. 22 | 23 | // Even if you don't use internalization, you can use this field to set useful 24 | // metadata like html lang. For example, if your site is Chinese, you may want 25 | // to replace "en" with "zh-Hans". 26 | i18n: { 27 | defaultLocale: 'ko', 28 | locales: ['ko', 'en'], 29 | }, 30 | plugins: [ 31 | [ 32 | 'content-docs', 33 | /** @type {import('@docusaurus/plugin-content-docs').Options} */ 34 | ({ 35 | id: 'community', 36 | path: 'community', 37 | routeBasePath: 'community', 38 | editUrl: 'https://github.com/mlops-for-mle/tutorial/tree/main/', 39 | editCurrentVersion: true, 40 | sidebarPath: require.resolve('./sidebarsCommunity.js'), 41 | showLastUpdateAuthor: true, 42 | showLastUpdateTime: true, 43 | }), 44 | ], 45 | ], 46 | presets: [ 47 | [ 48 | 'classic', 49 | /** @type {import('@docusaurus/preset-classic').Options} */ 50 | ({ 51 | docs: { 52 | sidebarPath: require.resolve('./sidebars.js'), 53 | // Please change this to your repo. 54 | // Remove this to remove the "edit this page" links. 55 | editUrl: 56 | 'https://github.com/mlops-for-mle/tutorial/tree/main/', 57 | editCurrentVersion: true, 58 | showLastUpdateAuthor: true, 59 | showLastUpdateTime: true, 60 | }, 61 | blog: { 62 | showReadingTime: true, 63 | // Please change this to your repo. 64 | // Remove this to remove the "edit this page" links. 65 | editUrl: 66 | 'https://github.com/mlops-for-mle/tutorial/tree/main/', 67 | }, 68 | theme: { 69 | customCss: require.resolve('./src/css/custom.css'), 70 | }, 71 | gtag: { 72 | trackingID: 'G-6GP6CF368Q', 73 | anonymizeIP: true, 74 | }, 75 | sitemap: { 76 | changefreq: 'weekly', 77 | priority: 0.5, 78 | ignorePatterns: ['/tags/**'], 79 | filename: 'sitemap.xml', 80 | }, 81 | }), 82 | ], 83 | ], 84 | 85 | themeConfig: 86 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 87 | ({ 88 | navbar: { 89 | title: 'MLOps for MLE', 90 | logo: { 91 | alt: 'My Site Logo', 92 | src: 'img/logo.svg', 93 | }, 94 | items: [ 95 | { 96 | type: 'doc', 97 | docId: 'intro', 98 | position: 'left', 99 | label: 'Documentation', 100 | }, 101 | { 102 | to: '/community/contributors', 103 | position: 'left', 104 | label: 'Community', 105 | }, 106 | { 107 | type: 'localeDropdown', 108 | position: 'right', 109 | }, 110 | { 111 | href: 'https://github.com/mlops-for-mle/mlops-for-mle', 112 | label: 'Code GitHub', 113 | position: 'right', 114 | }, 115 | { 116 | href: 'https://github.com/mlops-for-mle/tutorial', 117 | label: 'Tutorial Github', 118 | position: 'right', 119 | }, 120 | ], 121 | }, 122 | footer: { 123 | style: 'dark', 124 | links: [], 125 | logo: { 126 | alt: 'MakinaRocks', 127 | src: '/img/makinarocks.png', 128 | href: 'https://makinarocks.ai', 129 | }, 130 | copyright: `Copyright © 2022-${new Date().getFullYear()} MakinaRocks. Built with Docusaurus.`, 131 | }, 132 | prism: { 133 | theme: lightCodeTheme, 134 | darkTheme: darkCodeTheme, 135 | additionalLanguages: ['docker'], 136 | magicComments: [ 137 | // Remember to extend the default highlight class name as well! 138 | { 139 | className: 'theme-code-block-highlighted-line', 140 | line: 'highlight-next-line', 141 | block: {start: 'highlight-start', end: 'highlight-end'}, 142 | }, 143 | { 144 | className: 'code-block-terminal-command', 145 | line: 'terminal-command', 146 | }, 147 | ], 148 | }, 149 | image: 'img/logo.png', 150 | }), 151 | }; 152 | 153 | module.exports = config; 154 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-blog/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": { 3 | "message": "Blog", 4 | "description": "The title for the blog used in SEO" 5 | }, 6 | "description": { 7 | "message": "Blog", 8 | "description": "The description for the blog used in SEO" 9 | }, 10 | "sidebar.title": { 11 | "message": "Recent posts", 12 | "description": "The label for the left sidebar" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs-community/current.json: -------------------------------------------------------------------------------- 1 | { 2 | "version.label": { 3 | "message": "Next", 4 | "description": "The label for version current" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current.json: -------------------------------------------------------------------------------- 1 | { 2 | "version.label": { 3 | "message": "Next", 4 | "description": "The label for version current" 5 | }, 6 | "sidebar.tutorialSidebar.category.01. Database": { 7 | "message": "01. Database", 8 | "description": "The label for category 01. Database in sidebar tutorialSidebar" 9 | }, 10 | "sidebar.tutorialSidebar.category.01. Database.link.generated-index.description": { 11 | "message": "Database", 12 | "description": "The generated-index page description for category 01. Database in sidebar tutorialSidebar" 13 | }, 14 | "sidebar.tutorialSidebar.category.02. Model Development": { 15 | "message": "02. Model Development", 16 | "description": "The label for category 02. Model Development in sidebar tutorialSidebar" 17 | }, 18 | "sidebar.tutorialSidebar.category.02. Model Development.link.generated-index.description": { 19 | "message": "Model Development", 20 | "description": "The generated-index page description for category 02. Model Development in sidebar tutorialSidebar" 21 | }, 22 | "sidebar.tutorialSidebar.category.03. Model Registry": { 23 | "message": "03. Model Registry", 24 | "description": "The label for category 03. Model Registry in sidebar tutorialSidebar" 25 | }, 26 | "sidebar.tutorialSidebar.category.03. Model Registry.link.generated-index.description": { 27 | "message": "Model Registry", 28 | "description": "The generated-index page description for category 03. Model Registry in sidebar tutorialSidebar" 29 | }, 30 | "sidebar.tutorialSidebar.category.05. FastAPI": { 31 | "message": "05. FastAPI", 32 | "description": "The label for category 05. FastAPI in sidebar tutorialSidebar" 33 | }, 34 | "sidebar.tutorialSidebar.category.05. FastAPI.link.generated-index.description": { 35 | "message": "FastAPI", 36 | "description": "The generated-index page description for category 05. FastAPI in sidebar tutorialSidebar" 37 | }, 38 | "sidebar.tutorialSidebar.category.06. API Serving": { 39 | "message": "06. API Serving", 40 | "description": "The label for category 06. API Serving in sidebar tutorialSidebar" 41 | }, 42 | "sidebar.tutorialSidebar.category.06. API Serving.link.generated-index.description": { 43 | "message": "API Serving", 44 | "description": "The generated-index page description for category 06. API Serving in sidebar tutorialSidebar" 45 | }, 46 | "sidebar.tutorialSidebar.category.07. Kafka": { 47 | "message": "07. Kafka", 48 | "description": "The label for category 07. Kafka in sidebar tutorialSidebar" 49 | }, 50 | "sidebar.tutorialSidebar.category.07. Kafka.link.generated-index.description": { 51 | "message": "Kafka", 52 | "description": "The generated-index page description for category 07. Kafka in sidebar tutorialSidebar" 53 | }, 54 | "sidebar.tutorialSidebar.category.08. Stream": { 55 | "message": "08. Stream", 56 | "description": "The label for category 08. Stream in sidebar tutorialSidebar" 57 | }, 58 | "sidebar.tutorialSidebar.category.08. Stream.link.generated-index.description": { 59 | "message": "Stream", 60 | "description": "The generated-index page description for category 08. Stream in sidebar tutorialSidebar" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "06. API Serving", 3 | "position": 7, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "API Serving" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-4.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/api-serving/img/api-serving-5.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/model-api-on-docker-compose.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 API 서버를 Docker Compose 로 띄우기 위한 내용을 다룹니다. 4 | --- 5 | 6 | # 2) Model API on Docker Compose 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import APIServingImage5 from './img/api-serving-5.png'; 12 | 13 | 14 | ## Under tranlsation 15 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/model-api.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 Iris 데이터를 입력받아 예측값을 반환하는 API 를 작성합니다. 4 | --- 5 | 6 | # 1) Model API 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/api-serving/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of API Serving Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | 9 | 10 | ## Under tranlsation 11 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "01. Database", 3 | "position": 2, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Database" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/data-generator-docker-compose.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | description: 📌 DB 컨테이너와 Data Generator 컨테이너를 함께 띄우기 위한 Docker Compose 파일을 작성합니다. 4 | --- 5 | 6 | # 6) Data Generator on Docker Compose 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/data-generator-docker.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | description: 📌 앞서 작성했던 코드를 Docker 컨테이너 안에서 실행하기 위해 Dockerfile 을 작성합니다. 4 | --- 5 | 6 | # 5) Data Generator on Docker 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import DBImage2 from './img/db-2.png'; 12 | import DBImage3 from './img/db-3.png'; 13 | import DBImage4 from './img/db-4.png'; 14 | 15 | ## Under tranlsation 16 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/data-insertion-loop.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | description: 📌 생성된 테이블 안에 데이터를 계속해서 생성하는 스크립트를 작성합니다. 4 | --- 5 | 6 | # 4) Data Insertion Loop 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/data-insertion.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 생성한 테이블에 iris 데이터 한 줄을 삽입합니다. 4 | --- 5 | 6 | # 3) Data Insertion 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/db-server-creation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 Docker 를 이용하여 DB 서버를 생성합니다. 4 | --- 5 | 6 | # 1) DB Server Creation 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | ## Under tranlsation 12 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/img/db-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/database/img/db-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/img/db-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/database/img/db-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/img/db-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/database/img/db-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/img/db-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/database/img/db-4.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/img/db-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/database/img/db-5.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Database Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import DBImage1 from './img/db-1.png'; 8 | 9 | ## Under tranlsation 10 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/database/table-creation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 생성된 DB 에 query 를 작성하여 테이블을 생성합니다. 4 | --- 5 | 6 | # 2) Table Creation 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "05. FastAPI", 3 | "position": 6, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "FastAPI" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/fasapi-crud-pydantic.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 앞서 작성한 API 에서 Create 부분을 Pydantic 을 이용하여 수정합니다. 4 | --- 5 | 6 | # 3) FastAPI CRUD (Pydantic) 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/fastapi-crud.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 FastAPI 를 이용해 CRUD 를 수행하는 API 를 작성합니다. 4 | --- 5 | 6 | # 2) FastAPI CRUD 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/fastapi-on-docker.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | description: 📌 앞서 작성한 API 를 Docker 를 이용하여 실행합니다. 4 | --- 5 | 6 | # 4) FastAPI on Docker 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/fastapi-tutorial.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 FastAPI 의 공식 문서를 참고하여 간단한 API 를 만들어봅니다. 4 | --- 5 | 6 | # 1) FastAPI Tutorial 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-4.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-5.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-6.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-7.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-8.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/fastapi/img/fastapi-9.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/fastapi/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of FastAPI Chapter 4 | --- 5 | 6 | # 0) Overview 7 | 8 | ## Under tranlsation 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/img/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/img/architecture.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/img/google-trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/img/google-trend.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/img/mlops-level-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/img/mlops-level-0.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/img/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/img/pipeline.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/img/rest-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/img/rest-api.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/intro.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 00. Introduction 6 | import CodeDescription from '@site/src/components/CodeDescription'; 7 | import PreviewDescription from '@site/src/components/PreviewDescription'; 8 | import BrowserWindow from '@site/src/components/BrowserWindow'; 9 | 10 | 11 | ## Under tranlsation 12 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "07. Kafka", 3 | "position": 8, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Kafka" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/connect-connector.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 Kafka 의 Connect 와 Connector 에 대해 알아봅니다. 4 | --- 5 | 6 | # 3) Connect & Connector 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import KafkaImage7 from './img/kafka-7.png'; 12 | import KafkaImage8 from './img/kafka-8.png'; 13 | 14 | 15 | ## Under tranlsation 16 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-10.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-11.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-12.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-13.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-14.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-15.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-4.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-5.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-6.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-7.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-8.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-9.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-gif-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/kafka/img/kafka-gif-1.gif -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/kafka-introduction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 메시징 시스템에 대해 알아봅니다. 4 | --- 5 | 6 | # 1) Kafka Introduction 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/kafka-system.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | description: 📌 Docker Compose 를 이용하여 Zookeeper, Broker, Schema Registry, Connect 를 생성합니다. 4 | --- 5 | 6 | # 4) Kafka System 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import ArchitectureImage from './img/kafka-13.png'; 12 | 13 | 14 | ## Under tranlsation 15 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Kafka Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | 9 | 10 | ## Under tranlsation 11 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/producer-consumer.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 Docker Compose 를 이용하여 주키퍼와 브로커를 생성합니다. 4 | --- 5 | 6 | # 2) Producer & Consumer 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | 11 | 12 | ## Under tranlsation 13 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/sink-connector.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | description: 📌 Connect 에 Sink Connector 를 띄워봅니다. 4 | --- 5 | 6 | # 6) Sink Connector 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import ArchitectureImage from './img/kafka-15.png'; 12 | 13 | 14 | ## Under tranlsation 15 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/kafka/source-connector.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | description: 📌 Connect 에 Source Connector 를 생성합니다. 4 | --- 5 | 6 | # 5) Source Connector 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import ArchitectureImage from './img/kafka-14.png'; 12 | 13 | 14 | ## Under tranlsation 15 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-deployment.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | # 04. Model Deployment 5 | import { Chapter, Part } from '@site/src/components/Highlight'; 6 | 7 | 8 | ## Under tranlsation 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "02. Model Development", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Model Development" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/base-model-development.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 모델을 학습하고 저장하는 기본적인 파이프라인을 작성합니다. 4 | --- 5 | 6 | # 1) Base Model Development 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | import ModelDevelopmentImage1 from './img/model-development-1.png'; 12 | 13 | 14 | ## Under tranlsation 15 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/base-model-pipeline.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 여러 개의 모델들을 하나의 파이프라인으로 작성합니다. 4 | --- 5 | 6 | # 2) Model Pipeline 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/img/model-development-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-development/img/model-development-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/img/model-development-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-development/img/model-development-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/load-data-from-database.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 DB 에서 데이터를 가져오는 파이프라인을 작성합니다. 4 | --- 5 | 6 | # 3) Load Data from Database 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-development/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Model Development Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | import ModelDevelopmentImage1 from './img/model-development-1.png'; 9 | 10 | 11 | ## Under tranlsation 12 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "03. Model Registry", 3 | "position": 4, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Model Registry" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-10.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-11.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-4.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-5.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-6.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-7.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-8.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/model-registry/img/model-registry-9.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/load-model-from-registry.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | description: 📌 MLflow 에 저장된 모델을 불러올 수 있는 스크립트를 작성합니다. 4 | --- 5 | # 3) Load Model from Registry 6 | import CodeDescription from '@site/src/components/CodeDescription'; 7 | import PreviewDescription from '@site/src/components/PreviewDescription'; 8 | import BrowserWindow from '@site/src/components/BrowserWindow'; 9 | import WorkflowImage from './img/model-registry-9.png'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/mlflow-setup.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 Docker Compose 를 이용하여 실제 서비스 환경과 비슷한 형태로 MLflow 서버를 띄워봅니다. 4 | --- 5 | # 1) MLflow Setup 6 | import CodeDescription from '@site/src/components/CodeDescription'; 7 | import PreviewDescription from '@site/src/components/PreviewDescription'; 8 | import BrowserWindow from '@site/src/components/BrowserWindow'; 9 | import WorkflowImage from './img/model-registry-2.png'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Model Registry Chapter 4 | --- 5 | 6 | # 0) Overview 7 | import { Chapter, Part } from '@site/src/components/Highlight'; 8 | 9 | 10 | ## Under tranlsation 11 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/model-registry/save-model-to-registry.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 모델을 학습하고 MLflow 서버에 저장합니다. 4 | --- 5 | 6 | # 2) Save Model to Registry 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "08. Stream", 3 | "position": 9, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Stream" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/dashboard.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: 📌 Grafana 대시보드를 통해 실시간으로 데이터를 모니터링하는 대시보드를 작성합니다. 4 | --- 5 | 6 | # 2) Dashboard 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-add-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-add-panel-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-add-panel-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-add-panel-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-add-panel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-add-panel2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-after-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-after-login.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-after-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-after-save.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-click-gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-click-gear.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-click-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-click-new.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-dashboard-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-dashboard-setup.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-4.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-5.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source-6.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source2-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-data-source2-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-final-result.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-final-result.gif -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-init-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-init-setup.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-initial-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-initial-dashboard.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-intro.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-move-to-board-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-move-to-board-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-move-to-board-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-move-to-board-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-panel-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-panel-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-panel-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-panel-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-panel-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-save-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-save-dashboard.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-save-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-save-panel-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-save-panel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-save-panel2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-panel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-panel-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-panel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-panel2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-time-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-time-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-time-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-time-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-time-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-set-time-3.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-shape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/grafana-shape.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/stream-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/stream-1.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/img/stream-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/i18n/en/docusaurus-plugin-content-docs/current/stream/img/stream-2.png -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | description: 📌 Overview of Stream Chapter 4 | --- 5 | 6 | # 0) Overview 7 | 8 | import { Chapter, Part } from '@site/src/components/Highlight'; 9 | 10 | ## Under tranlsation 11 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-docs/current/stream/stream-serving.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: 📌 Stream Serving 을 위한 Data Subscriber 코드를 작성합니다. 4 | --- 5 | 6 | # 1) Stream Serving 7 | import CodeDescription from '@site/src/components/CodeDescription'; 8 | import PreviewDescription from '@site/src/components/PreviewDescription'; 9 | import BrowserWindow from '@site/src/components/BrowserWindow'; 10 | import { Chapter, Part } from '@site/src/components/Highlight'; 11 | 12 | 13 | ## Under tranlsation 14 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-pages/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import styles from './styles.module.css'; 4 | 5 | type FeatureItem = { 6 | title: string; 7 | Svg: React.ComponentType>; 8 | description: JSX.Element; 9 | }; 10 | 11 | const FeatureList: FeatureItem[] = [ 12 | { 13 | title: MLOps for MLE, 14 | Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, 15 | description: ( 16 | <> 17 | Code repository github that is used at MLOps for ML Engineer
18 | 19 | ), 20 | }, 21 | { 22 | title: MLOps for ALL, 23 | Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, 24 | description: ( 25 | <> 26 | If you have already wrap up this project how about MLOps for ALL project?
27 | MLOps for ALL is a tutorial for building an mlops platform based on Kubeflow.
28 | 29 | ), 30 | }, 31 | ]; 32 | 33 | function Feature({title, Svg, description}: FeatureItem) { 34 | return ( 35 |
36 |
37 | 38 |
39 |
40 |

{title}

41 |

{description}

42 |
43 |
44 | ); 45 | } 46 | 47 | export default function HomepageFeatures(): JSX.Element { 48 | return ( 49 |
50 |
51 |
52 | {FeatureList.map((props, idx) => ( 53 | 54 | ))} 55 |
56 |
57 |
58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-pages/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-plugin-content-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Link from '@docusaurus/Link'; 4 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 5 | import Layout from '@theme/Layout'; 6 | import HomepageFeatures from './components/HomepageFeatures'; 7 | 8 | import styles from './index.module.css'; 9 | 10 | function HomepageHeader() { 11 | const {siteConfig} = useDocusaurusContext(); 12 | return ( 13 |
14 |
15 |

MLOps for ML Engineer

16 |

{siteConfig.tagline}

17 |
18 | 21 | Let's Start! 22 | 23 |
24 |
25 |
26 | ); 27 | } 28 | 29 | export default function Home(): JSX.Element { 30 | const {siteConfig} = useDocusaurusContext(); 31 | return ( 32 | 35 | 36 |
37 | 38 |
39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-theme-classic/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "copyright": { 3 | "message": "Copyright © 2022-2024 MakinaRocks. Built with Docusaurus.", 4 | "description": "The footer copyright" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /i18n/en/docusaurus-theme-classic/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": { 3 | "message": "MLOps for MLE", 4 | "description": "The title in the navbar" 5 | }, 6 | "item.label.Documentation": { 7 | "message": "Documentation", 8 | "description": "Navbar item with label Documentation" 9 | }, 10 | "item.label.Community": { 11 | "message": "Community", 12 | "description": "Navbar item with label Community" 13 | }, 14 | "item.label.Code GitHub": { 15 | "message": "Code GitHub", 16 | "description": "Navbar item with label Code GitHub" 17 | }, 18 | "item.label.Tutorial Github": { 19 | "message": "Tutorial Github", 20 | "description": "Navbar item with label Tutorial Github" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /i18n/ko/docusaurus-plugin-content-blog/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": { 3 | "message": "Blog", 4 | "description": "The title for the blog used in SEO" 5 | }, 6 | "description": { 7 | "message": "Blog", 8 | "description": "The description for the blog used in SEO" 9 | }, 10 | "sidebar.title": { 11 | "message": "Recent posts", 12 | "description": "The label for the left sidebar" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /i18n/ko/docusaurus-plugin-content-docs-community/current.json: -------------------------------------------------------------------------------- 1 | { 2 | "version.label": { 3 | "message": "Next", 4 | "description": "The label for version current" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /i18n/ko/docusaurus-plugin-content-docs/current.json: -------------------------------------------------------------------------------- 1 | { 2 | "version.label": { 3 | "message": "Next", 4 | "description": "The label for version current" 5 | }, 6 | "sidebar.tutorialSidebar.category.01. Database": { 7 | "message": "01. Database", 8 | "description": "The label for category 01. Database in sidebar tutorialSidebar" 9 | }, 10 | "sidebar.tutorialSidebar.category.01. Database.link.generated-index.description": { 11 | "message": "Database", 12 | "description": "The generated-index page description for category 01. Database in sidebar tutorialSidebar" 13 | }, 14 | "sidebar.tutorialSidebar.category.02. Model Development": { 15 | "message": "02. Model Development", 16 | "description": "The label for category 02. Model Development in sidebar tutorialSidebar" 17 | }, 18 | "sidebar.tutorialSidebar.category.02. Model Development.link.generated-index.description": { 19 | "message": "Model Development", 20 | "description": "The generated-index page description for category 02. Model Development in sidebar tutorialSidebar" 21 | }, 22 | "sidebar.tutorialSidebar.category.03. Model Registry": { 23 | "message": "03. Model Registry", 24 | "description": "The label for category 03. Model Registry in sidebar tutorialSidebar" 25 | }, 26 | "sidebar.tutorialSidebar.category.03. Model Registry.link.generated-index.description": { 27 | "message": "Model Registry", 28 | "description": "The generated-index page description for category 03. Model Registry in sidebar tutorialSidebar" 29 | }, 30 | "sidebar.tutorialSidebar.category.05. FastAPI": { 31 | "message": "05. FastAPI", 32 | "description": "The label for category 05. FastAPI in sidebar tutorialSidebar" 33 | }, 34 | "sidebar.tutorialSidebar.category.05. FastAPI.link.generated-index.description": { 35 | "message": "FastAPI", 36 | "description": "The generated-index page description for category 05. FastAPI in sidebar tutorialSidebar" 37 | }, 38 | "sidebar.tutorialSidebar.category.06. API Serving": { 39 | "message": "06. API Serving", 40 | "description": "The label for category 06. API Serving in sidebar tutorialSidebar" 41 | }, 42 | "sidebar.tutorialSidebar.category.06. API Serving.link.generated-index.description": { 43 | "message": "API Serving", 44 | "description": "The generated-index page description for category 06. API Serving in sidebar tutorialSidebar" 45 | }, 46 | "sidebar.tutorialSidebar.category.07. Kafka": { 47 | "message": "07. Kafka", 48 | "description": "The label for category 07. Kafka in sidebar tutorialSidebar" 49 | }, 50 | "sidebar.tutorialSidebar.category.07. Kafka.link.generated-index.description": { 51 | "message": "Kafka", 52 | "description": "The generated-index page description for category 07. Kafka in sidebar tutorialSidebar" 53 | }, 54 | "sidebar.tutorialSidebar.category.08. Stream": { 55 | "message": "08. Stream", 56 | "description": "The label for category 08. Stream in sidebar tutorialSidebar" 57 | }, 58 | "sidebar.tutorialSidebar.category.08. Stream.link.generated-index.description": { 59 | "message": "Stream", 60 | "description": "The generated-index page description for category 08. Stream in sidebar tutorialSidebar" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /i18n/ko/docusaurus-theme-classic/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "copyright": { 3 | "message": "Copyright © 2022-2024 MakinaRocks. Built with Docusaurus.", 4 | "description": "The footer copyright" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /i18n/ko/docusaurus-theme-classic/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": { 3 | "message": "MLOps for MLE", 4 | "description": "The title in the navbar" 5 | }, 6 | "item.label.Documentation": { 7 | "message": "Documentation", 8 | "description": "Navbar item with label Documentation" 9 | }, 10 | "item.label.Community": { 11 | "message": "Community", 12 | "description": "Navbar item with label Community" 13 | }, 14 | "item.label.Code GitHub": { 15 | "message": "Code GitHub", 16 | "description": "Navbar item with label Code GitHub" 17 | }, 18 | "item.label.Tutorial Github": { 19 | "message": "Tutorial Github", 20 | "description": "Navbar item with label Tutorial Github" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "temp", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "2.2.0", 19 | "@docusaurus/plugin-google-analytics": "^2.2.0", 20 | "@docusaurus/plugin-google-gtag": "^2.2.0", 21 | "@docusaurus/plugin-sitemap": "^2.2.0", 22 | "@docusaurus/preset-classic": "2.2.0", 23 | "@mdx-js/react": "^1.6.22", 24 | "clsx": "^1.2.1", 25 | "prism-react-renderer": "^1.3.5", 26 | "react": "^17.0.2", 27 | "react-dom": "^17.0.2" 28 | }, 29 | "devDependencies": { 30 | "@docusaurus/module-type-aliases": "2.2.0", 31 | "@tsconfig/docusaurus": "^1.0.5", 32 | "docusaurus": "^1.14.7", 33 | "typescript": "^4.7.4" 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.5%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 1 chrome version", 43 | "last 1 firefox version", 44 | "last 1 safari version" 45 | ] 46 | }, 47 | "engines": { 48 | "node": ">=16.14" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | 'intro', 23 | 'hello', 24 | { 25 | type: 'category', 26 | label: 'Tutorial', 27 | items: ['tutorial-basics/create-a-document'], 28 | }, 29 | ], 30 | */ 31 | }; 32 | 33 | module.exports = sidebars; 34 | -------------------------------------------------------------------------------- /sidebarsCommunity.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | 'intro', 23 | 'hello', 24 | { 25 | type: 'category', 26 | label: 'Tutorial', 27 | items: ['tutorial-basics/create-a-document'], 28 | }, 29 | ], 30 | */ 31 | }; 32 | 33 | module.exports = sidebars; 34 | -------------------------------------------------------------------------------- /src/components/BrowserWindow/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, {type ReactNode} from 'react'; 9 | import clsx from 'clsx'; 10 | 11 | import styles from './styles.module.css'; 12 | 13 | interface Props { 14 | children: ReactNode; 15 | minHeight: number; 16 | url: string; 17 | } 18 | 19 | export default function BrowserWindow({ 20 | children, 21 | minHeight, 22 | url = 'http://localhost:3000', 23 | }: Props): JSX.Element { 24 | return ( 25 |
26 |
27 |
28 | 29 | 30 | 31 |
32 |
33 | {url} 34 |
35 |
36 |
37 | 38 | 39 | 40 |
41 |
42 |
43 | 44 |
{children}
45 |
46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/components/BrowserWindow/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .browserWindow { 9 | border: 3px solid var(--ifm-color-emphasis-200); 10 | border-radius: var(--ifm-global-radius); 11 | box-shadow: var(--ifm-global-shadow-lw); 12 | margin-bottom: var(--ifm-leading); 13 | } 14 | 15 | .browserWindowHeader { 16 | align-items: center; 17 | background: var(--ifm-color-emphasis-200); 18 | display: flex; 19 | padding: 0.5rem 1rem; 20 | } 21 | 22 | .row::after { 23 | content: ''; 24 | display: table; 25 | clear: both; 26 | } 27 | 28 | .buttons { 29 | white-space: nowrap; 30 | } 31 | 32 | .right { 33 | align-self: center; 34 | width: 10%; 35 | } 36 | 37 | [data-theme='light'] { 38 | --ifm-background-color: #fff; 39 | } 40 | 41 | .browserWindowAddressBar { 42 | flex: 1 0; 43 | margin: 0 1rem 0 0.5rem; 44 | border-radius: 12.5px; 45 | background-color: var(--ifm-background-color); 46 | color: var(--ifm-color-gray-800); 47 | padding: 5px 15px; 48 | font: 400 13px Arial, sans-serif; 49 | user-select: none; 50 | } 51 | 52 | [data-theme='dark'] .browserWindowAddressBar { 53 | color: var(--ifm-color-gray-300); 54 | } 55 | 56 | .dot { 57 | margin-right: 6px; 58 | margin-top: 4px; 59 | height: 12px; 60 | width: 12px; 61 | background-color: #bbb; 62 | border-radius: 50%; 63 | display: inline-block; 64 | } 65 | 66 | .browserWindowMenuIcon { 67 | margin-left: auto; 68 | } 69 | 70 | .bar { 71 | width: 17px; 72 | height: 3px; 73 | background-color: #aaa; 74 | margin: 3px 0; 75 | display: block; 76 | } 77 | 78 | .browserWindowBody { 79 | background-color: var(--ifm-background-color); 80 | border-bottom-left-radius: inherit; 81 | border-bottom-right-radius: inherit; 82 | padding: 1rem; 83 | } 84 | 85 | .browserWindowBody > *:last-child { 86 | margin-bottom: 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/components/CodeDescription/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, {type ReactNode} from 'react'; 9 | 10 | import styles from './styles.module.css'; 11 | 12 | interface Props { 13 | children: ReactNode; 14 | minHeight: number; 15 | url: string; 16 | } 17 | 18 | export default function CodeDescription({ 19 | children, 20 | minHeight, 21 | }: Props): JSX.Element { 22 | return ( 23 |
24 |
{children}
25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/CodeDescription/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .codeDescription { 9 | border: 3px solid var(--ifm-color-emphasis-200); 10 | border-radius: var(--ifm-global-radius); 11 | box-shadow: var(--ifm-global-shadow-lw); 12 | margin-bottom: var(--ifm-leading); 13 | } 14 | 15 | .codeDescriptionHeader { 16 | align-items: center; 17 | background: var(--ifm-color-emphasis-200); 18 | display: flex; 19 | padding: 0.5rem 1rem; 20 | } 21 | 22 | .row::after { 23 | content: ''; 24 | display: table; 25 | clear: both; 26 | } 27 | 28 | .buttons { 29 | white-space: nowrap; 30 | } 31 | 32 | .right { 33 | align-self: center; 34 | width: 10%; 35 | } 36 | 37 | [data-theme='light'] { 38 | --ifm-background-color: #fff; 39 | } 40 | 41 | .dot { 42 | margin-right: 6px; 43 | margin-top: 4px; 44 | height: 12px; 45 | width: 12px; 46 | background-color: #bbb; 47 | border-radius: 50%; 48 | display: inline-block; 49 | } 50 | 51 | .bar { 52 | width: 17px; 53 | height: 3px; 54 | background-color: #aaa; 55 | margin: 3px 0; 56 | display: block; 57 | } 58 | 59 | .codeDescriptionBody { 60 | background-color: var(--ifm-background-color); 61 | border-bottom-left-radius: inherit; 62 | border-bottom-right-radius: inherit; 63 | padding: 1rem; 64 | } 65 | 66 | .codeDescriptionBody > *:last-child { 67 | margin-bottom: 0; 68 | } 69 | -------------------------------------------------------------------------------- /src/components/Highlight.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, {type ReactNode} from 'react'; 9 | 10 | 11 | export function Part({ 12 | children, 13 | }: { 14 | children: ReactNode; 15 | }): JSX.Element { 16 | return ( 17 | 24 | {children} 25 | 26 | ); 27 | } 28 | 29 | export function Chapter({ 30 | children, 31 | }: { 32 | children: ReactNode; 33 | }): JSX.Element { 34 | return ( 35 | 42 | {children} 43 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import styles from './styles.module.css'; 4 | 5 | type FeatureItem = { 6 | title: string; 7 | Svg: React.ComponentType>; 8 | description: JSX.Element; 9 | }; 10 | 11 | const FeatureList: FeatureItem[] = [ 12 | { 13 | title: MLOps for MLE, 14 | Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, 15 | description: ( 16 | <> 17 | ML Engineer를 위한 MLOps 에서 사용하는 코드들을 모아둔 레포입니다.
18 | 19 | ), 20 | }, 21 | { 22 | title: MLOps for ALL, 23 | Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, 24 | description: ( 25 | <> 26 | 프로젝트 학습을 끝냈거나 이미 MLOps에 익숙하시다면 MLOps for ALL 은 어떨까요?
27 | MLOps for ALL 은 Kubeflow 를 기반으로한 MLOps 플랫폼 구축을 위한 과정을 담은 튜토리얼 입니다.
28 | 29 | ), 30 | }, 31 | ]; 32 | 33 | function Feature({title, Svg, description}: FeatureItem) { 34 | return ( 35 |
36 |
37 | 38 |
39 |
40 |

{title}

41 |

{description}

42 |
43 |
44 | ); 45 | } 46 | 47 | export default function HomepageFeatures(): JSX.Element { 48 | return ( 49 |
50 |
51 |
52 | {FeatureList.map((props, idx) => ( 53 | 54 | ))} 55 |
56 |
57 |
58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /src/components/PreviewDescription/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, {type ReactNode} from 'react'; 9 | 10 | import styles from './styles.module.css'; 11 | 12 | interface Props { 13 | children: ReactNode; 14 | minHeight: number; 15 | url: string; 16 | } 17 | 18 | export default function PreviewDescription({ 19 | children, 20 | minHeight, 21 | }: Props): JSX.Element { 22 | return ( 23 |
24 |
{children}
25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/PreviewDescription/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .PreviewDescription { 9 | border: 3px solid rgb(106, 176, 209); 10 | border-radius: var(--ifm-global-radius); 11 | box-shadow: var(--ifm-global-shadow-lw); 12 | margin-bottom: var(--ifm-leading); 13 | } 14 | 15 | .PreviewDescriptionHeader { 16 | align-items: center; 17 | background: var(--ifm-color-emphasis-200); 18 | display: flex; 19 | padding: 0.5rem 1rem; 20 | } 21 | 22 | .row::after { 23 | content: ''; 24 | display: table; 25 | clear: both; 26 | } 27 | 28 | .buttons { 29 | white-space: nowrap; 30 | } 31 | 32 | .right { 33 | align-self: center; 34 | width: 10%; 35 | } 36 | 37 | [data-theme='light'] { 38 | --prev-background-color: rgb(240, 249, 253); 39 | } 40 | 41 | .dot { 42 | margin-right: 6px; 43 | margin-top: 4px; 44 | height: 12px; 45 | width: 12px; 46 | background-color: #bbb; 47 | border-radius: 50%; 48 | display: inline-block; 49 | } 50 | 51 | .bar { 52 | width: 17px; 53 | height: 3px; 54 | background-color: #aaa; 55 | margin: 3px 0; 56 | display: block; 57 | } 58 | 59 | .PreviewDescriptionBody { 60 | background-color: var(--prev-background-color); 61 | border-bottom-left-radius: inherit; 62 | border-bottom-right-radius: inherit; 63 | padding: 1rem; 64 | } 65 | 66 | .PreviewDescriptionBody > *:last-child { 67 | margin-bottom: 0; 68 | } 69 | -------------------------------------------------------------------------------- /src/components/TeamProfileCards/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, {type ReactNode} from 'react'; 9 | import Translate from '@docusaurus/Translate'; 10 | 11 | 12 | type ProfileProps = { 13 | className?: string; 14 | name: string; 15 | children: ReactNode; 16 | githubUrl: string; 17 | linkedinUrl?: string; 18 | }; 19 | 20 | function TeamProfileCard({ 21 | className, 22 | name, 23 | children, 24 | githubUrl, 25 | linkedinUrl, 26 | }: ProfileProps) { 27 | return ( 28 |
29 |
30 |
31 |
32 | {`${name}'s 37 |
38 |

{name}

39 |
40 |
41 |
42 |
{children}
43 |
44 |
45 | {githubUrl && ( 46 | 47 | GitHub 48 | 49 | )} 50 | {linkedinUrl && ( 51 | 52 | LinkedIn 53 | 54 | )} 55 |
56 |
57 |
58 |
59 | ); 60 | } 61 | 62 | function TeamProfileCardCol(props: ProfileProps) { 63 | return ( 64 | 65 | ); 66 | } 67 | 68 | export function MainAuthorRow(): JSX.Element { 69 | return ( 70 |
71 | 76 | 77 | Project Leader 78 | 79 | 80 | 84 | 85 | Project Member 86 | 87 | 88 | 93 | 94 | Project Member 95 | 96 | 97 | 101 | 102 | Project Member 103 | 104 | 105 |
106 | ); 107 | } 108 | 109 | export function ReviewersRow(): JSX.Element { 110 | return ( 111 |
112 | 117 | 118 | Alpha & Beta Tester 119 | 120 | 121 | 126 | 127 | Beta Tester 128 | 129 | 130 | 135 | 136 | Beta Tester 137 | 138 | 139 |
140 | ); 141 | } 142 | -------------------------------------------------------------------------------- /src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #6A77D7; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 90%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #6A77D7; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | 32 | .code-block-terminal-command:before { 33 | content: '$'; 34 | margin-right: 10px; 35 | } 36 | -------------------------------------------------------------------------------- /src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Link from '@docusaurus/Link'; 4 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 5 | import Layout from '@theme/Layout'; 6 | import HomepageFeatures from '@site/src/components/HomepageFeatures'; 7 | 8 | import styles from './index.module.css'; 9 | 10 | 11 | function HomepageHeader() { 12 | const {siteConfig} = useDocusaurusContext(); 13 | return ( 14 |
15 |
16 |

{siteConfig.title}

17 |

{siteConfig.tagline}

18 |
19 | 22 | Let's Start! 23 | 24 |
25 |
26 |
27 | ); 28 | } 29 | 30 | export default function Home(): JSX.Element { 31 | const {siteConfig} = useDocusaurusContext(); 32 | return ( 33 | 36 | 37 |
38 | 39 |
40 |
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/.nojekyll -------------------------------------------------------------------------------- /static/googlee5904fe980148e9b.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlee5904fe980148e9b.html 2 | -------------------------------------------------------------------------------- /static/img/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/img/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/android-chrome-512x512.png -------------------------------------------------------------------------------- /static/img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/apple-touch-icon.png -------------------------------------------------------------------------------- /static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/docusaurus.png -------------------------------------------------------------------------------- /static/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/favicon-16x16.png -------------------------------------------------------------------------------- /static/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/favicon-32x32.png -------------------------------------------------------------------------------- /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/logo.png -------------------------------------------------------------------------------- /static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /static/img/makinarocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlops-for-mle/tutorial/0a59b069f0e5305c990dcad2eb7fa1a3b2348553/static/img/makinarocks.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@tsconfig/docusaurus/tsconfig.json", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | --------------------------------------------------------------------------------