๊ฐ์
opensearch-py-ml์ OpenSearch๋ฅผ ์ํ Python ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ๋จธ์ ๋ฌ๋ ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. Eland์ ์ปค๋ฎค๋ํฐ ์ฃผ๋ ์คํ์์ค ํฌํฌ๋ก, Apache v2.0 ๋ผ์ด์ ์ค ํ์ ๋ฐฐํฌ๋๋ค.
Eland๊ฐ Elasticsearch ์ ์ฉ์ธ ๊ฒ๊ณผ ๋ฌ๋ฆฌ, opensearch-py-ml์ OpenSearch๋ฅผ ์ํด ํน๋ณํ ๊ฐ๋ฐ๋์์ผ๋ฉฐ OpenSearch์ ML Commons ํ๋ฌ๊ทธ์ธ๊ณผ ๊ธด๋ฐํ๊ฒ ํตํฉ๋์ด ์๋ค.
์ฃผ์ ๊ธฐ๋ฅ
1. DataFrame API
OpenSearch ์ธ๋ฑ์ค๋ฅผ Pandas DataFrame์ฒ๋ผ ๋ค๋ฃฐ ์ ์๋ API๋ฅผ ์ ๊ณตํ๋ค. Jupyter Notebook ํ๊ฒฝ์์ ๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ถ์ํ ์ ์๋ค.
ํน์ง:
- Pandas์ ์ ์ฌํ ์ธํฐํ์ด์ค
- OpenSearch์์ ์ง์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ํ
- ๋ณต์กํ ํํฐ๋ง ๋ฐ ์ง๊ณ ์ฐ์ฐ ์ง์
- ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ ์์ด ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
2. ML Commons ํตํฉ
OpenSearch์ ML Commons ํ๋ฌ๊ทธ์ธ๊ณผ ํตํฉํ์ฌ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ๊ด๋ฆฌํ๊ณ ์ฌ์ฉํ ์ ์๋ค.
์ง์ ๊ธฐ๋ฅ:
- ์ฌ์ ํ์ต๋ ๋ชจ๋ธ ๋ฑ๋ก
- ๋ชจ๋ธ ๋ฐฐํฌ ๋ฐ ์ธ๋ก๋
- ์๋ฒ ๋ฉ ์์ฑ ๋ฐ ์ถ๋ก
- ๋ชจ๋ธ ๊ทธ๋ฃน ๊ด๋ฆฌ
- ๋ชจ๋ธ ์ญ์
3. SentenceTransformer ์ง์
SentenceTransformer ๋ชจ๋ธ์ ์ ๋ก๋ํ๊ณ ํ์ตํ ์ ์๋ค.
๊ธฐ๋ฅ:
- Hugging Face์ SentenceTransformer ๋ชจ๋ธ ์ ๋ก๋
- ํฉ์ฑ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋ชจ๋ธ ํ์ธํ๋
- ํ ์คํธ ์๋ฒ ๋ฉ ์์ฑ
์ค์น
# opensearch-py-ml ์ค์น
pip install opensearch-py-ml
# OpenSearch Python ํด๋ผ์ด์ธํธ๋ ํจ๊ป ์ค์น๋จ
์๊ตฌ์ฌํญ:
- Python 3.x
- opensearch-py (์๋์ผ๋ก ์ค์น๋จ)
- OpenSearch ํด๋ฌ์คํฐ (1.x, 2.x ์ง์)
์ฌ์ฉ ์์
DataFrame์ผ๋ก ๋ฐ์ดํฐ ์กฐํ
from opensearchpy import OpenSearch
import opensearch_py_ml as oml
# OpenSearch ์ฐ๊ฒฐ
client = OpenSearch(
hosts=[{'host': 'localhost', 'port': 9200}],
http_auth=('admin', 'admin'),
use_ssl=True,
verify_certs=False
)
# DataFrame ์์ฑ
oml_df = oml.DataFrame(client, 'my-index')
# ๋ฐ์ดํฐ ์กฐํ
print(oml_df.head())
# ํํฐ๋ง ๋ฐ ์ง๊ณ
filtered = oml_df[oml_df['age'] > 30]
result = filtered.groupby('city').mean()
print(result)
Pandas์ ์ํธ ๋ณํ
import pandas as pd
import opensearch_py_ml as oml
# Pandas DataFrame์ OpenSearch์ ์ ์ฅ
pd_df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['Seoul', 'Busan', 'Incheon']
})
oml.pandas_to_opensearch(
pd_df,
client,
'users-index'
)
# OpenSearch์์ Pandas DataFrame์ผ๋ก ๋ณํ
oml_df = oml.DataFrame(client, 'users-index')
pd_df_result = oml.opensearch_to_pandas(oml_df)
์ฌ์ ํ์ต ๋ชจ๋ธ ๋ฑ๋ก
from opensearchpy import OpenSearch
import opensearch_py_ml as oml
# OpenSearch ํด๋ผ์ด์ธํธ ์์ฑ
client = OpenSearch(
hosts=[{'host': 'localhost', 'port': 9200}],
http_auth=('admin', 'admin')
)
# ML Commons ํด๋ผ์ด์ธํธ ์์ฑ
ml_client = oml.MLCommonClient(client)
# ์ฌ์ ํ์ต ๋ชจ๋ธ ๋ฑ๋ก
model_id = ml_client.register_pretrained_model(
model_name="huggingface/sentence-transformers/all-MiniLM-L6-v2",
model_version="1.0.0",
model_format="TORCH_SCRIPT",
deploy_model=True # ๋ฑ๋ก ํ ์๋ ๋ฐฐํฌ
)
print(f"Model registered with ID: {model_id}")
๋ชจ๋ธ ๋ฐฐํฌ ๋ฐ ์ธ๋ก๋
# ๋ชจ๋ธ ๋ฐฐํฌ (๋ฉ๋ชจ๋ฆฌ์ ๋ก๋)
task_id = ml_client.deploy_model(model_id)
# ๋ฐฐํฌ ์ํ ํ์ธ
task_info = ml_client.get_task_info(task_id)
print(f"Deployment status: {task_info['state']}")
# ๋ชจ๋ธ ์ ๋ณด ์กฐํ
model_info = ml_client.get_model_info(model_id)
print(model_info)
# ๋ชจ๋ธ ์ธ๋ก๋ (๋ฉ๋ชจ๋ฆฌ์์ ์ ๊ฑฐ)
ml_client.undeploy_model(model_id)
์๋ฒ ๋ฉ ์์ฑ
# ํ
์คํธ ์๋ฒ ๋ฉ ์์ฑ
sentences = [
"OpenSearch๋ ๊ฐ๋ ฅํ ๊ฒ์ ์์ง์
๋๋ค",
"๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ฝ๊ฒ ํตํฉํ ์ ์์ต๋๋ค"
]
embeddings = ml_client.generate_embedding(
model_id=model_id,
sentences=sentences
)
print(f"Generated {len(embeddings)} embeddings")
print(f"Embedding dimension: {len(embeddings[0])}")
๋ชจ๋ธ ๊ทธ๋ฃน ๊ด๋ฆฌ
# ๋ชจ๋ธ ๊ทธ๋ฃน ์์ฑ (OpenSearch 2.8+)
model_group_id = ml_client.register_model_group(
name="sentence-transformers",
description="Sentence transformer models for semantic search"
)
# ๋ชจ๋ธ ๊ทธ๋ฃน์ ๋ชจ๋ธ ๋ฑ๋ก
model_id = ml_client.register_pretrained_model(
model_name="huggingface/sentence-transformers/msmarco-distilbert-base-v4",
model_version="1.0.0",
model_format="TORCH_SCRIPT",
model_group_id=model_group_id
)
๋ชจ๋ธ ์ญ์
# ๋ชจ๋ธ ์ญ์ (์ธ๋ก๋ ํ ์๊ตฌ ์ญ์ )
ml_client.delete_model(model_id)
print(f"Model {model_id} deleted")
์ฃผ์ ํ์ฉ ์ฌ๋ก
1. ์๋งจํฑ ๊ฒ์
SentenceTransformer ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์๋ฏธ ๊ธฐ๋ฐ ๊ฒ์์ ๊ตฌํํ ์ ์๋ค.
# 1. ๋ชจ๋ธ ๋ฑ๋ก ๋ฐ ๋ฐฐํฌ
model_id = ml_client.register_pretrained_model(
model_name="huggingface/sentence-transformers/all-MiniLM-L6-v2",
model_version="1.0.0",
model_format="TORCH_SCRIPT",
deploy_model=True
)
# 2. ๋ฌธ์ ์๋ฒ ๋ฉ ์์ฑ ๋ฐ ์ธ๋ฑ์ฑ
documents = [
"Python is a programming language",
"OpenSearch is a search engine",
"Machine learning helps computers learn"
]
embeddings = ml_client.generate_embedding(model_id, documents)
# 3. ๊ฒ์ ์ ์ฟผ๋ฆฌ ์๋ฒ ๋ฉ ์์ฑํ์ฌ ์ ์ฌ๋ ๊ฒ์
query = "What is a search tool?"
query_embedding = ml_client.generate_embedding(model_id, [query])[0]
2. ๋์ฉ๋ ๋ก๊ทธ ๋ถ์
OpenSearch์ ์ ์ฅ๋ ๋์ฉ๋ ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ Pandas์ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ๋ถ์ํ ์ ์๋ค.
# ๋ก๊ทธ ๋ฐ์ดํฐ ์กฐํ
logs_df = oml.DataFrame(client, 'logs-2024-*')
# ์๋ฌ ๋ก๊ทธ ํํฐ๋ง
error_logs = logs_df[logs_df['level'] == 'ERROR']
# ์๊ฐ๋๋ณ ์๋ฌ ์ง๊ณ
hourly_errors = error_logs.groupby(
pd.Grouper(key='timestamp', freq='1H')
).size()
print(hourly_errors)
3. ์ถ์ฒ ์์คํ
์ฌ์ฉ์์ ์์ดํ ์ ์๋ฒ ๋ฉํ์ฌ ์ถ์ฒ ์์คํ ์ ๊ตฌ์ถํ ์ ์๋ค.
# ์ฌ์ฉ์ ํ๋กํ ์๋ฒ ๋ฉ
user_profiles = [
"User likes action movies and sci-fi",
"User prefers comedy and romance"
]
user_embeddings = ml_client.generate_embedding(model_id, user_profiles)
# ์์ดํ
(์ํ) ์ค๋ช
์๋ฒ ๋ฉ
movie_descriptions = [
"Action-packed space adventure",
"Romantic comedy about love"
]
movie_embeddings = ml_client.generate_embedding(model_id, movie_descriptions)
# ์ฝ์ฌ์ธ ์ ์ฌ๋๋ก ์ถ์ฒ
4. ETL ํ์ดํ๋ผ์ธ
๋ค์ํ ๋ฐ์ดํฐ ์์ค์์ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ์ฌ OpenSearch๋ก ๋ก๋ํ ์ ์๋ค.
import pandas as pd
import opensearch_py_ml as oml
# CSV ํ์ผ ์ฝ๊ธฐ
df = pd.read_csv('data.csv')
# ๋ฐ์ดํฐ ๋ณํ
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['category'] = df['category'].str.lower()
# OpenSearch์ ๋ก๋
oml.pandas_to_opensearch(
df,
client,
'processed-data',
chunk_size=1000
)
Eland์์ ๋น๊ต
์ธก๋ฉด | Eland | opensearch-py-ml |
---|---|---|
๋์ ํ๋ซํผ | Elasticsearch | OpenSearch |
๋ผ์ด์ ์ค | Elastic License 2.0 | Apache 2.0 |
๊ฐ๋ฐ ์ฃผ์ฒด | Elastic | OpenSearch Community |
ML ํ๋ฌ๊ทธ์ธ | Elasticsearch ML | ML Commons |
๋ชจ๋ธ ๋ฐฐํฌ | Hugging Face Hub ์ง์ ํตํฉ | ML Commons API ์ฌ์ฉ |
์ง์ ๋ฒ์ | Elasticsearch 8+ | OpenSearch 1.x, 2.x, 3.x |
DataFrame API | Pandas ์คํ์ผ | Pandas ์คํ์ผ (์ ์ฌ) |
๋ฒ์ ํธํ์ฑ
OpenSearch ๋ฒ์ ์ง์
opensearch-py-ml์ opensearch-py ํด๋ผ์ด์ธํธ์ ์์กดํ๋ฏ๋ก, ํด๋น ํด๋ผ์ด์ธํธ์ ํธํ์ฑ์ ๋ฐ๋ฅธ๋ค.
ํธํ์ฑ ๋งคํธ๋ฆญ์ค:
opensearch-py-ml ๋ฒ์ | OpenSearch ๋ฒ์ | ๋น๊ณ |
---|---|---|
1.0.0 | 2.4.0 | ๊ณต์ ํธํ์ฑ ๋งคํธ๋ฆญ์ค์ ๋ช ์ |
1.3.0 (์ต์ ) | 1.x, 2.x, 3.x | opensearch-py 3.x ์์กด์ฑ์ ํตํด ์ง์ |
๋ฒ์ ๋ณ ์ฃผ์ ๊ธฐ๋ฅ:
- OpenSearch 1.x: DataFrame API, ๊ธฐ๋ณธ ML ๋ชจ๋ธ ์ ๋ก๋
- OpenSearch 2.x: ML Commons ๊ณ ๊ธ ๊ธฐ๋ฅ, ๋ชจ๋ธ ๊ทธ๋ฃน (2.8+)
- OpenSearch 3.x: opensearch-py 3.x์ ํจ๊ป ํธํ (๋จ, 3.0์์ ์ ๊ฑฐ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉ ๋ถ๊ฐ)
์ฐธ๊ณ ์ฌํญ:
- opensearch-py 3.x.x๋ OpenSearch 1.0.0-3.x๋ฅผ ์ง์
- OpenSearch ์ฃผ์ ๋ฒ์ ์ ๊ทธ๋ ์ด๋ ์ ์ ๊ฑฐ๋ ๊ธฐ๋ฅ์ด ์์ ์ ์์ผ๋ฏ๋ก ๋ฆด๋ฆฌ์ค ๋ ธํธ ํ์ธ ํ์
- ์ต์ ๋ฒ์ ํธํ์ฑ์ opensearch-py COMPATIBILITY.md ์ฐธ๊ณ
Python ๋ฒ์
- Python 3.7+
- ๊ถ์ฅ: Python 3.9 ์ด์
์์กด์ฑ
- opensearch-py: OpenSearch Python ํด๋ผ์ด์ธํธ
- pandas: DataFrame ์กฐ์
- numpy: ์์น ์ฐ์ฐ
์ ์ฝ์ฌํญ
- Pandas API ๋ถ๋ถ ํธํ: ๋ชจ๋ Pandas ๊ธฐ๋ฅ์ ์ง์ํ์ง ์์
- ML Commons ์์กด์ฑ: ML ๊ธฐ๋ฅ์ ML Commons ํ๋ฌ๊ทธ์ธ ์ค์น ํ์
- OpenSearch ์ ์ฉ: Elasticsearch์ ํธํ๋์ง ์์
- ๋ฌธ์ ๋ถ์กฑ: Eland์ ๋นํด ๋ฌธ์์ ์์ ๊ฐ ์ ์
ML Commons ์ค์
ML ๋ชจ๋ธ์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ OpenSearch ํด๋ฌ์คํฐ์์ ํน์ ์ค์ ์ ํ์ฑํํด์ผ ํ๋ค:
# ์ธ๋ถ URL์์ ๋ชจ๋ธ ๋ฑ๋ก ํ์ฉ
PUT _cluster/settings
{
"persistent": {
"plugins.ml_commons.allow_registering_model_via_url": true
}
}
# ๋ก์ปฌ ํ์ผ์์ ๋ชจ๋ธ ๋ฑ๋ก ํ์ฉ
PUT _cluster/settings
{
"persistent": {
"plugins.ml_commons.allow_registering_model_via_local_file": true
}
}