The page has been translated by Gen AI.

RAG

Building a Personalized RAG Based on SCP Service Information

Build a lightweight RAG (Retrieval-Augmented Generation) application that uses Simple AI Inference and OpenSearch running in a VM to search SCP service information and generate recommended answers based on virtual user profiles. It uses only a Python application, JSONL service documentation, and JSON user profiles, without a separate database or web UI.

Reference
The service name uses the actual SCP service name. The service description, user profile, and recommended answers are simplified examples for tutorial purposes. Please refer to the service-specific documentation for details on actual availability and features.

Architecture

The following flow retrieves SCP service information and generates a response.

Personalized RAG architecture based on SCP service information
Figure. Personalized RAG architecture based on SCP service information

index_products.py generates vectors for service documents and indexes them in OpenSearch, while ask.py generates question vectors, performs KNN search, selects personalized documents, and calls the Chat Completions API.

From the OpenSearch KNN search results, prioritize the preferred categories from the user profile for up to 8 candidate documents, and use up to 3 documents in the response. User profiles are virtual data that only have preferred categories and usage purposes.

Prerequisites

Prepare the following environment.

  • Python 3.10 or later and pip
  • OpenSearch running in a VM (e.g., http://localhost:9200)
  • Private Endpoints and API Keys for Simple AI Inference

When using a private endpoint, add the VM resource to the allowed access targets when creating a Simple AI Inference. We recommend deploying the VM and Simple AI Inference in the same region. For details, refer to Create a Simple AI Inference and Manage API Keys.

Reference
In this tutorial, you use OpenSearch running on a VM as a vector database. You can connect to your existing OpenSearch environment or use the Search Engine service in SCP.

Preparing the Project File

Create the file with the following structure. Each of the following code blocks is a complete file.

rag-product-demo/
├── data/
│   ├── products.jsonl
│   └── personas.json
├── index_products.py
└── ask.py
Color mode
mkdir -p rag-product-demo/data
cd rag-product-demo
mkdir -p rag-product-demo/data
cd rag-product-demo
Code block. Create a project folder

Package Installation

Install the required Python packages.

Color mode
pip install requests opensearch-py
pip install requests opensearch-py
Code block. Package installation

SCP service information and user profile

data/products.jsonl stores the SCP service documents to search, and data/personas.json stores the personalization conditions. The example uses a small dataset, but you can add services with the same structure.

Color mode
Service Name: Virtual Server Auto-Scaling
Purpose: Automatically adjusts the number of web application servers in response to traffic fluctuations
Features: Scales Virtual Servers up or down based on policies or schedules, and can be integrated with Load Balancers.
{"id":"object-storage","name":"Object Storage","category":"Storage","source":"SCP Service Catalog / Object Storage","text":"Service Name: Object Storage\nPurpose: Store unstructured data such as images, documents, and logs\nFeatures: Store large volumes of data and leverage S3 API compatibility and access control features."}
Service Name: Load Balancer
Purpose: Distributes requests across multiple application servers
Features: Automatically distributes traffic to available servers during traffic spikes or server failures.
Service Name: Search Engine
Purpose: Configure search and analytics clusters based on OpenSearch or Elasticsearch
Features: Automates cluster creation and configuration in the Console and supports OpenSearch Dashboards.
Service Name: Simple AI Inference
Purpose: AI applications that use LLM models in API form
Features: Uses an OpenAI-compatible API and allows you to select a Public or Private Endpoint.
Service Name: Log Transmission
Purpose: Collects event logs from security devices and transmits them to the required areas
Features: Collects, stores, and transmits logs from firewalls, IPS, DDoS Protection, and other systems in real time.
{"id":"backup","name":"Backup","category":"Backup","source":"SCP Service Catalog / Backup","text":"Service Name: Backup\nPurpose: Back up data and restore it when needed\nFeatures: You can configure backup policies that include backup targets, frequency, and retention periods."}
Service Name: Archive Storage
Purpose: Store logs and documents that require long-term retention
Features: Archive Object Storage data and cost-effectively store data that is not frequently accessed.
Service Name: Virtual Server Auto-Scaling
Purpose: Automatically adjusts the number of web application servers in response to traffic fluctuations
Features: Scales Virtual Servers up or down based on policies or schedules, and can be integrated with Load Balancers.
{"id":"object-storage","name":"Object Storage","category":"Storage","source":"SCP Service Catalog / Object Storage","text":"Service Name: Object Storage\nPurpose: Store unstructured data such as images, documents, and logs\nFeatures: Store large volumes of data and leverage S3 API compatibility and access control features."}
Service Name: Load Balancer
Purpose: Distributes requests across multiple application servers
Features: Automatically distributes traffic to available servers during traffic spikes or server failures.
Service Name: Search Engine
Purpose: Configure search and analytics clusters based on OpenSearch or Elasticsearch
Features: Automates cluster creation and configuration in the Console and supports OpenSearch Dashboards.
Service Name: Simple AI Inference
Purpose: AI applications that use LLM models in API form
Features: Uses an OpenAI-compatible API and allows you to select a Public or Private Endpoint.
Service Name: Log Transmission
Purpose: Collects event logs from security devices and transmits them to the required areas
Features: Collects, stores, and transmits logs from firewalls, IPS, DDoS Protection, and other systems in real time.
{"id":"backup","name":"Backup","category":"Backup","source":"SCP Service Catalog / Backup","text":"Service Name: Backup\nPurpose: Back up data and restore it when needed\nFeatures: You can configure backup policies that include backup targets, frequency, and retention periods."}
Service Name: Archive Storage
Purpose: Store logs and documents that require long-term retention
Features: Archive Object Storage data and cost-effectively store data that is not frequently accessed.
Code block. data/products.jsonl
Color mode
{
  "startup-commerce": {
    "name": "Initial Online Shopping Mall",
    "description": "Operates an online shopping mall with significant traffic fluctuations, prioritizing scalability and cost efficiency."
    "categories": ["Compute", "Storage", "Network"]
  },
  "secure-enterprise": {
    "name": "Security-First Enterprise",
    "Minimize external exposure and prioritize internal document search and security monitoring."
    "categories": ["AI/ML", "Search", "Security", "Network"]
  },
  "
    "name": "Long-term Data Retention Organization",
    "Preserve logs and documentation for long-term retention, prioritizing recoverability."
    "categories": ["Storage", "Backup"]
  }
}
{
  "startup-commerce": {
    "name": "Initial Online Shopping Mall",
    "description": "Operates an online shopping mall with significant traffic fluctuations, prioritizing scalability and cost efficiency."
    "categories": ["Compute", "Storage", "Network"]
  },
  "secure-enterprise": {
    "name": "Security-First Enterprise",
    "Minimize external exposure and prioritize internal document search and security monitoring."
    "categories": ["AI/ML", "Search", "Security", "Network"]
  },
  "
    "name": "Long-term Data Retention Organization",
    "Preserve logs and documentation for long-term retention, prioritizing recoverability."
    "categories": ["Storage", "Backup"]
  }
}
Code block. data/personas.json

