Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions private-ai-services-container/introduction/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ In the following labs you will work not only with in-database embedding but **sp
- run cosine similarity search
- build a simple image search app that used multimodal embedding models

Estimated Workshop Time: 90 minutes
Estimated Workshop Time: 60 minutes

### Architecture at a Glance

Expand Down Expand Up @@ -56,4 +56,4 @@ In this workshop, you will:

## Acknowledgements
- **Author** - Oracle LiveLabs Team
- **Last Updated By/Date** - Oracle LiveLabs Team, March 2026
- **Last Updated By/Date** - Oracle LiveLabs Team, April 2026
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,70 @@ In this lab, you will:
- Verify internal container DNS resolution from JupyterLab
- Validate Private AI health and model list
- Confirm Oracle AI Database and ORDS reachability from JupyterLab
- Confirm `/home/.env` is available to the notebook

### Prerequisites

This lab assumes:
- You can open a terminal in JupyterLab (`File` -> `New` -> `Terminal`)
- You can open a terminal in JupyterLab (`File` -> `New` -> `Terminal`) or click the `Terminal` tile on the home page


## Task 1: Verify Internal Hostname Resolution

1. In JupyterLab, open a new terminal.

![JL Login](./images/jl.png)

2. Verify that runtime service names resolve:

```bash
<copy>getent hosts privateai aidbfree ords</copy>
<copy>getent hosts privateai aidbfree ords | sort -u</copy>
```

Expected: one IP entry for each service name.

## Task 2: Validate Private AI REST Endpoints and list available models
![Services](./images/services.png)

1. Health endpoint:
## Task 2: Validate Private AI Services Container REST Endpoints and list available models

1. Let's first check that the Health REST endpoint of the Private AI Services Container:

```bash
<copy>curl -sS -i http://privateai:8080/health</copy>
```

Expected: HTTP `200`.

2. List deployed models:
![Curl result](./images/curl.png)

2. Now we list all deployed models that come with the Private AI Services Container:

```bash
<copy>curl -sS http://privateai:8080/v1/models | jq .</copy>
```

Expected: JSON payload with a `data` array of model IDs.

![Models](./images/models.png)

3. Review the models

Use the table below as a quick model-selection guide after you run `/v1/models`:

| Model ID | Capabilities | Model Size | Typical Use Case | When to Choose It |
| --- | --- | --- | --- | --- |
| `clip-vit-base-patch32-img` | `IMAGE_EMBEDDINGS` | `335.38M` | Create embeddings for images/photos. | Choose for image indexing and visual similarity search. Pair with `clip-vit-base-patch32-txt` for text-to-image retrieval. |
| `clip-vit-base-patch32-txt` | `TEXT_EMBEDDINGS` | `243.57M` | Create text embeddings compatible with CLIP image vectors. | Choose for natural-language queries against a CLIP image index. |
| `all-minilm-112-v2` | `TEXT_EMBEDDINGS` | `127.13M` | Lightweight general-purpose text embeddings. | Choose for fastest startup and lower resource usage in English-focused semantic search. |
| `all-mpnet-base-v2` | `TEXT_EMBEDDINGS` | `415.82M` | Higher-quality English semantic embeddings. | Choose when retrieval quality matters more than model size and latency. |
| `multilingual-e5-base` | `TEXT_EMBEDDINGS` | `1.04G` | Multilingual semantic search across many languages. | Choose for mixed-language corpora or non-English user queries. |
| `multilingual-e5-large` | `TEXT_EMBEDDINGS` | `2.09G` | Large text embedding model Multilingual semantic search across many languages.. | Choose when you want strongest semantic coverage and can accept higher memory/latency cost. |
{: title="Models deployed in Oracle Private AI Services Container"}

Rule of thumb:
- For image search: use the CLIP pair (`clip-vit-base-patch32-img` + `clip-vit-base-patch32-txt`).
- For text-only search: start with `all-minilm-112-v2`, then move to larger models if quality needs improvement.


## Acknowledgements
- **Author** - Oracle LiveLabs Team
- **Last Updated By/Date** - Oracle LiveLabs Team, March 2026
- **Last Updated By/Date** - Oracle LiveLabs Team, April 2026
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
In this lab you run vector search using an embedding model that is already stored in Oracle AI Database (for example `ALL_MINILM_L12_V2`).


Estimated Time: 20 minutes
Estimated Time: 15 minutes

### Objectives

Expand Down Expand Up @@ -35,6 +35,8 @@ This lab assumes:
## Task 2: Open the Notebook

1. From the sidebar, double-click on the folder notebooks and then open the notebook (in case you do not see the folder click on refresh):

![refresh](./images/refresh.png)

