注意:
- 本教程需要访问 Oracle Cloud。要注册免费账户,请参阅开始使用 Oracle Cloud Infrastructure 免费套餐。
- 它对 Oracle Cloud Infrastructure 身份证明、租户和区间使用示例值。完成实验室后,请使用特定于云环境的那些值替换这些值。
使用 Oracle Resource Manager 使用 One Click Deployment 在 OCI Compute A10.2 实例上运行 Elyza LLM 模型
简介
Oracle Cloud Infrastructure (OCI) Compute 支持您创建不同类型的配置,以测试本地部署的人工智能 (AI) 模型的图形处理单元 (GPU)。在本教程中,我们将 A10.2 配置与预先存在的 VCN 和子网资源结合使用,您可以从 Oracle 资源管理器中选择这些资源。
Terraform 代码还包括将实例配置为为自然语言处理任务运行本地虚拟大语言模型 (vLLM) Elyza 模型。
目标
- 在 OCI Compute 上创建 A10.2 配置,下载 Elyza LLM 模型并查询本地 vLLM 模型。
先决条件
-
确保您具有 OCI 虚拟云网络 (VCN) 和将部署虚拟机 (VM) 的子网。
-
了解网络组件及其关系。有关更多信息,请参见 Networking Overview 。
-
了解云中的网络。有关详细信息,请观看以下视频:云中的网络视频 EP.01:虚拟云网络。
-
要求:
- 实例类型:具有两个 Nvidia GPU 的 A10.2 配置。
- 操作系统:Oracle Linux。
- 映像选择:部署脚本选择支持 GPU 的最新 Oracle Linux 映像。
- 标记:添加自由格式标记 GPU_TAG = "A10-2"。
- 引导卷大小: 250GB。
- 初始化:使用 cloud-init 下载和配置 vLLM Elyza 模型。
任务 1:下载用于一键部署的 Terraform 代码
从以下位置下载 ORM Terraform 代码: orm_stack_a10_2_gpu_elyza_models.zip ,以在本地实施 Elyza vLLM 模型,从而允许您选择现有 VCN 和子网以测试 Elyza vLLM 模型在 A10.2 实例配置中的本地部署。
在本地下载 ORM Terraform 代码后,请按照以下步骤操作:从文件夹创建堆栈上载堆栈并执行 Terraform 代码应用。
注:请确保已创建 OCI 虚拟云网络 (VCN) 和将部署 VM 的子网。
任务 2:在 OCI 上创建 VCN(如果尚未创建,则为可选)
要在 Oracle Cloud Infrastructure 中创建 VCN,请参阅:视频了解如何在 OCI 上创建虚拟云网络
或者
要创建 VCN,请执行以下操作:
-
登录到 OCI 控制台,输入云租户名称、用户名和密码。
-
单击左上角的汉堡菜单(≡)。
-
转到网络、虚拟云网络,然后从列表范围部分中选择适当的区间。
-
选择 VCN with Internet Connectivity ,然后单击 Start VCN Wizard(启动 VCN 向导)。
-
在创建具有 Internet 连接的 VCN 页中,输入以下信息并单击下一步。
- VCN 名称:输入
OCI_HOL_VCN
。 - COMPARTMENT(COMPARTMENT):选择相应的区间。
- VCN CIDR 块:输入
10.0.0.0/16
。 - PUBLIC SUBNET CIDR BLOCK:输入
10.0.2.0/24
。 - PRIVATE SUBNET CIDR BLOCK:输入
10.0.1.0/24
。 - DNS 解析:选择 USE DNS HOSTNAMES IN THIS VCN 。
- VCN 名称:输入
-
在复查页中,复查您的设置,然后单击创建。
创建 VCN 需要一些时间,而进度屏幕会让您随时了解工作流。
-
创建 VCN 后,单击查看虚拟云网络。
在实际情况下,您将根据访问需求(要打开哪些端口)以及谁可以访问这些 VCN 来创建多个 VCN。
任务 3:请参见 cloud-init 配置详细信息
cloud-init
脚本将安装所有必需的依赖项,启动 Docker,下载并启动 vLLM Elyza 模型。您可以在任务 1 中下载的 cloudinit.sh
文件中找到以下代码。
dnf install -y dnf-utils zip unzip
dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
dnf remove -y runc
dnf install -y docker-ce --nobest
systemctl enable docker.service
dnf install -y nvidia-container-toolkit
systemctl start docker.service
...
Cloud-init 将下载运行 Elyza 模型所需的所有文件,并且不需要在 Hugging Face 中预定义的 API 令牌。在任务 6 中使用 Docker 启动 Elyza 模型需要 API 标记。
任务 4:监视系统
使用以下命令(如果需要)跟踪 Cloud-init 完成情况和 GPU 资源使用情况。
-
监视 cloud-init 完成:
tail -f /var/log/cloud-init-output.log
。 -
监视 GPU 使用率:
nvidia-smi dmon -s mu -c 100 --id 0,1
。 -
使用 Python 部署 vLLM Elyza 模型并与之交互:(仅在需要时更改参数 - 该命令已包含在
cloud-init
脚本中):python -O -u -m vllm.entrypoints.api_server \ --host 0.0.0.0 \ --port 8000 \ --model /home/opc/models/${MODEL} \ --tokenizer hf-internal-testing/llama-tokenizer \ --enforce-eager \ --max-num-seqs 1 \ --tensor-parallel-size 2 \ >> /home/opc/${MODEL}.log 2>&1
任务 5:测试模型集成
使用命令或 Jupyter Notebook 详细信息通过以下方式与模型交互。
-
在 cloud-init 完成后,从命令行界面 (Command Line Interface,CLI) 测试模型。
curl -X POST "http://0.0.0.0:8000/generate" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -d '{"prompt": "Write a humorous limerick about the wonders of GPU computing.", "max_tokens": 64, "temperature": 0.7, "top_p": 0.9}'
-
从 Jupyter Notebook 测试模型(确保打开端口
8888
)。import requests import json url = "http://0.0.0.0:8000/generate" headers = { "accept": "application/json", "Content-Type": "application/json", } data = { "prompt": "Write a short conclusion.", "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 } response = requests.post(url, headers=headers, json=data) if response.status_code == 200: result = response.json() # Pretty print the response for better readability formatted_response = json.dumps(result, indent=4) print("Response:", formatted_response) else: print("Request failed with status code:", response.status_code) print("Response:", response.text)
-
将 Gradio 与聊天机器人集成以查询模型。
import requests import gradio as gr import os # Function to interact with the model via API def interact_with_model(prompt): url = 'http://0.0.0.0:8000/generate' headers = { "accept": "application/json", "Content-Type": "application/json", } data = { "prompt": prompt, "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 } response = requests.post(url, headers=headers, json=data) if response.status_code == 200: result = response.json() completion_text = result["text"][0].strip() # Extract the generated text return completion_text else: return {"error": f"Request failed with status code {response.status_code}"} # Retrieve the MODEL environment variable model_name = os.getenv("MODEL") # Example Gradio interface iface = gr.Interface( fn=interact_with_model, inputs=gr.Textbox(lines=2, placeholder="Write a prompt..."), outputs=gr.Textbox(type="text", placeholder="Response..."), title=f"{model_name} Interface", # Use model_name to dynamically set the title description=f"Interact with the {model_name} deployed locally via Gradio.", # Use model_name to dynamically set the description live=True ) # Launch the Gradio interface iface.launch(share=True)
任务 6:使用 Docker 部署模型(如果需要)
或者,使用 Docker 为封装环境部署模型:
-
来自外部源的模型。
docker run --gpus all \ --env "HUGGING_FACE_HUB_TOKEN=$TOKEN_ACCESS" \ -p 8000:8000 \ --ipc=host \ --restart always \ vllm/vllm-openai:latest \ --tensor-parallel-size 2 \ --model elyza/$MODEL
-
使用已下载的本地文件通过 docker 运行的模型(启动速度更快)。
docker run --gpus all \ -v /home/opc/models/$MODEL/:/mnt/model/ \ --env "HUGGING_FACE_HUB_TOKEN=$TOKEN_ACCESS" \ -p 8000:8000 \ --env "TRANSFORMERS_OFFLINE=1" \ --env "HF_DATASET_OFFLINE=1" \ --ipc=host vllm/vllm-openai:latest \ --model="/mnt/model/" \ --tensor-parallel-size 2
可以通过以下方式查询模型:
-
从 CLI 查询使用 Docker 启动的模型(需要进一步注意):
-
模型从外部源使用 Docker 启动。
(elyza) [opc@a10-2-gpu ~]$ curl -X 'POST' 'http://0.0.0.0:8000/v1/chat/completions' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "model": "elyza/'${MODEL}'", "messages": [{"role": "user", "content": "Write a humorous limerick about the wonders of GPU computing."}], "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 }'
-
使用 Docker 在本地启动模型。
curl -X 'POST' 'http://0.0.0.0:8000/v1/chat/completions' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{ "model": "/mnt/model/", "messages": [{"role": "user", "content": "Write a humorous limerick about the wonders of GPU computing."}], "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 }'
-
-
从 Jupyter Notebook 查询 Docker 启动的模型。
-
模型从 Docker Hub 启动。
import requests import json import os url = "http://0.0.0.0:8000/v1/chat/completions" headers = { "accept": "application/json", "Content-Type": "application/json", } # Assuming `MODEL` is an environment variable set appropriately model = f"elyza/{os.getenv('MODEL')}" data = { "model": model, "messages": [{"role": "user", "content": "Write a humorous limerick about the wonders of GPU computing."}], "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 } response = requests.post(url, headers=headers, json=data) if response.status_code == 200: result = response.json() # Extract the generated text from the response completion_text = result["choices"][0]["message"]["content"].strip() print("Generated Text:", completion_text) else: print("Request failed with status code:", response.status_code) print("Response:", response.text)
-
容器通过 Docker 在本地启动。
import requests import json import os url = "http://0.0.0.0:8000/v1/chat/completions" headers = { "accept": "application/json", "Content-Type": "application/json", } # Assuming `MODEL` is an environment variable set appropriately model = f"/mnt/model/" # Adjust this based on your specific model path or name data = { "model": model, "messages": [{"role": "user", "content": "Write a humorous limerick about the wonders of GPU computing."}], "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 } response = requests.post(url, headers=headers, json=data) if response.status_code == 200: result = response.json() # Extract the generated text from the response completion_text = result["choices"][0]["message"]["content"].strip() print("Generated Text:", completion_text) else: print("Request failed with status code:", response.status_code) print("Response:", response.text)
-
-
使用与聊天机器人集成的 Gradio 查询 Docker 启动的模型。
-
模型从外部源使用 Docker 启动。
import requests import gradio as gr import os # Function to interact with the model via API def interact_with_model(prompt): url = 'http://0.0.0.0:8000/v1/chat/completions' # Update the URL to match the correct endpoint headers = { "accept": "application/json", "Content-Type": "application/json", } # Assuming `MODEL` is an environment variable set appropriately model = f"elyza/{os.getenv('MODEL')}" data = { "model": model, "messages": [{"role": "user", "content": prompt}], # Use the user-provided prompt "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 } response = requests.post(url, headers=headers, json=data) if response.status_code == 200: result = response.json() completion_text = result["choices"][0]["message"]["content"].strip() # Extract the generated text return completion_text else: return {"error": f"Request failed with status code {response.status_code}"} # Retrieve the MODEL environment variable model_name = os.getenv("MODEL") # Example Gradio interface iface = gr.Interface( fn=interact_with_model, inputs=gr.Textbox(lines=2, placeholder="Write a prompt..."), outputs=gr.Textbox(type="text", placeholder="Response..."), title=f"{model_name} Interface", # Use model_name to dynamically set the title description=f"Interact with the {model_name} model deployed locally via Gradio.", # Use model_name to dynamically set the description live=True ) # Launch the Gradio interface iface.launch(share=True)
-
使用 Gradio 通过 Docker 在本地启动容器
import requests import gradio as gr import os # Function to interact with the model via API def interact_with_model(prompt): url = 'http://0.0.0.0:8000/v1/chat/completions' # Update the URL to match the correct endpoint headers = { "accept": "application/json", "Content-Type": "application/json", } # Assuming `MODEL` is an environment variable set appropriately model = "/mnt/model/" # Adjust this based on your specific model path or name data = { "model": model, "messages": [{"role": "user", "content": prompt}], "max_tokens": 64, "temperature": 0.7, "top_p": 0.9 } response = requests.post(url, headers=headers, json=data) if response.status_code == 200: result = response.json() completion_text = result["choices"][0]["message"]["content"].strip() return completion_text else: return {"error": f"Request failed with status code {response.status_code}"} # Example Gradio interface iface = gr.Interface( fn=interact_with_model, inputs=gr.Textbox(lines=2, placeholder="Write a humorous limerick about the wonders of GPU computing."), outputs=gr.Textbox(type="text", placeholder="Response..."), title="Model Interface", # Set your desired title here description="Interact with the model deployed locally via Gradio.", live=True ) # Launch the Gradio interface iface.launch(share=True)
注:用于打开 Jupyter Notebook 的
8888
端口的防火墙命令。sudo firewall-cmd --zone=public --permanent --add-port 8888/tcp sudo firewall-cmd --reload sudo firewall-cmd --list-all
-
确认
-
作者 — Bogdan Bazarca(高级云工程师)
-
贡献者 — Oracle NACI-AI-CN-DEV 团队
更多学习资源
浏览 docs.oracle.com/learn 上的其他实验室,或者访问 Oracle Learning YouTube 渠道上的更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Run Elyza LLM Model on OCI Compute A10.2 Instance with Oracle Resource Manager using One Click Deployment
G11830-01
July 2024