Indexing SCP service information

The following code vectorizes each SCP service document using the Embedding API and loads them into OpenSearch.

Color mode
import json
import os
from pathlib import Path

import requests
from opensearchpy import OpenSearch

INDEX_NAME = "product-rag-demo"
DATA_FILE = Path("data/products.jsonl")


def required(name):
    value = os.getenv(name)
    if not value:
        raise SystemExit(f"Set the {name} environment variable.")
    return value


SAI_ENDPOINT = required("SAI_ENDPOINT").rstrip("/")
SAI_API_KEY = required("SAI_API_KEY")
EMBEDDING_MODEL = required("SAI_EMBEDDING_MODEL")


def sai_headers():
    return {
        "Authorization": f"bearer {SAI_API_KEY}",
        "Content-Type": "application/json",
    }


def create_embedding(text):
    response = requests.post(
        f"{SAI_ENDPOINT}/v1/embeddings",
        headers=sai_headers(),
        json={
            "model": EMBEDDING_MODEL,
            "input": text,
            "encoding_format": "float",
        },
        timeout=60,
    )
    response.raise_for_status()
    return response.json()["data"][0]["embedding"]


def get_opensearch_client():
    return OpenSearch(
        hosts=[{
            "host": os.getenv("OPENSEARCH_HOST", "localhost"),
            "port": int(os.getenv("OPENSEARCH_PORT", "9200")),
        }],
        use_ssl=False,
        verify_certs=False,
    )