```
database-model-embeddings.ipynb
Expand All @@ -46,6 +48,8 @@ This lab assumes:

Run this cell:

This cell imports the Python modules used throughout the notebook. You need these libraries to read environment settings, connect to Oracle Database, format JSON parameters, and safely validate model names before using them in SQL.

```python
<copy>import os
import json
Expand All @@ -54,16 +58,18 @@ import oracledb
from dotenv import dotenv_values</copy>
```

## Task 3: Load Database Configuration
## Task 4: Load Database Configuration

Run this cell:

This cell loads your database connection settings and preferred model name from environment variables.

```python
<copy>ENV_PATH = os.getenv('LAB_ENV_FILE', '/home/.env')
env = dotenv_values(ENV_PATH) if os.path.exists(ENV_PATH) else {}

DB_USER = os.getenv('DB_USER') or env.get('USERNAME') or 'ADMIN'
DB_PASSWORD = os.getenv('DB_PASSWORD') or env.get('DBPASSWORD')
DB_PASSWORD = os.getenv('ORACLE_PWD')
DB_HOST = os.getenv('DB_HOST', 'aidbfree')
DB_PORT = os.getenv('DB_PORT', '1521')
DB_SERVICE = os.getenv('DB_SERVICE', 'FREEPDB1')
Expand All @@ -76,13 +82,15 @@ print('DB dsn :', DB_DSN)
print('Preferred DB model:', PREFERRED_DB_MODEL)

