서비스 한도 증설 요청 방법은 아래 포스팅을 참고해주세요 OCI 지원 요청(SR)을 위해 지원 티켓을 오픈하여 지원받는 방법
OCI AI Quick Action(AQUA)를 사용하기 위해서는 동적그룹 및 정책을 생성해야 합니다. OCI 에서는 이러한 작업을 간편하게 수행할 수 있도록 Terraform 스크립트를 제공하고 있습니다. 아래 내용을 순서대로 진행하여 정책을 적용합니다.
Note: 이미 Data Science 서비스를 사용할수 있는 정책이 작성되어 있더라도 Terraform 구성 파일을 사용하여 ORM 스택을 통해 AI Quick Actions에서 사용할 정책을 설정하기 위한 정책이 필요합니다.
allow group <your_admin_group> to manage orm-stacks in TENANCY
allow group <your_admin_group> to manage orm-jobs in TENANCY
allow group <your_admin_group> to manage dynamic-groups in TENANCY
allow group <your_admin_group> to manage policies in TENANCY
allow group <your_admin_group> to read compartments in TENANCY
아래 동적 그룹 및 정책을 단계별로 생성 합니다. 이러한 정책과 동적 그룹은 사용자의 OCI 환경 내에서 AI Quick Action을 가능하게 하기 위해 필요한 권한을 설정합니다. “
aqua-dynamic-group
any {all {resource.type='datasciencenotebooksession', resource.compartment.id='<your_compartment_ocid>'}, all {resource.type='datasciencemodeldeployment',resource.compartment.id='<your_compartment_ocid>'}, all {resource.type='datasciencejobrun', resource.compartment.id='<your_compartment_ocid>'}}
distributed_training_job_runs
any {all {resource.type='datasciencejobrun', resource.compartment.id='<your_compartment_ocid>'}}
aqua_policies
Define tenancy datascience as ocid1.tenancy.oc1..aaaaaaaax5hdic7ya6r5rxsgpifff4l6xdxzltnrncdzp3m75ubbvzqqzn3q
Endorse any-user to read data-science-models in tenancy datascience where ALL {target.compartment.name='service-managed-models'}
Endorse any-user to inspect data-science-models in tenancy datascience where ALL {target.compartment.name='service-managed-models'}
Endorse any-user to read object in tenancy datascience where ALL {target.compartment.name='service-managed-models', target.bucket.name='service-managed-models'}
Allow dynamic-group aqua-dynamic-group to manage data-science-model-deployments in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to manage data-science-models in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to use logging-family in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to manage data-science-jobs in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to manage data-science-job-runs in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to use virtual-network-family in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to read resource-availability in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to manage data-science-projects in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to manage data-science-notebook-sessions in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to manage data-science-modelversionsets in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to read buckets in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to read objectstorage-namespaces in compartment <your-compartment-name>
Allow dynamic-group aqua-dynamic-group to inspect compartments in tenancy
Allow dynamic-group aqua-dynamic-group to manage object-family in compartment <your-compartment-name> where any {target.bucket.name='<your-bucket-name>'}
dt_jr_policies
Allow dynamic-group distributed_training_job_runs to use logging-family in compartment <your-compartment-name>
Allow dynamic-group distributed_training_job_runs to manage data-science-models in compartment <your-compartment-name>
Allow dynamic-group distributed_training_job_runs to read data-science-jobs in compartment <your-compartment-name>
Allow dynamic-group distributed_training_job_runs to manage objects in compartment <your-compartment-name> where any {target.bucket.name='<your-bucket-name>'}
Allow dynamic-group distributed_training_job_runs to read buckets in compartment <your-compartment-name> where any {target.bucket.name='<your-bucket-name>'}
OCI AQUA는 Data Science 노트북 세션을 기반으로 동작합니다. 정책이 모두 작성된 이후 기존 세션을 비활성화/활성화 하거나, 새로운 세션을 생성하여 AI Quick Action을 활성화 할 수 있습니다.
OCI AQUA 에서는 Fine-Tune 작업에 필요한 데이터셋을 Object Storage 또는 노트북 세션에서 불러와서 작업을 생성할 수 있습니다. 만약 Fine-tune 작업을 염두하고 있다면 Output 버킷은 객체 버전 지정
을 활성화 해야 합니다.
만약 버킷을 이미 생성하였다면 객체 버전 지정
편집 버튼을 통해 활성화 해야 합니다.
OCI AQUA 에서 Fine-Tune 작업을 수행하기 위해서는 학습에 필요한 데이터셋을 준비해야 합니다.
주의 사항
{"prompt":"<s>[INST]<<SYS>>[모델에게 지시할 내용]<</SYS>>[질문 내용][\/INST]","completion":"[답변 내용]","category": null}
{"prompt":"<s>[INST]<<SYS>>당신은 클라우드 전문가입니다. 도움이 되고 상세하며 정확한 답변을 제공합니다.<</SYS>>OCI 가상머신 서비스에 대해서 설명해줘[\/INST]","completion":"가상 머신(VM)은 소규모 개발 프로젝트에서 실시간 통신 플랫폼과 같은 대규모 글로벌 애플리케이션에 이르는 워크로드를 위해 클라우드에서 안전하고 탄력적인 컴퓨팅 용량을 제공합니다. 유연한 모양을 통해 사용자는 가격 대비 성능을 향상시키기 위해 맞춤형 프로세서 및 메모리 값으로 VM 리소스를 최적화할 수 있습니다.","category": null}
노트북 세션에 접속 후 런처 화면의 AI Quick Action 메뉴를 클릭하여 AQUA 서비스를 사용할 수 있습니다.
AQUA에서는 GPU A10 자원을 활용하여 모델을 배포합니다. 모델 크기에 따라 A10 GPU를 최소 1장~4장까지 사용할 수 있습니다.
Deploy
버튼을 클릭합니다. AQUA에서 모델을 미세조정(Fine-tune)하기 위해서는 A10 GPU를 최소 2장~4장까지 사용할 수 있습니다. 충분한 리소스가 있는지 미리 확인이 필요합니다.
Fine Tune
버튼을 클릭합니다. 미세조정 학습이 완료된 모델은 Fine-tuned models 탭에서 확인할 수 있습니다. 목록의 모델 중 Ready to Deploy
뱃지가 활성화된 모델만 배포할 수 있습니다.
Deploy
버튼을 클릭합니다. 배포한 모델이 기대하고 있는 답변을 생성하는지 간편하게 확인할 수 있도록 모델 평가 작업을 생성하여 확인할 수 있습니다. 평가에 필요한 데이터셋은 평가하고자 하는 질문, 답변을 데이터셋 포멧에 맞게 준비하거나, 학습에 사용된 데이터 중 일부 데이터를 샘플링하여 사용할 수 있습니다.
Create Evaluation
버튼을 클릭합니다. oci raw-request --http-method POST --target-uri https://modeldeployment.us-ashburn-1.oci.oc-test.com/ocid1.datasciencemodeldeployment.oc1.iad.xxxxxxxxx/predict --request-body '{
"model": "odsc-llm",
"prompt":"what are activation functions?",
"max_tokens":250,
"temperature": 0.7,
"top_p":0.8,
}' --auth <auth_method>
Note: Currently oci-cli
does not support streaming response, use Python or Java SDK instead.
# The OCI SDK must be installed for this example to function properly.
# Installation instructions can be found here: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/pythonsdk.htm
import requests
import oci
from oci.signer import Signer
from oci.config import from_file
config = from_file('~/.oci/config')
auth = Signer(
tenancy=config['tenancy'],
user=config['user'],
fingerprint=config['fingerprint'],
private_key_file_location=config['key_file'],
pass_phrase=config['pass_phrase']
)
# For security token based authentication
# token_file = config['security_token_file']
# token = None
# with open(token_file, 'r') as f:
# token = f.read()
# private_key = oci.signer.load_private_key_from_file(config['key_file'])
# auth = oci.auth.signers.SecurityTokenSigner(token, private_key)
endpoint = "https://modeldeployment.us-ashburn-1.oci.oc-test.com/ocid1.datasciencemodeldeployment.oc1.iad.xxxxxxxxx/predict"
body = {
"model": "odsc-llm", # this is a constant
"prompt": "what are activation functions?",
"max_tokens": 250,
"temperature": 0.7,
"top_p": 0.8,
}
res = requests.post(endpoint, json=body, auth=auth, headers={}).json()
print(res)
To consume streaming Server-sent Events (SSE), install sseclient-py using pip install sseclient-py
.
# The OCI SDK must be installed for this example to function properly.
# Installation instructions can be found here: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/pythonsdk.htm
import requests
import oci
from oci.signer import Signer
from oci.config import from_file
import sseclient # pip install sseclient-py
config = from_file('~/.oci/config')
auth = Signer(
tenancy=config['tenancy'],
user=config['user'],
fingerprint=config['fingerprint'],
private_key_file_location=config['key_file'],
pass_phrase=config['pass_phrase']
)
# For security token based authentication
# token_file = config['security_token_file']
# token = None
# with open(token_file, 'r') as f:
# token = f.read()
# private_key = oci.signer.load_private_key_from_file(config['key_file'])
# auth = oci.auth.signers.SecurityTokenSigner(token, private_key)
endpoint = "https://modeldeployment.us-ashburn-1.oci.oc-test.com/ocid1.datasciencemodeldeployment.oc1.iad.xxxxxxxxx/predict"
body = {
"model": "odsc-llm", # this is a constant
"prompt": "what are activation functions?",
"max_tokens": 250,
"temperature": 0.7,
"top_p": 0.8,
"stream": True,
}
headers={'Content-Type':'application/json','enable-streaming':'true', 'Accept': 'text/event-stream'}
response = requests.post(endpoint, json=body, auth=auth, stream=True, headers=headers)
print(response.headers)
client = sseclient.SSEClient(response)
for event in client.events():
print(event.data)
# Alternatively, we can use the below code to print the response.
# for line in response.iter_lines():
# if line:
# print(line)
/**
* The OCI SDK must be installed for this example to function properly.
* Installation instructions can be found here: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/javasdk.htm
*/
package org.example;
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
import com.oracle.bmc.auth.SessionTokenAuthenticationDetailsProvider;
import com.oracle.bmc.http.ClientConfigurator;
import com.oracle.bmc.http.Priorities;
import com.oracle.bmc.http.client.HttpClient;
import com.oracle.bmc.http.client.HttpClientBuilder;
import com.oracle.bmc.http.client.HttpRequest;
import com.oracle.bmc.http.client.HttpResponse;
import com.oracle.bmc.http.client.Method;
import com.oracle.bmc.http.client.jersey.JerseyHttpProvider;
import com.oracle.bmc.http.client.jersey.sse.SseSupport;
import com.oracle.bmc.http.internal.ParamEncoder;
import com.oracle.bmc.http.signing.RequestSigningFilter;
import javax.ws.rs.core.MediaType;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class RestExample {
public static void main(String[] args) throws Exception {
String configurationFilePath = "~/.oci/config";
String profile = "DEFAULT";
// Pre-Requirement: Allow setting of restricted headers. This is required to allow the SigningFilter
// to set the host header that gets computed during signing of the request.
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
final AuthenticationDetailsProvider provider =
new SessionTokenAuthenticationDetailsProvider(configurationFilePath, profile);
// 1) Create a request signing filter instance using SessionTokenAuth Provider.
RequestSigningFilter requestSigningFilter = RequestSigningFilter.fromAuthProvider(
provider);
// 1) Alternatively, RequestSigningFilter can be created from a config file.
// RequestSigningFilter requestSigningFilter = RequestSigningFilter.fromConfigFile(configurationFilePath, profile);
// 2) Create a Jersey client and register the request signing filter.
// Refer to this page https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/javasdkexamples.htm for information regarding the compatibility of the HTTP client(s) with OCI SDK version.
HttpClientBuilder builder = JerseyHttpProvider.getInstance()
.newBuilder()
.registerRequestInterceptor(Priorities.AUTHENTICATION, requestSigningFilter)
.baseUri(
URI.create(
"${modelDeployment.modelDeploymentUrl}/")
+ ParamEncoder.encodePathParam("predict"));
// 3) Create a request and set the expected type header.
String jsonPayload = "{}"; // Add payload here with respect to your model example shown in next line:
// 4) Setup Streaming request
Function<InputStream, List<String>> generateTextResultReader = getInputStreamListFunction();
SseSupport sseSupport = new SseSupport(generateTextResultReader);
ClientConfigurator clientConfigurator = sseSupport.getClientConfigurator();
clientConfigurator.customizeClient(builder);
try (HttpClient client = builder.build()) {
HttpRequest request = client
.createRequest(Method.POST)
.header("accepts", MediaType.APPLICATION_JSON)
.header("content-type", MediaType.APPLICATION_JSON)
.header("enable-streaming", "true")
.body(jsonPayload);
// 5) Invoke the call and get the response.
HttpResponse response = request.execute().toCompletableFuture().get();
// 6) Print the response headers and body
Map<String, List<String>> responseHeaders = response.headers();
System.out.println("HTTP Headers " + responseHeaders);
InputStream responseBody = response.streamBody().toCompletableFuture().get();
try (
final BufferedReader reader = new BufferedReader(
new InputStreamReader(responseBody, StandardCharsets.UTF_8)
)
) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (Exception ex) {
throw ex;
}
}
private static Function<InputStream, List<String>> getInputStreamListFunction() {
Function<InputStream, List<String>> generateTextResultReader = entityStream -> {
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(entityStream))) {
String line;
List<String> generatedTextList = new ArrayList<>();
while ((line = reader.readLine()) != null) {
if (line.isEmpty() || line.startsWith(":")) {
continue;
}
generatedTextList.add(line);
}
return generatedTextList;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
return generateTextResultReader;
}
}
만약 모델을 배포하거나, Fine-tune 작업을 실행하다고 오류가 발생한 경우 작업 생성 시 지정한 로깅 서비스에서 확인하거나, Notebook 세션에서 Terminal 기능에서 아래 명령어를 통해 jobrun 로그를 확인할 수 있습니다.
ads opctl watch [jobrun-ocid] --auth resource_principal
A10 리소스는 중지할 경우 비용이 발생하지 않기 때문에 비용을 절감하기 위해서 사용하지 않을 때에는 모델 배치를 비활성화 하여 리소스를 중지할 수 있습니다.
이 글은 개인적으로 얻은 지식과 경험을 작성한 글로 내용에 오류가 있을 수 있습니다. 또한 글 속의 의견은 개인적인 의견으로 특정 회사를 대변하지 않습니다.
Younghwan Cho AIML
oci data science generative ai gen ai aqua ai quick action ai llm