def load_products():
    with DATA_FILE.open(encoding="utf-8") as file:
        return [json.loads(line) for line in file if line.strip()]


def create_index(client, dimension):
    if client.indices.exists(index=INDEX_NAME):
        client.indices.delete(index=INDEX_NAME)

    client.indices.create(
        index=INDEX_NAME,
        body={
            "settings": {"index": {"knn": True}},
            "mappings": {
                "properties": {
                    "id": {"type": "keyword"},
                    "name": {"type": "text"},
                    "category": {"type": "keyword"},
                    "source": {"type": "keyword"},
                    "text": {"type": "text"},
                    "embedding": {
                        "type": "knn_vector",
                        "dimension": dimension,
                    },
                }
            },
        },
    )


def main():
    products = load_products()
    if not products:
        raise SystemExit("No service information available.")

    first_embedding = create_embedding(products[0]["text"])
    client = get_opensearch_client()
    create_index(client, len(first_embedding))

    for position, product in enumerate(products):
        embedding = first_embedding if position == 0 else create_embedding(product["text"])
        document = {**product, "embedding": embedding}
        client.index(index=INDEX_NAME, id=product["id"], body=document)
        print(f"Indexing complete: {product['name']}")

    client.indices.refresh(index=INDEX_NAME)
    print(f"Indexed a total of {len(products)} services.")


if __name__ == "__main__":
    main()
import json
import os
from pathlib import Path

import requests
from opensearchpy import OpenSearch

INDEX_NAME = "product-rag-demo"
DATA_FILE = Path("data/products.jsonl")


def required(name):
    value = os.getenv(name)
    if not value:
        raise SystemExit(f"Set the {name} environment variable.")
    return value


SAI_ENDPOINT = required("SAI_ENDPOINT").rstrip("/")
SAI_API_KEY = required("SAI_API_KEY")
EMBEDDING_MODEL = required("SAI_EMBEDDING_MODEL")


def sai_headers():
    return {
        "Authorization": f"bearer {SAI_API_KEY}",
        "Content-Type": "application/json",
    }


def create_embedding(text):
    response = requests.post(
        f"{SAI_ENDPOINT}/v1/embeddings",
        headers=sai_headers(),
        json={
            "model": EMBEDDING_MODEL,
            "input": text,
            "encoding_format": "float",
        },
        timeout=60,
    )
    response.raise_for_status()
    return response.json()["data"][0]["embedding"]


def get_opensearch_client():
    return OpenSearch(
        hosts=[{
            "host": os.getenv("OPENSEARCH_HOST", "localhost"),
            "port": int(os.getenv("OPENSEARCH_PORT", "9200")),
        }],
        use_ssl=False,
        verify_certs=False,
    )


def load_products():
    with DATA_FILE.open(encoding="utf-8") as file:
        return [json.loads(line) for line in file if line.strip()]


def create_index(client, dimension):
    if client.indices.exists(index=INDEX_NAME):
        client.indices.delete(index=INDEX_NAME)

    client.indices.create(
        index=INDEX_NAME,
        body={
            "settings": {"index": {"knn": True}},
            "mappings": {
                "properties": {
                    "id": {"type": "keyword"},
                    "name": {"type": "text"},
                    "category": {"type": "keyword"},
                    "source": {"type": "keyword"},
                    "text": {"type": "text"},
                    "embedding": {
                        "type": "knn_vector",
                        "dimension": dimension,
                    },
                }
            },
        },
    )