if not DB_PASSWORD:
raise ValueError('DB password not found. Set DB_PASSWORD or DBPASSWORD in /home/.env')</copy>
raise ValueError('DB password not found. Set ORACLE_PWD')</copy>
```

## Task 4: Connect and Discover Stored Models
## Task 5: Connect and Discover Stored Models

Run this cell:

This cell connects to Oracle AI Database, lists available embedding models from `USER_MINING_MODELS`, and picks the model to use for the rest of the lab. All later embedding and vector-search steps depend on selecting a valid deployed model first.

```python
<copy>conn = oracledb.connect(user=DB_USER, password=DB_PASSWORD, dsn=DB_DSN)
cur = conn.cursor()
Expand All @@ -108,10 +116,12 @@ if not re.match(r'^[A-Z][A-Z0-9_$#]*$', MODEL_NAME):
raise ValueError(f'Unsafe model identifier: {MODEL_NAME}')</copy>
```

## Task 5: Determine Embedding Dimension
## Task 6: Determine Embedding Dimension

Run this cell:

This cell performs a small probe embedding and asks the database for the vector dimension returned by the selected model. This can be relevant because the in table schema a user can specify same dimension in its `VECTOR(...)` column.

```python
<copy>db_params = json.dumps({
'provider': 'database',
Expand All @@ -129,10 +139,12 @@ EMBEDDING_DIM = int(cur.fetchone()[0])
print('Embedding dimension:', EMBEDDING_DIM)</copy>
```

## Task 6: Create Table and Store Embeddings
## Task 7: Create Table and Store Embeddings

Run this cell:

This cell creates a demo table, embeds sample text rows, and stores both text and vectors in Oracle AI Database. Here we build the vector dataset that you will query in the similarity search step.

```python
<copy>TABLE_NAME = 'PRIVATEAI_DOCS_DBMODEL'

Expand Down Expand Up @@ -173,10 +185,12 @@ conn.commit()
print('Inserted rows:', inserted)</copy>
```

## Task 7: Run Similarity Search
## Task 8: Run Similarity Search

Run this cell:

This cell embeds the user query and compares it to stored vectors using cosine distance, then returns the top matching rows. This demonstrates the full semantic-search flow in SQL, not just exact keyword matching.

```python
<copy>query_text = 'Which approach keeps embedding generation inside Oracle Database?'

Expand Down Expand Up @@ -207,17 +221,21 @@ for idx, (title, score, preview) in enumerate(rows, 1):
print(f' {preview}')</copy>
```

## Task 8: Optional Cleanup
## Task 9: Optional Cleanup

Run optional cleanup:

This optional cell drops the demo table so you can reset the lab and rerun from a clean state.

```python
<copy># cur.execute(f'DROP TABLE {TABLE_NAME} PURGE')
# conn.commit()</copy>
```

Close the connection:

This final cell closes database resources. Closing cursors and connections is good practice and prevents resource leaks in longer notebook sessions.

```python
<copy>cur.close()
conn.close()
Expand All @@ -230,4 +248,4 @@ print('Connection closed.')</copy>

## Acknowledgements
- **Author** - Oracle LiveLabs Team
- **Last Updated By/Date** - Oracle LiveLabs Team, March 2026
- **Last Updated By/Date** - Oracle LiveLabs Team, April 2026
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ In this lab you run vector search using Oracle Private AI Services Container (`p
This lab mirrors the notebook:

```text
lab3-privateai-container-embeddings/files/privateai-container-embeddings.ipynb
privateai-container-embeddings.ipynb
```

Estimated Time: 25 minutes
Estimated Time: 15 minutes

### Objectives

Expand Down Expand Up @@ -55,6 +55,9 @@ This lab assumes:

Run this cell:

This cell imports the Python modules used throughout the notebook. You need these libraries to read environment settings, connect to Oracle Database, format JSON parameters, and safely validate model names before using them in SQL.


```python
<copy>import os
import json
Expand All @@ -63,16 +66,18 @@ import oracledb
from dotenv import dotenv_values</copy>
```

## Task 3: Load Configuration
## Task 4: Load Configuration

Run this cell:

This step reads database and Private AI settings from environment variables and prints the active values. It gives you a quick sanity check that the notebook is pointing to the correct services before any API or SQL calls run.

```python
<copy>ENV_PATH = os.getenv('LAB_ENV_FILE', '/home/.env')
env = dotenv_values(ENV_PATH) if os.path.exists(ENV_PATH) else {}

DB_USER = os.getenv('DB_USER') or env.get('USERNAME') or 'ADMIN'
DB_PASSWORD = os.getenv('DB_PASSWORD') or env.get('DBPASSWORD')
DB_PASSWORD = os.getenv('ORACLE_PWD')
DB_HOST = os.getenv('DB_HOST', 'aidbfree')
DB_PORT = os.getenv('DB_PORT', '1521')
DB_SERVICE = os.getenv('DB_SERVICE', 'FREEPDB1')
Expand All @@ -88,13 +93,15 @@ print('Private AI URL:', PRIVATEAI_BASE_URL)
print('Preferred model:', PREFERRED_MODEL)

if not DB_PASSWORD:
raise ValueError('DB password not found. Set DB_PASSWORD or DBPASSWORD in /home/.env')</copy>
raise ValueError('DB password not found. Set ORACLE_PWD)</copy>
```

## Task 4: Validate Private AI and Choose Model
## Task 5: Validate Private AI and Choose Model

Run this cell:

This block checks that the Private AI service is healthy, fetches the deployed model list, filters to text-embedding-capable models, and selects one model ID. You do this now so the rest of the lab uses a model that is actually available in your environment.

```python
<copy>health = requests.get(f'{PRIVATEAI_BASE_URL}/health', timeout=20)
print('Health status:', health.status_code)
Expand Down Expand Up @@ -129,10 +136,12 @@ print()
print('Selected model:', MODEL_ID)</copy>
```

## Task 5: Call `/v1/embeddings` Directly
## Task 6: Send embedding request to REST API

Run this cell:

Here you send a direct embeddings request to the Private AI endpoint with sample text. The response confirms end-to-end API behavior and reveals the embedding dimension needed for the database `VECTOR` column.

```python
<copy>payload = {
'model': MODEL_ID,
Expand All @@ -156,22 +165,26 @@ print('Returned vectors:', len(embed_json.get('data', [])))
print('Embedding dimension:', EMBEDDING_DIM)</copy>
```

## Task 6: Connect to Oracle Database
## Task 7: Connect to Oracle Database

Run this cell:

This step opens a database session and verifies the connected user. It establishes the SQL connection required to create tables, insert vectors, and run similarity search queries.

```python
<copy>conn = oracledb.connect(user=DB_USER, password=DB_PASSWORD, dsn=DB_DSN)
cur = conn.cursor()

cur.execute('select user from dual')
cur.execute('select user')
print('Connected as:', cur.fetchone()[0])</copy>
```

## Task 7: Create Table and Store Private AI Embeddings
## Task 8: Create Table and Store Private AI Embeddings

Run this cell:

This cell creates a demo table, defines Private AI embedding parameters, and inserts sample rows with vectors generated through Private AI Services Container. The result is a searchable vector dataset stored in Oracle AI Database.

```python
<copy>TABLE_NAME = 'PRIVATEAI_DOCS_CONTAINER'

Expand Down Expand Up @@ -219,10 +232,12 @@ conn.commit()
print('Inserted rows:', inserted)</copy>
```

## Task 8: Run Similarity Search
## Task 9: Run Similarity Search

Run this cell:

This query converts the user question into an embedding and ranks stored rows by cosine similarity. It demonstrates semantic retrieval, where meaning-based matches can be returned even when keywords differ.

```python
<copy>query_text = 'How can I run embeddings locally and use them for semantic search?'

Expand Down Expand Up @@ -253,17 +268,21 @@ for idx, (title, score, preview) in enumerate(rows, 1):
print(f' {preview}')</copy>
```

## Task 9: Optional Cleanup
## Task 10: Optional Cleanup

Run optional cleanup:

Use this optional command to drop the demo table when you want to reset and rerun the lab from a clean state.

```python
<copy># cur.execute(f'DROP TABLE {TABLE_NAME} PURGE')
# conn.commit()</copy>
```

Close the connection:

This final cell closes the cursor and connection so the session ends cleanly and no resources remain open in the notebook kernel.

```python
<copy>cur.close()
conn.close()
Expand All @@ -279,4 +298,4 @@ print('Connection closed.')</copy>

## Acknowledgements
- **Author** - Oracle LiveLabs Team
- **Last Updated By/Date** - Oracle LiveLabs Team, March 2026
- **Last Updated By/Date** - Oracle LiveLabs Team, April 2026
Binary file not shown.
Loading
Loading