def main():
    products = load_products()
    if not products:
        raise SystemExit("No service information available.")

    first_embedding = create_embedding(products[0]["text"])
    client = get_opensearch_client()
    create_index(client, len(first_embedding))

    for position, product in enumerate(products):
        embedding = first_embedding if position == 0 else create_embedding(product["text"])
        document = {**product, "embedding": embedding}
        client.index(index=INDEX_NAME, id=product["id"], body=document)
        print(f"Indexing complete: {product['name']}")

    client.indices.refresh(index=INDEX_NAME)
    print(f"Indexed a total of {len(products)} services.")


if __name__ == "__main__":
    main()
Code block. index_products.py

Querying Personalized Service Information

The following code vectorizes the user’s query and finds similar service documents in OpenSearch. Pass the documents, prioritized by the user profile’s preferred categories, along with the user’s context to the Chat Completions API to generate the final response.

Color mode
import argparse
import json
import os
from pathlib import Path

import requests
from opensearchpy import OpenSearch

INDEX_NAME = "product-rag-demo"
PERSONAS_FILE = Path("data/personas.json")
CANDIDATE_COUNT = 8
ANSWER_DOCUMENT_COUNT = 3


def required(name):
    value = os.getenv(name)
    if not value:
        raise SystemExit(f"Set the {name} environment variable.")
    return value


SAI_ENDPOINT = required("SAI_ENDPOINT").rstrip("/")
SAI_API_KEY = required("SAI_API_KEY")
EMBEDDING_MODEL = required("SAI_EMBEDDING_MODEL")
CHAT_MODEL = required("SAI_CHAT_MODEL")


def sai_headers():
    return {
        "Authorization": f"bearer {SAI_API_KEY}",
        "Content-Type": "application/json",
    }


def create_embedding(text):
    response = requests.post(
        f"{SAI_ENDPOINT}/v1/embeddings",
        headers=sai_headers(),
        json={"model": EMBEDDING_MODEL, "input": text, "encoding_format": "float"},
        timeout=60,
    )
    response.raise_for_status()
    return response.json()["data"][0]["embedding"]


def get_opensearch_client():
    return OpenSearch(
        hosts=[{
            "host": os.getenv("OPENSEARCH_HOST", "localhost"),
            "port": int(os.getenv("OPENSEARCH_PORT", "9200")),
        }],
        use_ssl=False,
        verify_certs=False,
    )


def search_candidates(client, question_vector):
    response = client.search(
        index=INDEX_NAME,
        body={
            "size": CANDIDATE_COUNT,
            "query": {
                "knn": {
                    "embedding": {
                        "vector": question_vector,
                        "k": CANDIDATE_COUNT,
                    }
                }
            },
        },
    )
    return [hit["_source"] for hit in response["hits"]["hits"]]


def select_personalized_documents(candidates, persona):
    preferred_categories = set(persona["categories"])
    preferred = [
        document for document in candidates
        if document["category"] in preferred_categories
    ]
    remaining = [document for document in candidates if document not in preferred]
    return (preferred + remaining)[:ANSWER_DOCUMENT_COUNT]


def create_answer(persona, question, documents):
    context = "\n\n".join(
        f"[Document {number}] {document['name']}\n{document['text']}\nSource: {document['source']}"
        for number, document in enumerate(documents, start=1)
    )
    prompt = f"""User situation: {persona['description']}
Preferred service categories: {', '.join(persona['categories'])}

Retrieved SCP service information:
{context}

Question: {question}

Answer in Korean using only the information in the document above. Recommend services tailored to the user's situation, and display the [document number] after the recommendation reason. Do not estimate prices, contract terms, or features that are not in the documentation.

    payload = {
        "model": CHAT_MODEL,
        "messages": [
            {"role": "system", "content": "You are an AI assistant that helps with SCP service information inquiries."},
            {"role": "user", "content": prompt},
        ],
        "temperature": 0.2,
    }
    response = requests.post(
        f"{SAI_ENDPOINT}/v1/chat/completions",
        headers=sai_headers(),
        json=payload,
        timeout=60,
    )
    response.raise_for_status()

    content = response.json()["choices"][0]["message"]["content"]
    if not content:
        raise RuntimeError("Failed to generate a response.         Check the model settings.")
    return content


def main():
    personas = json.loads(PERSONAS_FILE.read_text(encoding="utf-8"))
    parser = argparse.ArgumentParser()
    parser.add_argument("--persona", required=True, choices=sorted(personas))
    parser.add_argument("--question", required=True)
    args = parser.parse_args()

    persona = personas[args.persona]
    client = get_opensearch_client()
    candidates = search_candidates(client, create_embedding(args.question))
    documents = select_personalized_documents(candidates, persona)
    answer = create_answer(persona, args.question, documents)

    print(f"\n[User Profile] {persona['name']}")
    print("[Search Document]")
    for number, document in enumerate(documents, start=1):
        print(f"{number}.         {document['name']} ({document['source']})")
    print(f"\n[Answer]\n{answer}")


if __name__ == "__main__":
    main()
import argparse
import json
import os
from pathlib import Path

import requests
from opensearchpy import OpenSearch

INDEX_NAME = "product-rag-demo"
PERSONAS_FILE = Path("data/personas.json")
CANDIDATE_COUNT = 8
ANSWER_DOCUMENT_COUNT = 3


def required(name):
    value = os.getenv(name)
    if not value:
        raise SystemExit(f"Set the {name} environment variable.")
    return value


SAI_ENDPOINT = required("SAI_ENDPOINT").rstrip("/")
SAI_API_KEY = required("SAI_API_KEY")
EMBEDDING_MODEL = required("SAI_EMBEDDING_MODEL")
CHAT_MODEL = required("SAI_CHAT_MODEL")


def sai_headers():
    return {
        "Authorization": f"bearer {SAI_API_KEY}",
        "Content-Type": "application/json",
    }


def create_embedding(text):
    response = requests.post(
        f"{SAI_ENDPOINT}/v1/embeddings",
        headers=sai_headers(),
        json={"model": EMBEDDING_MODEL, "input": text, "encoding_format": "float"},
        timeout=60,
    )
    response.raise_for_status()
    return response.json()["data"][0]["embedding"]


def get_opensearch_client():
    return OpenSearch(
        hosts=[{
            "host": os.getenv("OPENSEARCH_HOST", "localhost"),
            "port": int(os.getenv("OPENSEARCH_PORT", "9200")),
        }],
        use_ssl=False,
        verify_certs=False,
    )


def search_candidates(client, question_vector):
    response = client.search(
        index=INDEX_NAME,
        body={
            "size": CANDIDATE_COUNT,
            "query": {
                "knn": {
                    "embedding": {
                        "vector": question_vector,
                        "k": CANDIDATE_COUNT,
                    }
                }
            },
        },
    )
    return [hit["_source"] for hit in response["hits"]["hits"]]


def select_personalized_documents(candidates, persona):
    preferred_categories = set(persona["categories"])
    preferred = [
        document for document in candidates
        if document["category"] in preferred_categories
    ]
    remaining = [document for document in candidates if document not in preferred]
    return (preferred + remaining)[:ANSWER_DOCUMENT_COUNT]


def create_answer(persona, question, documents):
    context = "\n\n".join(
        f"[Document {number}] {document['name']}\n{document['text']}\nSource: {document['source']}"
        for number, document in enumerate(documents, start=1)
    )
    prompt = f"""User situation: {persona['description']}
Preferred service categories: {', '.join(persona['categories'])}

Retrieved SCP service information:
{context}

Question: {question}

Answer in Korean using only the information in the document above. Recommend services tailored to the user's situation, and display the [document number] after the recommendation reason. Do not estimate prices, contract terms, or features that are not in the documentation.

    payload = {
        "model": CHAT_MODEL,
        "messages": [
            {"role": "system", "content": "You are an AI assistant that helps with SCP service information inquiries."},
            {"role": "user", "content": prompt},
        ],
        "temperature": 0.2,
    }
    response = requests.post(
        f"{SAI_ENDPOINT}/v1/chat/completions",
        headers=sai_headers(),
        json=payload,
        timeout=60,
    )
    response.raise_for_status()

    content = response.json()["choices"][0]["message"]["content"]
    if not content:
        raise RuntimeError("Failed to generate a response.         Check the model settings.")
    return content


def main():
    personas = json.loads(PERSONAS_FILE.read_text(encoding="utf-8"))
    parser = argparse.ArgumentParser()
    parser.add_argument("--persona", required=True, choices=sorted(personas))
    parser.add_argument("--question", required=True)
    args = parser.parse_args()

    persona = personas[args.persona]
    client = get_opensearch_client()
    candidates = search_candidates(client, create_embedding(args.question))
    documents = select_personalized_documents(candidates, persona)
    answer = create_answer(persona, args.question, documents)

    print(f"\n[User Profile] {persona['name']}")
    print("[Search Document]")
    for number, document in enumerate(documents, start=1):
        print(f"{number}.         {document['name']} ({document['source']})")
    print(f"\n[Answer]\n{answer}")


if __name__ == "__main__":
    main()
Code block. ask.py

Run

Set the Simple AI Inference endpoint, API key, and model ID to use as environment variables.

Reference

For the SAI_ENDPOINT, SAI_EMBEDDING_MODEL, and SAI_CHAT_MODEL values used in the code, refer to Serverless Inference detailed information and Model detailed information.

  • Embedding API: {Simple AI Inference private endpoint}/v1/embeddings
  • Chat Completions API: {Simple AI Inference private endpoint}/v1/chat/completions
  • SAI_EMBEDDING_MODEL: {Embedding model ID confirmed in the console}
  • SAI_CHAT_MODEL: {Chat model ID confirmed in the console}
Color mode
export SAI_ENDPOINT="{Simple AI Inference private endpoint}"
export SAI_API_KEY="sai-..."
export SAI_EMBEDDING_MODEL="{Embedding model ID confirmed in the console}"
export SAI_CHAT_MODEL="{Chat model ID confirmed in the console}"

# Configure this only if the VM's OpenSearch is not running on localhost:9200.
export OPENSEARCH_HOST="localhost"
export OPENSEARCH_PORT="9200"
export SAI_ENDPOINT="{Simple AI Inference private endpoint}"
export SAI_API_KEY="sai-..."
export SAI_EMBEDDING_MODEL="{Embedding model ID confirmed in the console}"
export SAI_CHAT_MODEL="{Chat model ID confirmed in the console}"

# Configure this only if the VM's OpenSearch is not running on localhost:9200.
export OPENSEARCH_HOST="localhost"
export OPENSEARCH_PORT="9200"
Code block. Environment variable configuration

Run index_products.py to vectorize the SCP service documentation and store it in OpenSearch. If the product-rag-demo index already exists, delete the existing index and then create it again.

Color mode
python index_products.py
python index_products.py
Code block. SCP service information index

After vector document storage is complete, the processing results by service and the total number of items are output as follows.

Color mode
Indexing complete: Virtual Server Auto-Scaling
Indexing complete: Object Storage
Indexing complete: Load Balancer
Indexing complete: Search Engine
Indexing complete: Simple AI Inference
Indexing complete: Log Transmission
Indexing complete: Backup
Indexing complete: Archive Storage
Indexed a total of 8 services.
Indexing complete: Virtual Server Auto-Scaling
Indexing complete: Object Storage
Indexing complete: Load Balancer
Indexing complete: Search Engine
Indexing complete: Simple AI Inference
Indexing complete: Log Transmission
Indexing complete: Backup
Indexing complete: Archive Storage
Indexed a total of 8 services.
Example output. SCP service information index

If you have access to OpenSearch Dashboards, you can select product-rag-demo* in Discover to view the service information and embedding vectors stored in the index.

View documents in the product-rag-demo index in OpenSearch Dashboards
Figure.

Try running the question for each user profile.

Color mode
python ask.py \
  --persona startup-commerce \
  --question "Please recommend a service suitable for an online shopping mall with high traffic fluctuations."

python ask.py \
  --persona secure-enterprise \
  --question "What service is suitable for configuring internal document search while minimizing external exposure?"
python ask.py \
  --persona startup-commerce \
  --question "Please recommend a service suitable for an online shopping mall with high traffic fluctuations."

python ask.py \
  --persona secure-enterprise \
  --question "What service is suitable for configuring internal document search while minimizing external exposure?"
Code block. Run personalized questions

Example Output

The following is an example of running the above command once. The phrasing of the generated response may vary depending on the selected model.

Color mode
[User Profile] Initial Online Shopping Mall
[Search Document]
1. Virtual Server Auto-Scaling (SCP Service Catalog / Virtual Server Auto-Scaling)
2. Load Balancer (SCP Service Catalog / Load Balancer)
3. Archive Storage (SCP Service Catalog / Archive Storage)

[Answer]
The following services are suitable for operating and scaling an online shopping mall with significant traffic fluctuations, prioritizing cost efficiency:

- **Virtual Server Auto-Scaling**: You can scale the number of servers up or down based on policies or schedules to handle traffic fluctuations. - [Document 1]
- **Load Balancer**: You can handle traffic spikes and distribute requests across multiple application servers to improve service availability. - [Document 2]
- **Archive Storage**: Ideal for cost-efficiency-first scenarios, as it provides cost-effective storage for logs and documents that are not frequently accessed. - [Document 3]
[User Profile] Initial Online Shopping Mall
[Search Document]
1. Virtual Server Auto-Scaling (SCP Service Catalog / Virtual Server Auto-Scaling)
2. Load Balancer (SCP Service Catalog / Load Balancer)
3. Archive Storage (SCP Service Catalog / Archive Storage)

[Answer]
The following services are suitable for operating and scaling an online shopping mall with significant traffic fluctuations, prioritizing cost efficiency:

- **Virtual Server Auto-Scaling**: You can scale the number of servers up or down based on policies or schedules to handle traffic fluctuations. - [Document 1]
- **Load Balancer**: You can handle traffic spikes and distribute requests across multiple application servers to improve service availability. - [Document 2]
- **Archive Storage**: Ideal for cost-efficiency-first scenarios, as it provides cost-effective storage for logs and documents that are not frequently accessed. - [Document 3]
[User Profile] Security-Focused Enterprise
[Search Document]
1. Search Engine (SCP Service Catalog / Search Engine)
2. Simple AI Inference (SCP Service Catalog / Simple AI Inference)
3. Log Transmission (SCP Service Catalog / Log Transmission)

[Answer]
To configure internal document search while minimizing external exposure, we recommend **Simple AI Inference** as the first choice. You can call the model API by selecting a Private Endpoint. [Document 2]

You can configure a **Search Engine** as the document search repository. You can configure an OpenSearch-based cluster to use as a search and analytics environment. [Document 1]

To collect security device event logs and transmit them to the required destinations, you can additionally use **Log Transmission**. [Document 3]
[User Profile] Security-Focused Enterprise
[Search Document]
1. Search Engine (SCP Service Catalog / Search Engine)
2. Simple AI Inference (SCP Service Catalog / Simple AI Inference)
3. Log Transmission (SCP Service Catalog / Log Transmission)

[Answer]
To configure internal document search while minimizing external exposure, we recommend **Simple AI Inference** as the first choice. You can call the model API by selecting a Private Endpoint. [Document 2]

You can configure a **Search Engine** as the document search repository. You can configure an OpenSearch-based cluster to use as a search and analytics environment. [Document 1]

To collect security device event logs and transmit them to the required destinations, you can additionally use **Log Transmission**. [Document 3]
Example output

Personalization prioritizes preferred categories. The retrieved documents and answers may vary based on vector similarity to the query. If there are insufficient preferred category candidates, services from other categories may also be included.

Scaling to Production

When scaling to a production environment, consider the following.

  • If you have documents that require permissions, apply the permission filter at the OpenSearch search stage, not after receiving the search results.
  • For frequently changing information such as pricing, inventory, and contract availability, query a separate API or business system instead of RAG documents.
  • As the number of service documents and search candidates grows, add the Rerank API to rerank the top documents.

For the request formats of the Embedding API and the Chat Completions API, refer to Embedding API and Chat Completions API, respectively.

Tutorial
API Reference