diff --git a/dev-ai-app-dev-constructioneng-aiexperience/app-architecture/app-architecture.md b/dev-ai-app-dev-constructioneng-aiexperience/app-architecture/app-architecture.md
index c23208eb2..f3d221bc5 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/app-architecture/app-architecture.md
+++ b/dev-ai-app-dev-constructioneng-aiexperience/app-architecture/app-architecture.md
@@ -2,71 +2,69 @@
## Introduction
-In this lab, you will explore the architecture behind the workshop that supports the tasks you will perform. We also have a closer look at all the features of the Oracle AI Database that were used to build the workshop and the demo application.
+In this lab, you will explore the architecture behind the workshop and the construction procurement application it supports. You will also look more closely at the Oracle AI Database features used to build both the workshop labs and the demo app.
Estimated Lab Time: 15 minutes
-## Physical Architecture
-
-The SeerEquities loan application runs in an **Oracle Cloud Infrastructure (OCI)** Region, with its application layer in a public subnet inside a **Virtual Cloud Network (VCN)**.
-
-
-
-### Architecture Breakdown
-
-- The Application Tier VCN includes:
-
- - An Internet Gateway for outbound traffic
+### Objectives
- - A Service Gateway for access to Oracle Cloud services
+In this lab, you will:
- - A Dynamic Routing Gateway (DRG) to connect to the Oracle Services Network
+* Review the OCI architecture that supports the Seer Construction
+ procurement application
+* Understand how JSON Duality Views, AI Vector Search, and Property
+ Graph support the procurement workflow
+* Connect the workshop labs to the application design used in the demo
- - A VM in the public subnet runs two containers, including:
-
- - Open-source Python library for the Loan Approval Demo
-
- - JupterLab as a browser-based development environment
-
-- The Application Subnet connects to the Oracle Services Network via the Service Gateway, enabling access to:
+## Physical Architecture
- - Autonomous AI Database Serverless
+The Seer Construction procurement application runs in an **Oracle Cloud Infrastructure (OCI)** region, with its application layer in a public subnet inside a **Virtual Cloud Network (VCN)**.
- - OCI Generative AI Services
+
-This architecture provides strong connectivity, scalability, and integration with Oracle cloud-native services to support efficient loan processing and approval.
+### Architecture Breakdown
-## Oracle AI Database features used in the demo app and in this workshop
+- The application-tier VCN includes:
+ - An Internet Gateway for outbound traffic
+ - A Service Gateway for access to Oracle Cloud services
+ - A Dynamic Routing Gateway (DRG) to connect to the Oracle Services Network
+ - A VM in the public subnet that runs two containers:
+ - The open-source Python stack for the construction procurement demo
+ - JupyterLab as a browser-based development environment
+- The application subnet connects to the Oracle Services Network through the Service Gateway, enabling access to:
+ - Autonomous AI Database Serverless
+ - OCI Generative AI services
+This architecture provides strong connectivity, scalability, and integration with Oracle cloud-native services to support efficient construction procurement review, supplier recommendation, and decision workflows.
+## Oracle AI Database Features Used in the Demo App and in this Workshop
### **JSON Duality View**
-JSON Relational Duality in Oracle AI Database bridges the gap between relational and document data models. It gives developers the flexibility of JSON with the efficiency and power of relational storage. This eliminates the trade-offs of choosing one model over the other.
+JSON Relational Duality in Oracle AI Database bridges the gap between relational and document data models. It gives developers the flexibility of JSON with the efficiency and power of relational storage, eliminating the trade-offs of choosing one model over the other.
At the core of this capability is the JSON Relational Duality View, which lets applications read and write JSON while the data remains stored in relational tables.
-A key feature that should be highlighted is the ability to connect the database using Mongo DB syntax. This allows developers to interact with collections and documents using a familiar syntax.
+A key feature worth highlighting is the ability to connect to the database using MongoDB-style syntax. This allows developers to interact with collections and documents using a familiar API style.
-**Where is it used**: We implemented JSON Duality View in the demo app and in this workshop. All data you can view in the dashboard of the demo app is query from JSON Duality Views. In Lab 3, you learn how to interact with JSON Duality View using Oracle's Python driver. But you also learn how to use Oracle's Mongo API to query JSON Duality Views using Mongo DB syntax.
+**Where is it used**: We implement JSON Duality Views in both the demo app and this workshop. Procurement dashboard data shown in the application is queried from JSON Duality Views. In Lab 3, you learn how to interact with JSON Duality Views using Oracle’s Python driver and Oracle’s Mongo API.
### **AI Vector Search**
-Oracle AI Vector Search, a feature of Oracle AI Database, enables fast, efficient searches over AI-generated vectors stored in the database. It supports multiple indexing strategies and scales to large datasets. With it, Large Language Models (LLMs) can query private business data using natural language, returning more accurate, context-aware results. Developers can also add semantic search to new or existing applications with minimal effort. A **unique feature** of Oracle AI Database is its capability to host ONNX models and deploy them as a database function. This feature allows you to host ONNX models and deploy them as a database function, enabling seamless integration with Oracle AI Database.
+Oracle AI Vector Search, a feature of Oracle AI Database, enables fast, efficient searches over AI-generated vectors stored in the database. It supports multiple indexing strategies and scales to large datasets. With it, Large Language Models (LLMs) can query private business data using natural language while returning more accurate, context-aware results.
-**Where is it used**: AI Vector Search is a key feature of the demo app and is also a topic in Lab 4 and Lab 5. In Lab 4, you use AI Vector Search to implement a RAG process, while in Lab 5, you specifically implement similarity search.
+**Where is it used**: AI Vector Search is a key feature of the demo app and is also covered in Lab 4 and Lab 5. In Lab 4, you use AI Vector Search to implement a RAG process. In Lab 5, you focus on similarity search.
### **Property Graph**
-Oracle AI Database supports property graphs, which model relationships using vertices and edges mapped to existing tables, external tables, materialized views, or synonyms. These graphs store metadata—not the actual data—which remains in the underlying objects. You use SQL/PGQ to query and interact with them.
-
-Property graphs simplify working with connected data, such as identifying influencers, predicting trends, or discovering relationships through pattern matching, by offering a more intuitive and efficient way to model and query complex networks.
+Oracle AI Database supports property graphs, which model relationships using vertices and edges mapped to existing tables, external tables, materialized views, or synonyms. These graphs store metadata rather than duplicating the underlying data. You use SQL/PGQ to query and interact with them.
-**Where is it used**: We implemented property graphs in the demo part of this workshop. Loan approval officers can use it to identify potential alternative loans for their customers.
+Property graphs simplify connected-data analysis, such as tracing supplier recommendations, risk outcomes, project requirements, and pending procurement decisions through a graph representation.
+**Where is it used**: We implement property graphs in the workshop demo. Construction procurement officers can use them to identify near-approval suppliers, explain denial outcomes, and understand the decision context around project procurement risk.
## Acknowledgements
* **Authors** - Linda Foinding, Francis Regalado
* **Contributors** - Eddie Ambler
-* **Last Updated By/Date** - Linda Foinding, April 2025
\ No newline at end of file
+* **Last Updated By/Date** - Taylor Zheng, Uma Kumar, Deion Locklear, Daniet Hart, July 2026
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/build.md b/dev-ai-app-dev-constructioneng-aiexperience/build/build.md
index 24b6281a3..7e8bdf53e 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/build/build.md
+++ b/dev-ai-app-dev-constructioneng-aiexperience/build/build.md
@@ -1,19 +1,19 @@
-# Step by step: Implement RAG with Oracle AI Database
+# Step by step: Implement RAG with Oracle AI Database
## Introduction
-In this lab, you build a complete loan approval engine with Oracle AI Database and OCI Generative AI. Connect to the database, explore order and image data, and invoke a large language model to generate personalized loan decisions and policy explanations. Building on earlier exercises, you’ll apply Python to deliver a fully integrated, AI-powered finance loan application.
+In this lab, you build a construction procurement engine with Oracle AI Database and OCI Generative AI. Connect to the database, explore the sample procurement data, and invoke a large language model to generate supplier recommendations and risk explanations. Building on earlier exercises, you’ll apply Python to deliver a fully integrated, AI-powered construction procurement application.
-This lab uses some of the basic coding samples you created in lab 3, such as cursor.execute and more.
+This lab uses some of the basic coding samples you created in lab 3, such as `cursor.execute` and more.
Estimated Time: 30 minutes
### Objectives
-* Build the complete loan approval application as seen in lab 1
-* Use OCI Generative AI to generate contextual loan recommendations
+* Build the complete construction procurement application as seen in lab 1
+* Use OCI Generative AI to generate contextual procurement recommendations
* Use Python to connect to an Oracle AI Database instance and run queries
-* Explore customer data and extract relevant information
+* Explore procurement data and extract relevant information
### Prerequisites
@@ -32,7 +32,7 @@ This lab assumes you have:

-1. Click the blue "+". This will open the Launcher.
+3. Click the blue `+`. This will open the Launcher.

@@ -40,9 +40,9 @@ This lab assumes you have:
1. Review the different elements in JupyterLab:
- **File browser (1):** The file browser organizes and manages files within the JupyterLab workspace. It supports drag-and-drop file uploads, file creation, renaming, and deletion. Users can open notebooks, terminals, and text editors directly from the browser. Navigation is fast and intuitive, with breadcrumbs and context menus that surface relevant actions. Users can right-click files to access options like duplicate, shutdown kernel, or open with a specific editor.
+ **File browser (1):** The file browser organizes and manages files within the JupyterLab workspace. It supports drag-and-drop file uploads, file creation, renaming, and deletion. Users can open notebooks, terminals, and text editors directly from the browser.
- **Launcher (2 and 3):** The launcher offers a streamlined entry point for starting new activities. Users can create Jupyter Notebooks for interactive coding with live code execution, visualizations, and rich markdown. The terminal provides direct shell access, enabling command-line operations within the JupyterLab environment. These two tools form the core of most workflows, supporting both interactive analysis and system-level tasks from a single interface.
+ **Launcher (2 and 3):** The launcher offers a streamlined entry point for starting new activities. Users can create Jupyter Notebooks for interactive coding with live code execution, visualizations, and rich markdown. The terminal provides direct shell access for command-line work in the same environment.

@@ -52,7 +52,7 @@ This lab assumes you have:

-2. Navigate to `db_setup_script_2.sql` under the `dbinit` folder. Here is where you can see all the tables that will be created for the finance industry.
+2. Navigate to `db_setup_script_2.sql` under the `dbinit` folder. Here is where you can see all the tables that support this construction procurement scenario.

@@ -96,158 +96,170 @@ This lab assumes you have:
```
-4. Run the code block to connect to the database.
+4. Run the code block to connect to the database.

+## Task 5: Create a function to retrieve procurement data from the database
-## Task 5: Create a Function to retrieve data from the database.
+You will query project procurement data from the `procurement_profiles_dv` JSON duality view, which combines `CONSTRUCTION_PROCUREMENTS` and related procurement fields into one JSON document. This task will:
-You will query customer data from the `clients_dv` JSON duality view, which combines data from CUSTOMERS, LOAN_APPLICATIONS, and related tables. This task will:
-
-- **Define a Function**: Create a reusable function `fetch_customer_data` to query the database by customer ID, extracting the JSON data for a specific customer.
-
-- **Use an Example**: Fetch data for customer `1000` (James Smith) to demonstrate the process.
-
-- **Display the Results**: Format the retrieved data into a pandas DataFrame for a clear, tabular presentation, showing key details like name, income, credit score, and total debt.
+- **Define a Function**: Create a reusable function `fetch_procurement_data` to query the database by project ID, extracting the JSON data for a specific procurement.
+- **Use an Example**: Fetch data for project `1001` (`P1001 Downtown Mixed-Use Tower`) to demonstrate the process.
+- **Display the Results**: Format the retrieved data into a pandas DataFrame for a clear, tabular presentation, showing key details like project name, location, project phase, required trade, procurement urgency, budget range, and risk level.
1. Copy and paste the code below into the new notebook.
```python
-def fetch_customer_data(customer_id):
+def fetch_procurement_data(project_id):
cursor.execute(
- "SELECT data FROM clients_dv WHERE JSON_VALUE(data, '$._id') = :customer_id",
- {'customer_id': customer_id}
+ "SELECT data FROM procurement_profiles_dv WHERE JSON_VALUE(data, '$._id') = :project_id",
+ {'project_id': project_id}
)
result = cursor.fetchone()
return json.loads(result[0]) if result and isinstance(result[0], str) else result[0] if result else None
-selected_customer_id = "CUST_1000"
-customer_json = fetch_customer_data(selected_customer_id)
+selected_project_id = "1001"
+procurement_json = fetch_procurement_data(selected_project_id)
-if customer_json:
- loan_app = customer_json.get("loanApplications", [{}])[0]
- print(f"Customer: {customer_json['firstName']} {customer_json['lastName']}")
- print(f"Loan Status: {loan_app['loanStatus']}")
+if procurement_json:
+ print(f"Project: {procurement_json['projectName']}")
+ print(f"Status: {procurement_json['projectStatus']}")
desired_fields = [
- ("Customer ID", selected_customer_id),
- ("Application ID", loan_app.get("applicationId", "")),
- ("First Name", customer_json.get("firstName", "")),
- ("Last Name", customer_json.get("lastName", "")),
- ("City", customer_json.get("city", "")),
- ("State", customer_json.get("state", "")),
- ("Zip code", customer_json.get("zipCode", "")),
- ("Age", customer_json.get("age", 0)),
- ("Income", customer_json.get("income", 0)),
- ("Credit score", loan_app.get("creditScore", 600)),
- ("Requested loan amount", loan_app.get("requestedLoanAmount", 0)),
- ("Total Debt", loan_app.get("totalDebt", 0)),
- ("Loan status", loan_app.get("loanStatus", "Pending Review"))
+ ("Project ID", selected_project_id),
+ ("Project Code", procurement_json.get("projectCode", "")),
+ ("Project Name", procurement_json.get("projectName", "")),
+ ("Location", procurement_json.get("location", "")),
+ ("Project Phase", procurement_json.get("projectPhase", "")),
+ ("Required Trade", procurement_json.get("requiredTrade", "")),
+ ("Procurement Urgency", procurement_json.get("procurementUrgency", "")),
+ ("Budget Range", procurement_json.get("budgetRange", "")),
+ ("Risk Level", procurement_json.get("riskLevel", "")),
+ ("Project Status", procurement_json.get("projectStatus", "Pending Review"))
]
- df_customer_details = pd.DataFrame(
+ df_procurement_details = pd.DataFrame(
{field_name: [field_value] for field_name, field_value in desired_fields}
)
- display(df_customer_details)
+ display(df_procurement_details)
else:
- print("No data found for customer ID:", selected_customer_id)
+ print("No data found for project ID:", selected_project_id)
- ```
+ ```
-2. Click the "Run" button to see James Smith’s profile. The output will include a brief summary (name and loan status) followed by a detailed table. If no data is found for the specified ID, a message will indicate this, helping you debug potential issues like an incorrect ID or empty database. The output will display a DataFrame containing the customer details for the selected customer ID.
+2. Click the **Run** button to see `P1001 Downtown Mixed-Use Tower`. The output will include a brief summary followed by a detailed table. If no data is found for the specified ID, a message will indicate this, helping you debug potential issues like an incorrect ID or empty database.

+ If you completed Lab 1: Run the Demo earlier, this is what gets
+ printed out when the construction procurement officer opens project
+ `1001`.
-If you completed Lab 1: Run the Demo earlier, this is what gets printed out when the loan officer clicks on the customer 1000. You just built it, well done!
-
-## Task 6: Create a function to generate recommendations for the customer
+## Task 6: Create a function to generate procurement recommendations
-In a new cell, define a function `generate_recommendations` to generate loan recommendations.
+In a new cell, define a function `generate_procurement_recommendations` to generate supplier recommendations.
-With customer profiles in place, you will use OCI Generative AI to generate personalized loan recommendations.
+With procurement profiles in place, you will use OCI Generative AI to generate personalized procurement recommendations.
Here’s what we’ll do:
-- **Fetch Mock Loan Data**: Retrieve all mock loan data and combine them with customer data.
-- **Build a Prompt**: Construct a structured prompt that combines the customer’s profile with loan requests instructing the LLM to evaluate and recommend a loan (APPROVE, REQUEST INFO, DENY) based solely on this data.
-- **Use OCI Generative AI**: Send the prompt to the **meta.llama-3.2-90b-vision-instruct** model via OCI’s inference client, which will process the input and generate a response.
-- **Format the Output**: Display the recommendations with styled headers and lists, covering evaluation, top picks, and explanations—making it easy to read and understand.
+
+- **Fetch Supplier Data**: Retrieve the available supplier options and combine them with the selected procurement data.
+- **Build a Prompt**: Construct a structured prompt that combines the project’s procurement profile with supplier options, instructing the LLM to evaluate and recommend suppliers (`APPROVE`, `REQUEST INFO`, `DENY`) based solely on this data.
+- **Use OCI Generative AI**: Send the prompt to the `meta.llama-3.2-90b-vision-instruct` model via OCI’s inference client.
+- **Format the Output**: Display the recommendations with structured sections covering evaluation, top supplier options, and explanations.
1. Copy and paste the code in a new cell:
```python
- # Fetch Mock Loan Data
-cursor.execute("SELECT loan_id, loan_provider_name, loan_type, interest_rate, origination_fee, time_to_close, credit_score, debt_to_income_ratio, income, down_payment_percent, is_first_time_home_buyer FROM MOCK_LOAN_DATA")
-df_mock_loans = pd.DataFrame(cursor.fetchall(), columns=["LOAN_ID", "LOAN_PROVIDER_NAME", "LOAN_TYPE", "INTEREST_RATE", "ORIGINATION_FEE", "TIME_TO_CLOSE", "CREDIT_SCORE", "DEBT_TO_INCOME_RATIO", "INCOME", "DOWN_PAYMENT_PERCENT", "IS_FIRST_TIME_HOME_BUYER"])
+ # Fetch supplier options
+cursor.execute("SELECT supplier_option_id, supplier_name, trade_specialty, experience_summary, compliance_status, on_time_delivery_rate, delivery_window_weeks, capacity_status, project_fit, recommendation_status FROM supplier_option_catalog")
+df_supplier_options = pd.DataFrame(cursor.fetchall(), columns=["SUPPLIER_OPTION_ID", "SUPPLIER_NAME", "TRADE_SPECIALTY", "EXPERIENCE_SUMMARY", "COMPLIANCE_STATUS", "ON_TIME_DELIVERY_RATE", "DELIVERY_WINDOW_WEEKS", "CAPACITY_STATUS", "PROJECT_FIT", "RECOMMENDATION_STATUS"])
# Generate Recommendations
-def generate_recommendations(customer_id, customer_json, df_mock_loans):
- loan_app = customer_json.get("loanApplications", [{}])[0]
- available_loans_text = "\n".join([f"{loan['LOAN_ID']}: {loan['LOAN_TYPE']} | {loan['INTEREST_RATE']}% interest | Credit Score: {loan['CREDIT_SCORE']} | DTI: {loan['DEBT_TO_INCOME_RATIO']}" for loan in df_mock_loans.to_dict(orient='records')])
- customer_profile_text = "\n".join([f"- {key.replace('_', ' ').title()}: {value}" for key, value in {**customer_json, **loan_app}.items() if key not in ["embedding_vector", "ai_response_vector", "chunk_vector"]])
-
- prompt = f"""[INST] <>You are a Loan Approver AI. Use only the provided context to evaluate the applicant’s profile and recommend loans. Format results as plain text with numbered sections (1. Comprehensive Evaluation, 2. Top 3 Loan Recommendations, 3. Recommendations Explanations, 4. Final Suggestion). Use newlines between sections.> [/INST]
- [INST]Available Loan Options:\n{available_loans_text}\nApplicant's Full Profile:\n{customer_profile_text}\nTasks:\n1. Comprehensive Evaluation\n2. Top 3 Loan Recommendations\n3. Recommendations Explanations\n4. Final Suggestion"""
+def generate_procurement_recommendations(project_id, procurement_json, df_supplier_options):
+ available_suppliers_text = "\n".join([
+ f"{supplier['SUPPLIER_OPTION_ID']}: {supplier['SUPPLIER_NAME']} | {supplier['TRADE_SPECIALTY']} | "
+ f"Compliance: {supplier['COMPLIANCE_STATUS']} | On-Time Delivery: {supplier['ON_TIME_DELIVERY_RATE']} | "
+ f"Delivery Window: {supplier['DELIVERY_WINDOW_WEEKS']} weeks | Capacity: {supplier['CAPACITY_STATUS']}"
+ for supplier in df_supplier_options.to_dict(orient='records')
+ ])
+ procurement_profile_text = "\n".join([
+ f"- {key.replace('_', ' ').title()}: {value}"
+ for key, value in procurement_json.items()
+ if key not in ["embedding_vector", "ai_response_vector", "chunk_vector", "supplierRecommendations"]
+ ])
+
+ prompt = f"""[INST] <>You are a Construction Procurement AI. Use only the provided context to evaluate the procurement and recommend the best supplier next steps. Choose only from APPROVE, REQUEST INFO, or DENY. Format results as plain text with numbered sections (1. Comprehensive Procurement Evaluation, 2. Top 3 Supplier Recommendations, 3. Recommendation Explanations, 4. Final Suggestion). Use newlines between sections.> [/INST]
+ [INST]Available Supplier Options:\n{available_suppliers_text}\nProcurement Profile:\n{procurement_profile_text}\nTasks:\n1. Comprehensive Procurement Evaluation\n2. Top 3 Supplier Recommendations\n3. Recommendation Explanations\n4. Final Suggestion"""
print("Generating AI response...")
print(" ")
-
- genai_client = oci.generative_ai_inference.GenerativeAiInferenceClient(config=oci.config.from_file(os.getenv("OCI_CONFIG_PATH", "~/.oci/config")), service_endpoint=os.getenv("ENDPOINT"))
+
+ genai_client = oci.generative_ai_inference.GenerativeAiInferenceClient(
+ config=oci.config.from_file(os.getenv("OCI_CONFIG_PATH", "~/.oci/config")),
+ service_endpoint=os.getenv("ENDPOINT")
+ )
chat_detail = oci.generative_ai_inference.models.ChatDetails(
compartment_id=os.getenv("COMPARTMENT_OCID"),
- chat_request=oci.generative_ai_inference.models.GenericChatRequest(messages=[oci.generative_ai_inference.models.UserMessage(content=[oci.generative_ai_inference.models.TextContent(text=prompt)])], temperature=0.0, top_p=1.00),
- serving_mode=oci.generative_ai_inference.models.OnDemandServingMode(model_id="meta.llama-3.2-90b-vision-instruct") #here is where we are calling our llm
+ chat_request=oci.generative_ai_inference.models.GenericChatRequest(
+ messages=[oci.generative_ai_inference.models.UserMessage(
+ content=[oci.generative_ai_inference.models.TextContent(text=prompt)]
+ )],
+ temperature=0.0,
+ top_p=1.00
+ ),
+ serving_mode=oci.generative_ai_inference.models.OnDemandServingMode(
+ model_id="meta.llama-3.2-90b-vision-instruct"
+ )
)
chat_response = genai_client.chat(chat_detail)
recommendations = chat_response.data.chat_response.choices[0].message.content[0].text
return recommendations
- recommendations = generate_recommendations(selected_customer_id, customer_json, df_mock_loans)
- print(recommendations)
+recommendations = generate_procurement_recommendations(selected_project_id, procurement_json, df_supplier_options)
+print(recommendations)
```
-2. Click the "Run" button to execute the code. Note that this will take time to run. Be patient, you will get the recommendations from the LLM shortly.
+2. Click the **Run** button to execute the code. Note that this will take time to run. Be patient while the LLM evaluates the procurement and returns its recommendations.

-3. Review the output. In the demo, this is where you selected the "Navigate to Decisions" button as the Approval Officer. You just used AI to get recommendations for the approval officer which would have taken them hours to do, congratulations!
+3. Review the output. In the demo, this is where you selected the **Navigate To Project Decisions** button as the construction procurement officer.
- >*Note:* Your result may be different due to non-deterministic character of generative AI.
+ >*Note:* Your result may be different due to the non-deterministic nature of generative AI.

-## Task 7: Chunk & Store the Recommendations
+## Task 7: Chunk & Store the Recommendations
-In this section we will be chunking and storing the recommendations.
+In this section we will chunk and store the recommendations.
-- We delete prior chunks for this customer.
+- We delete prior chunks for this project.
- We use `VECTOR_CHUNKS` to insert the chunks.
-- The chunks will be inserted into `LOAN_CHUNK` with unique `CHUNK_ID` = (`size + chunk_offset`).
+- The chunks are inserted into `PROCUREMENT_RECOMMENDATION_CHUNK` with unique `CHUNK_ID` = (`size + chunk_offset`).
- We display a data frame summary to show the chunks.
1. Copy the following code and run it in a new cell:
```python
- # Clean any prior chunks for this customer
-cursor.execute("DELETE FROM LOAN_CHUNK WHERE CUSTOMER_ID = :cust_id", {'cust_id': selected_customer_id})
+ # Clean any prior chunks for this project
+cursor.execute("DELETE FROM PROCUREMENT_RECOMMENDATION_CHUNK WHERE PROJECT_ID = :project_id", {'project_id': selected_project_id})
connection.commit()
-# Choose your chunk sizes (add more like 200, 500 if you want)
-chunk_sizes = [50] # e.g., [50, 200, 500]
+chunk_sizes = [50]
-# Insert chunks using VECTOR_CHUNKS. Make CHUNK_ID unique by (size + chunk_offset).
for size in chunk_sizes:
insert_sql = f"""
- INSERT INTO LOAN_CHUNK (CUSTOMER_ID, CHUNK_ID, CHUNK_TEXT)
- SELECT :cust_id,
+ INSERT INTO PROCUREMENT_RECOMMENDATION_CHUNK (PROJECT_ID, CHUNK_ID, CHUNK_TEXT)
+ SELECT :project_id,
:chunk_size + vc.chunk_offset,
vc.chunk_text
FROM (SELECT :rec_text AS txt FROM dual) s,
@@ -263,19 +275,17 @@ for size in chunk_sizes:
"""
cursor.execute(
insert_sql,
- {'cust_id': selected_customer_id, 'chunk_size': size, 'rec_text': recommendations}
+ {'project_id': selected_project_id, 'chunk_size': size, 'rec_text': recommendations}
)
-# Fetch chunks for preview
cursor.execute("""
SELECT CHUNK_ID, CHUNK_TEXT
- FROM LOAN_CHUNK
- WHERE CUSTOMER_ID = :cust_id
+ FROM PROCUREMENT_RECOMMENDATION_CHUNK
+ WHERE PROJECT_ID = :project_id
ORDER BY CHUNK_ID
-""", {'cust_id': selected_customer_id})
+""", {'project_id': selected_project_id})
rows = cursor.fetchall()
-# Build a compact dataframe
def _lob_to_str(v): return v.read() if isinstance(v, oracledb.LOB) else v
items = []
@@ -288,9 +298,9 @@ for cid, ctext in rows:
"Preview": (txt[:160] + "…") if len(txt) > 160 else txt
})
- df_chunks = pd.DataFrame(items).sort_values("CHUNK_ID")
- connection.commit()
-print(f"✅ Task 7 complete: recommendation chunked for customer {selected_customer_id} (sizes: {chunk_sizes}).")
+df_chunks = pd.DataFrame(items).sort_values("CHUNK_ID")
+connection.commit()
+print(f"✅ Task 7 complete: recommendation chunked for project {selected_project_id} (sizes: {chunk_sizes}).")
display(df_chunks)
```
@@ -299,41 +309,39 @@ display(df_chunks)

-3. Review the output to see the top recommendations.
+3. Review the output to see the chunked procurement recommendations.

-## Task 8: Create a function to create embeddings - Use Oracle AI Database to create vector data
-
-To handle follow-up questions, you will enhance the system with an AI Guru powered by Oracle AI Database’s Vector Search and Retrieval-Augmented Generation (RAG). The AI Guru will be able to answer questions about the loan application and provide recommendations based on the data.
+## Task 8: Create embeddings - Use Oracle AI Database to create vector data
-Before answering questions, we need to prepare the data by vectoring the recommendations. This step:
+To handle follow-up questions, you will enhance the system with an AI Guru powered by Oracle AI Database’s Vector Search and Retrieval-Augmented Generation (RAG). The AI Guru will be able to answer questions about the procurement and provide recommendations based on the data.
- - **Stores Recommendations**: Inserts the full recommendation text (from previous cell) as a single chunk if not already present.
+Before answering questions, we need to prepare the data by vectorizing the recommendations. This step:
- - **Generates Embeddings**: This is a new feature in Oracle AI Database that allows you to create embeddings directly within the database, eliminating the need for external tools or APIs. The `dbms_vector_chain.utl_to_embedding` function takes the recommendation text as input and returns an embedding vector.
-
- - **Stores Embeddings**: Inserts the generated embedding vector into a table called `LOAN_CHUNKS`.
+- **Stores Recommendations**: Uses the recommendation text from the previous cell.
+- **Generates Embeddings**: Uses `dbms_vector_chain.utl_to_embedding` to create vectors directly in the database.
+- **Stores Embeddings**: Inserts the generated embedding vector into `PROCUREMENT_RECOMMENDATION_CHUNK`.
1. Run and review the code in a new cell:
```python
- # Create Embeddings for Loan Chunks ----
+ # Create embeddings for procurement recommendation chunks
cursor.execute("""
- UPDATE LOAN_CHUNK
+ UPDATE PROCUREMENT_RECOMMENDATION_CHUNK
SET CHUNK_VECTOR = dbms_vector_chain.utl_to_embedding(
CHUNK_TEXT,
JSON('{"provider":"database","model":"DEMO_MODEL","dimensions":384}')
)
- WHERE CUSTOMER_ID = :cust_id
-""", {'cust_id': selected_customer_id})
+ WHERE PROJECT_ID = :project_id
+""", {'project_id': selected_project_id})
connection.commit()
-print("✅ Task 8 complete: embedded vectors for LOAN_CHUNK rows.")
+print("✅ Task 8 complete: embedded vectors for PROCUREMENT_RECOMMENDATION_CHUNK rows.")
```
-2. Click the "Run" button to execute the code and review the output.
+2. Click the **Run** button to execute the code and review the output.

@@ -341,19 +349,19 @@ print("✅ Task 8 complete: embedded vectors for LOAN_CHUNK rows.")
Now that the recommendations are vectorized, we can process a user’s question:
-```Can we recommend any other loans to James?```
+```Which supplier option best fits the Downtown Mixed-Use Tower procurement if we prioritize strong compliance and delivery reliability?```
This step:
- - **Vectorizes the question**: Embeds the question using `DEMO_MODEL` via `dbms_vector_chain.utl_to_embedding`.
- - **Performs AI Vector Search**: Retrieve the relevant recommendation text from `LOAN_CHUNKS` table. Then find the most relevant recommendations using similarity search.
- - **Use RAG**: Combines the customer profile, policy rules using the retrieved recommendation context.
+- **Vectorizes the question**: Embeds the question using `DEMO_MODEL` via `dbms_vector_chain.utl_to_embedding`.
+- **Performs AI Vector Search**: Retrieves the most relevant recommendation text from `PROCUREMENT_RECOMMENDATION_CHUNK`.
+- **Uses RAG**: Combines the procurement profile, supplier options, and retrieved recommendation context.
1. Copy the code block below to implement RAG:
```python
-question = "Can we recommend any other loans to James?"
+question = "Which supplier option best fits the Downtown Mixed-Use Tower procurement if we prioritize strong compliance and delivery reliability?"
def vectorize_question(q):
cursor.execute("""
@@ -369,47 +377,42 @@ print("Processing your question using AI Vector Search across chunked recommenda
try:
q_vec = vectorize_question(question)
- # Retrieve top recommendation chunks (across all sizes) for this customer
cursor.execute("""
SELECT CHUNK_ID, CHUNK_TEXT
- FROM LOAN_CHUNK
- WHERE CUSTOMER_ID = :cust_id
+ FROM PROCUREMENT_RECOMMENDATION_CHUNK
+ WHERE PROJECT_ID = :project_id
AND CHUNK_VECTOR IS NOT NULL
ORDER BY VECTOR_DISTANCE(CHUNK_VECTOR, :qv, COSINE)
FETCH FIRST 4 ROWS ONLY
- """, {'cust_id': selected_customer_id, 'qv': q_vec})
+ """, {'project_id': selected_project_id, 'qv': q_vec})
retrieved = [
(r[0], r[1].read() if isinstance(r[1], oracledb.LOB) else r[1])
for r in cursor.fetchall()
]
if not retrieved:
- # Fallback to full text as one chunk
retrieved = [(0, recommendations)]
- # Prepare clean context for the LLM
- cleaned = [re.sub(r'[^\w\s\d.,\-\'"]', ' ', t).strip() for _, t in retrieved]
+ cleaned = [re.sub(r"[^\\w\\s\\d.,\\-'\"]", " ", t).strip() for _, t in retrieved]
docs_as_one_string = "\n=========\n".join(cleaned) + "\n=========\n"
- # Rebuild available loans + customer profile
- available_loans_text = "\n".join(
- [f"{loan['LOAN_ID']}: {loan['LOAN_TYPE']} | {loan['INTEREST_RATE']}% interest | "
- f"Credit Score: {loan['CREDIT_SCORE']} | DTI: {loan['DEBT_TO_INCOME_RATIO']} | "
- f"Origination Fee: ${loan['ORIGINATION_FEE']} | Time to Close: {loan['TIME_TO_CLOSE']} days"
- for loan in df_mock_loans.to_dict(orient='records')]
- )
- loan_app = customer_json.get("loanApplications", [{}])[0]
- customer_profile_text = "\n".join(
- [f"- {k.replace('_',' ').title()}: {v}"
- for k, v in {**customer_json, **loan_app}.items()
- if k not in ["embedding_vector","ai_response_vector","chunk_vector"]]
- )
+ available_suppliers_text = "\n".join([
+ f"{supplier['SUPPLIER_OPTION_ID']}: {supplier['SUPPLIER_NAME']} | {supplier['TRADE_SPECIALTY']} | "
+ f"Compliance: {supplier['COMPLIANCE_STATUS']} | On-Time Delivery: {supplier['ON_TIME_DELIVERY_RATE']} | "
+ f"Delivery Window: {supplier['DELIVERY_WINDOW_WEEKS']} weeks | Capacity: {supplier['CAPACITY_STATUS']}"
+ for supplier in df_supplier_options.to_dict(orient='records')
+ ])
+ procurement_profile_text = "\n".join([
+ f"- {k.replace('_',' ').title()}: {v}"
+ for k, v in procurement_json.items()
+ if k not in ["embedding_vector","ai_response_vector","chunk_vector","supplierRecommendations"]
+ ])
rag_prompt = f"""\
[INST] <>
-You are AI Loan Guru. Use only the provided context to answer. Do not mention sources outside of the provided context.
+You are AI Procurement Guru. Use only the provided context to answer. Do not mention sources outside of the provided context.
Do NOT provide warnings, disclaimers, or exceed the specified response length.
-Keep under 300 words. Be specific and actionable. Have the ability to respond in Spanish, French, Italian, German, and Portuguese if asked.
+Keep under 300 words. Be specific and actionable.
<> [/INST]
[INST]
Question: "{question}"
@@ -417,15 +420,15 @@ Question: "{question}"
# Context (top chunks from prior AI recommendations):
{docs_as_one_string}
-# Available Loan Options:
-{available_loans_text}
+# Available Supplier Options:
+{available_suppliers_text}
-# Applicant Profile:
-{customer_profile_text}
+# Procurement Profile:
+{procurement_profile_text}
Tasks:
1) Provide a direct answer to the question.
-2) Briefly justify based on profile + loan options.
+2) Briefly justify based on the procurement profile and available supplier options.
[/INST]"""
print("Generating AI response...")
@@ -449,12 +452,11 @@ Tasks:
)
chat_response = genai_client.chat(chat_detail)
ai_response = chat_response.data.chat_response.choices[0].message.content[0].text
- ai_response = re.sub(r'[^\w\s\d.,\-\'"]', ' ', ai_response)
+ ai_response = re.sub(r"[^\\w\\s\\d.,\\-'\"]", " ", ai_response)
- print("\n🤖 AI Loan Guru Response:")
+ print("\n🤖 AI Procurement Guru Response:")
print(ai_response)
- # Print which chunks were retrieved (for transparency/debug)
print("\n📑 Retrieved Chunks Used in Response:")
for cid, text in retrieved:
preview = text[:140].replace("\n", " ") + ("..." if len(text) > 140 else "")
@@ -465,13 +467,13 @@ except Exception as e:
```
-2. Click the "Run" button to execute the code.
+2. Click the **Run** button to execute the code.

3. Review the result.
- >*Note:* Your result may be different due to non-deterministic character of generative AI.
+ >*Note:* Your result may be different due to the non-deterministic nature of generative AI.

@@ -482,12 +484,12 @@ Congratulations! You implemented a RAG process in Oracle AI Database using Pytho
To summarize:
* You created a function to connect to Oracle AI Database using the Oracle Python driver `oracledb`.
-* You created a function to retrieve customer data.
-* You created a function to connect to OCI Generative AI and create a first recommendation.
-* You created a function to create embeddings of the customer data using Oracle AI Database.
+* You created a function to retrieve procurement data.
+* You created a function to connect to OCI Generative AI and create procurement recommendations.
+* You created embeddings of procurement recommendation data using Oracle AI Database.
* And finally, you implemented a RAG process in Oracle AI Database using Python.
-Congratulations, you completed the lab!
+Congratulations, you completed the lab.
You may now proceed to the next lab.
@@ -498,4 +500,4 @@ You may now proceed to the next lab.
## Acknowledgements
* **Authors** - Francis Regalado
-* **Last Updated By/Date** - Uma Kumar, December 2025
\ No newline at end of file
+* **Last Updated By/Date** - Taylor Zheng, Uma Kumar, Deion Locklear, Daniet Hart, July 2026
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/files/starter-file.sql b/dev-ai-app-dev-constructioneng-aiexperience/build/files/starter-file.sql
index 9d7e762e8..b29250621 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/build/files/starter-file.sql
+++ b/dev-ai-app-dev-constructioneng-aiexperience/build/files/starter-file.sql
@@ -1,101 +1,66 @@
-/* NOTE: Files cannot contain empty lines (line breaks) */
-/* Specify the base URL that you copied from your files in OCI Object Storage in the define base_URL line below*/
-/* change idthydc0kinr to your real namespace. The name is case-sensitive. */
-/* change ADWCLab to your real bucket name. The name is case-sensitive. */
-/* change us-phoenix-1 to your real region name. The name is case-sensitive. */
-/* you can find these values on the OCI Console .. Storage .. Object Storage screen */
-set define on
-define base_URL='https://objectstorage.us-phoenix-1.oraclecloud.com/n/idthydc0kinr/b/ADWCLab/o'
-/* copy Channels table */
-begin
- dbms_cloud.copy_data(
- table_name =>'CHANNELS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/chan_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true')
- );
-end;
-/
-/* copy Countries table */
-begin
- dbms_cloud.copy_data(
- table_name =>'COUNTRIES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/coun_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true')
- );
-end;
-/
-/* Copy customers */
-begin
- dbms_cloud.copy_data(
- table_name =>'CUSTOMERS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/cust1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'SUPPLEMENTARY_DEMOGRAPHICS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/dem1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'SALES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/dmsal_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'PRODUCTS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/prod1v3.dat',
- format => json_object('delimiter' value '|', 'quote' value '^', 'ignoremissingcolumns' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'PROMOTIONS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/prom1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'SALES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/sale1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'TIMES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/time_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'COSTS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/costs.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'dateformat' value 'YYYY-MM-DD', 'blankasnull' value 'true')
- );
-end;
-/
+/* Construction procurement starter schema for the AI Experience workshop */
+
+drop view if exists procurement_profiles_dv;
+drop table if exists procurement_recommendation_chunk;
+drop table if exists supplier_option_catalog;
+drop table if exists construction_procurements;
+
+create table if not exists construction_procurements (
+ project_id varchar2(30) primary key,
+ project_code varchar2(30),
+ project_name varchar2(200),
+ location varchar2(200),
+ project_phase varchar2(100),
+ required_trade varchar2(100),
+ procurement_urgency varchar2(50),
+ budget_range varchar2(50),
+ risk_level varchar2(50),
+ project_status varchar2(40)
+);
+
+create table if not exists supplier_option_catalog (
+ supplier_option_id number primary key,
+ supplier_name varchar2(200),
+ trade_specialty varchar2(120),
+ experience_summary varchar2(400),
+ compliance_status varchar2(120),
+ on_time_delivery_rate varchar2(50),
+ delivery_window_weeks number,
+ capacity_status varchar2(100),
+ project_fit varchar2(200),
+ recommendation_status varchar2(40)
+);
+
+create table if not exists procurement_recommendation_chunk (
+ project_id varchar2(30) not null,
+ chunk_id number not null,
+ chunk_text clob,
+ chunk_vector vector(384, float32),
+ constraint procurement_recommendation_chunk_pk primary key (project_id, chunk_id)
+);
+
+insert into construction_procurements (project_id, project_code, project_name, location, project_phase, required_trade, procurement_urgency, budget_range, risk_level, project_status) values
+('1001', 'P1001', 'Downtown Mixed-Use Tower', 'Chicago, IL', 'Structural Frame', 'Structural Steel', 'High', '$4.0-5.5M', 'Low Risk', 'Pending Review'),
+('1003', 'P1003', 'Harbor Seismic Retrofit', 'Long Beach, CA', 'Retrofit', 'Seismic Steel Retrofit', 'Critical', '$6.5-8.0M', 'High Risk', 'Pending Review'),
+('1004', 'P1004', 'North Campus Lab Expansion', 'Austin, TX', 'Procurement Planning', 'Mechanical + Lab Fit-Out', 'Medium', '$1.1-1.6M', 'Medium Risk', 'Pending Review');
+
+insert into supplier_option_catalog (supplier_option_id, supplier_name, trade_specialty, experience_summary, compliance_status, on_time_delivery_rate, delivery_window_weeks, capacity_status, project_fit, recommendation_status) values
+(7001, 'Atlas Structural Fabrication', 'Structural Steel', 'Strong mid-rise steel frame project experience', 'Current AISC and AWS documentation', '96%', 6, 'Confirmed', 'High fit for six-week downtown tower delivery', 'Recommended'),
+(7002, 'Metro Build Systems', 'Structural Steel', 'Broad tower podium and transfer deck experience', 'AISC current, AWS renewal pending', '92%', 8, 'Limited', 'Good fit but tighter capacity window', 'Review'),
+(7003, 'Coastal Retrofit Metals', 'Seismic Retrofit Steel', 'Extensive retrofit portfolio in coastal zones', 'Compliance gaps under review', '88%', 10, 'Conditional', 'Technically aligned but elevated risk profile', 'Denied'),
+(7004, 'Northline MEP Supply', 'Mechanical + Lab Fit-Out', 'University and life-science lab package experience', 'Current QA and safety files', '94%', 7, 'Confirmed', 'Good fit for updated lab expansion budget', 'Recommended');
+
+create or replace json relational duality view procurement_profiles_dv as
+ construction_procurements @insert @update @delete
+ {
+ _id : project_id,
+ projectCode : project_code,
+ projectName : project_name,
+ location,
+ projectPhase : project_phase,
+ requiredTrade : required_trade,
+ procurementUrgency : procurement_urgency,
+ budgetRange : budget_range,
+ riskLevel : risk_level,
+ projectStatus : project_status
+ };
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task1.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task1.png
index bb1d91bc8..59dfe43c7 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task1.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task1.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task3.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task3.png
index a8ebd17ed..9eea1695a 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task3.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task3.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task4.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task4.png
index bd406001a..c841c299a 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task4.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/lab4task4.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task4recommendations.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task4recommendations.png
index 8f3a21424..a1da02284 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task4recommendations.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task4recommendations.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task5.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task5.png
index 1782b5dc4..e83375f48 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task5.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task5.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7.png
index 28bcf42a3..e782fc591 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7recs.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7recs.png
index b8fa76aa1..e41997718 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7recs.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7recs.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7results.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7results.png
index 89210f766..d713566ce 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7results.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task7results.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task8.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task8.png
index 5b5642b76..db286ae04 100644
Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/task8.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/task8.png differ
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/codingbasics/codingbasics.md b/dev-ai-app-dev-constructioneng-aiexperience/codingbasics/codingbasics.md
index 9d1abd611..0f254d572 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/codingbasics/codingbasics.md
+++ b/dev-ai-app-dev-constructioneng-aiexperience/codingbasics/codingbasics.md
@@ -3,17 +3,17 @@
## Introduction
-At Seer Holdings, developers are building a next-generation loan approval system that needs to combine enterprise-grade data governance with modern AI capabilities. But before GenAI or vector search can be applied, one thing must be true:
+At Seer Holdings, developers are building a next-generation construction procurement system that needs to combine enterprise-grade data governance with modern AI capabilities. But before GenAI or vector search can be applied, one thing must be true:
👉 The data must be in the right shape — accessible, trustworthy, and programmable.
In this lab, you’ll act as a developer on the Seer Holdings data team. Your job is to build the foundational logic that powers the application’s intelligence layer. That means:
-- Creating and querying relational tables that represent real loan and customer data using Python
+- Creating and querying relational tables that represent real procurement and supplier data using Python
- Converting that data into **JSON documents** using **JSON Duality Views**
- Using **MongoDB-style syntax** via Oracle’s Mongo API to interact with the same data — without needing to duplicate or move it
-These capabilities make Oracle AI Database a **developer-friendly**, **multi-model platform**. You’ll write less glue code, eliminate data movement, and stay focused on the real task: powering intelligent loan workflows.
+These capabilities make Oracle AI Database a **developer-friendly**, **multi-model platform**. You’ll write less glue code, eliminate data movement, and stay focused on the real task: powering intelligent construction procurement workflows.
> 💡 Everything you implement here becomes the data foundation for Retrieval-Augmented Generation (RAG) and AI Vector Search in upcoming labs.
@@ -50,11 +50,7 @@ All of the coding examples will be executed in a new Jupyter Notebook.
## Task 2: Connect to the database using Python
-<<<<<<< HEAD
-In this first task, you will connect to an Oracle AI Database instance using Oracle's Python driver, `oracledb`. `oracledb` is available in PyPi (`pip install oracledb`) and supports in its latest version all of the advanced features of the Oracle Database, including JSON and VECTOR.
-=======
In this first task, you will connect to an Oracle AI Database instance using Oracle's Python driver, `oracledb`. `oracledb` is available in PyPi (`pip install oracledb`) and supports in its latest version all of the advanced features of the Oracle AI Database, including JSON and VECTOR.
->>>>>>> upstream/main
1. In the newly created Jupyter Notebook, copy and paste the following code block into an empty cell. This code block imports the `oracledb` Python driver and other libraries that help us to securely read credentials from the environment variables.
@@ -86,7 +82,15 @@ In this first task, you will connect to an Oracle AI Database instance using Ora

->**Note:** The last line, `cursor = connection.cursor()`, creates a cursor object from the established Oracle AI Database connection. A cursor acts as a control structure that enables the execution of SQL queries and retrieval of results from the database. It is essential for sending SQL commands, fetching data, and iterating through query results. We will be using the cursor object in later steps of this lab. The object persists in the notebook session, so you can use it in subsequent cells without re-establishing the connection.
+ > **Note:** The last line, `cursor = connection.cursor()`, creates
+ > a cursor object from the established Oracle AI Database
+ > connection. A cursor acts as a control structure that enables the
+ > execution of SQL queries and retrieval of results from the
+ > database. It is essential for sending SQL commands, fetching
+ > data, and iterating through query results. We will be using the
+ > cursor object in later steps of this lab. The object persists in
+ > the notebook session, so you can use it in subsequent cells
+ > without re-establishing the connection.
## Task 3: Create tables and insert data
@@ -141,7 +145,9 @@ Now, that we have established a connection, we can start creating our tables and
```
->**Note:** We are creating a function called `query_orders()` that will allow us to query our table. We can use the same function in one of the following tasks
+ > **Note:** We are creating a function called `query_orders()`
+ > that will allow us to query our table. We can use the same
+ > function in one of the following tasks.
3. Run your code (**shift+enter**) and see what happens. You should get a list of all the orders in our table.
@@ -197,11 +203,13 @@ Now, that we have established a connection, we can start creating our tables and

-### **Task Summary**
+ ### **Task Summary**
-Congratulations! You successfully created two new tables with sample data using Python and Oracle AI Database.
+ Congratulations! You successfully created two new tables with
+ sample data using Python and Oracle AI Database.
-You also created a function that allows you to query your new table which we will use in some of the following tasks
+ You also created a function that allows you to query your new table
+ which we will use in some of the following tasks.
## Task 4: Create a JSON Duality View
@@ -269,7 +277,12 @@ Next, we want to explore how we can use a **JSON Duality View** to query our new

->💡 **JSON Duality Views** automatically maps relational columns to JSON documents (and vice versa) in the same table, letting you store data in a traditional schema but also access it as if it were a JSON object. So even though you’ve coded a JSON view in Python, you can switch over to standard SQL queries without duplicating data or maintaining extra structures. Super cool!
+ > 💡 **JSON Duality Views** automatically maps relational columns
+ > to JSON documents (and vice versa) in the same table, letting you
+ > store data in a traditional schema but also access it as if it
+ > were a JSON object. So even though you have coded a JSON view in
+ > Python, you can switch over to standard SQL queries without
+ > duplicating data or maintaining extra structures.
3. Let's create a new function that allows us to query our new JSON Duality View. This time however, we will enhance our function to allow using input parameters. Instead of retrieving all rows, we want to write a function that returns only a specific row based on the first name of a customer. Copy the following code into a new cell and run it.
@@ -311,7 +324,9 @@ Next, we want to explore how we can use a **JSON Duality View** to query our new
🔴 **`query_dv("Dan")`** - Here we are calling our query function again, but this time passing in the string `"Dan"` as a parameter. This will return all rows where `first_name` is equal to `"Dan"`. The result is displayed in JSON format.
->**Note:** Notice that our output is a nicely formatted document that now not only includes our customer data but also all orders for that customer.
+ > **Note:** Notice that our output is a nicely formatted document
+ > that now not only includes our customer data but also all orders
+ > for that customer.
## Task 5: Connect to the database using pymongo
@@ -490,11 +505,11 @@ The final step in our basic coding tour with Python and the Oracle AI Database i
## Conclusion
-As a developer at Seer Holdings, you've just built the foundation for a GenAI-powered loan approval system. We learned how to use Python and Oracle's Python driver `oracledb` to interact with Oracle AI Database's new features. You learned how to user the `cursor` object to execute SQL queries. Using the `cursor` object, you created a **JSON Duality View** and you even used some JSON functions to query documents using SQL syntax. Then, you also learned how to connect to the database using `pymongo` and retrieve data from a table in the database using **MongoDB syntax**. You created functions to update the **JSON Duality View** and you learned how these updates are also reflected in the underlying relational database tables.
+As a developer at Seer Holdings, you've just built the foundation for a GenAI-powered construction procurement system. We learned how to use Python and Oracle's Python driver `oracledb` to interact with Oracle AI Database's new features. You learned how to use the `cursor` object to execute SQL queries. Using the `cursor` object, you created a **JSON Duality View** and used JSON functions to query documents with SQL syntax. Then, you also learned how to connect to the database using `pymongo` and retrieve data from a table in the database using **MongoDB syntax**. You created functions to update the **JSON Duality View** and learned how those updates are also reflected in the underlying relational database tables.
This architecture eliminates the need for duplicating data across platforms and simplifies how developers build AI-ready applications. Whether you're calling SQL, working with JSON, or speaking Mongo, you're always working with a single source of truth inside the Oracle AI Database.
-In the next lab, you'll build on this foundation to implement Retrieval-Augmented Generation (RAG), create vector embeddings, and generate personalized loan recommendations with Oracle AI Database and OCI Generative AI.
+In the next lab, you'll build on this foundation to implement Retrieval-Augmented Generation (RAG), create vector embeddings, and generate personalized procurement recommendations with Oracle AI Database and OCI Generative AI.
## Acknowledgements
* **Authors** - Linda Foinding
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/introduction/introduction.md b/dev-ai-app-dev-constructioneng-aiexperience/introduction/introduction.md
index 2e9c1808c..168b31186 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/introduction/introduction.md
+++ b/dev-ai-app-dev-constructioneng-aiexperience/introduction/introduction.md
@@ -2,67 +2,60 @@
## About this Workshop
-**Data is more than an asset—it’s the engine behind every smart decision, risk calculation and growth strategy. From real-time decision-making to risk management and innovation, success hinges on how well you harness it.**
+Construction procurement runs on connected decisions. Project requirements, supplier qualifications, compliance documents, schedules, budgets, and risk signals all need to come together quickly if teams want to avoid delays and make confident award decisions.
-SeerGroup is a global conglomerate with multiple divisions. Each division buried in transactions, documents, and customer data. Their challenge is always the same: **decisions take too long** because data is scattered across silos and systems.
+SeerGroup is a global conglomerate with multiple divisions. Across those divisions, the challenge is the same: **critical decisions take too long** because data is scattered across spreadsheets, documents, forms, and disconnected systems.
-This workshop shows how SeerGroup tackles that problem with Oracle AI Database + OCI Generative AI. By **keeping data in one place**, they cut out fragile integrations and give analysts, engineers, and managers a **single platform** for smarter approvals, faster investigations, and clearer customer answers.
+This workshop shows how Seer Construction addresses that problem with Oracle AI Database + OCI Generative AI. By keeping procurement data in one place, the team reduces brittle integrations and gives procurement officers, engineers, and managers a single platform for faster reviews, clearer supplier recommendations, and better project outcomes.
-You’ll see how SeerGroup’s teams can move from manual, fragmented workflows to AI-powered applications—and you’ll build the same capabilities yourself in the labs that follow.
+You’ll see how Seer Construction moves from manual, fragmented procurement workflows to AI-powered applications, and you’ll build the same capabilities yourself in the labs that follow.
-✅ **Start with the demo! (Lab 1)**
-
-Step into SeerGroup’s Finance division as a Loan Officer. You’ll use an AI-powered loan approval app built on Oracle AI Database to:
-
-* Review loan applications with AI Vector Search, Graph analytics, and RAG
+Estimated Workshop Time: 90 minutes
-* See how Generative AI evaluates credit profiles, compares against policy and past cases, and recommends tailored loan options
+✅ **Start with the demo! (Lab 1)**
-* Approve, deny, or request more information with AI-generated guidance, risk factors, and decision letters
+Step into Seer Construction’s Construction Engineering division as a construction procurement officer. You’ll use an AI-powered construction procurement app built on Oracle AI Database to:
-* Update applicant profiles using JSON Duality Views, ensuring income and credit data remain consistent
+* Review project procurements with AI Vector Search, Graph analytics, and RAG
+* See how Generative AI evaluates project requirements, risk, and supplier readiness against available supplier options
+* Approve, deny, or request more information with AI-generated guidance, risk factors, and decision summaries
+* Update procurement profiles using JSON Duality Views so project data stays consistent
-This story shows how SeerEquities uses Oracle AI Database and OCI Generative AI to accelerate loan processing, reduce risk, and improve customer experience—all without moving data across fragile systems.
+This story shows how Seer Construction uses Oracle AI Database and OCI Generative AI to accelerate procurement review, reduce supplier risk, and improve decision quality without moving data across fragile systems.
✅ **What’s next (Labs 2–3)**
-After the demo, you’ll switch roles to developer. In the next labs you’ll connect to Oracle AI Database , shape data into JSON Duality Views, build a retrieval-augmented application, and extend it with reusable MCP tools. By the end, you’ll see how SeerGroup industries can move from siloed processes to intelligent, AI-driven applications—all on one platform.
+After the demo, you’ll switch roles to developer. In the next labs you’ll connect to Oracle AI Database, shape data into JSON Duality Views, build a retrieval-augmented application, and extend it with reusable MCP tools. By the end, you’ll see how SeerGroup teams can move from siloed procurement processes to intelligent, AI-driven applications on one platform.
* **Lab 2 – Connect to your environment**
-Log in to the JupyterLab IDE where you’ll write Python and run your code. **Build the data foundation** Use Python with Oracle AI Database to create tables, shape them into JSON Duality Views, and interact with them using both SQL and MongoDB-style syntax—laying the groundwork for AI workflows across SeerGroup. **Implement RAG** Construct a working AI application. Pull customer and grid data, generate recommendations with OCI Generative AI, chunk and vectorize the results, and answer follow-up questions using Vector Search + RAG.
+Log in to the JupyterLab IDE where you’ll write Python and run your code. Build the data foundation by using Python with Oracle AI Database to create tables, shape them into JSON Duality Views, and interact with them using both SQL and MongoDB-style syntax. Implement RAG by constructing a working AI application that pulls procurement and supplier data, generates recommendations with OCI Generative AI, chunks and vectorizes the results, and answers follow-up questions with Vector Search + RAG.
* **Lab 3 – Extend with MCP tools**
-Wire Oracle AI Database and OCI Generative AI into reusable MCP tools. Call them from notebooks, chain them together into workflows, and even register your own tool for SeerGroup’s finance, retail, healthcare, or energy teams.
-
-By the end, you’ll have a complete toolkit—from clean data to live AI apps to composable tools—that shows how SeerGroup industries can turn their data into intelligent applications.
+Wire Oracle AI Database and OCI Generative AI into reusable MCP tools. Call them from notebooks, chain them together into workflows, and register tools that support SeerGroup’s construction, retail, healthcare, or energy teams.
-**Objectives**
+By the end, you’ll have a complete toolkit, from clean procurement data to live AI apps to composable tools, that shows how SeerGroup divisions can turn operational data into intelligent applications.
-* Build and query data with Python + Oracle AI Database
+### Objectives
+* Build and query data with Python + Oracle AI Database
* Shape relational data into documents using JSON Duality Views
-
* Run Vector Search, Graph analytics, and RAG directly in the database
-
* Extend apps with OCI Generative AI and MCP tools
-
* Deliver industry-grade solutions for SeerGroup’s divisions
-**Prerequisites**
+### Prerequisites
This lab assumes you have:
-* An Oracle account to submit your a LiveLabs Sandbox reservation.
-
-* Basic knowledge of Python.
-
-* Basic knowledge of Oracle Database, i.e., how to run queries.
+* An Oracle account to submit your LiveLabs Sandbox reservation
+* Basic knowledge of Python
+* Basic knowledge of Oracle Database, including how to run queries
## Learn More
-* [Oracle AI Database Documentation](https://docs.oracle.com/en/database/oracle/oracle-database/23/)
+* [Oracle AI Database Documentation](https://docs.oracle.com/en/database/oracle/oracle-database/23/)
## Acknowledgements
* **Authors** - Uma Kumar
* **Contributors** - Linda Foinding
-* **Last Updated By/Date** - Uma Kumar, December 2025
\ No newline at end of file
+* **Last Updated By/Date** - Taylor Zheng, Uma Kumar, Deion Locklear, Daniet Hart, July 2026
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/local-tenancy/local-tenancy.md b/dev-ai-app-dev-constructioneng-aiexperience/local-tenancy/local-tenancy.md
index ccded3061..6abd0e06d 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/local-tenancy/local-tenancy.md
+++ b/dev-ai-app-dev-constructioneng-aiexperience/local-tenancy/local-tenancy.md
@@ -2,7 +2,7 @@
## Introduction
-This lab will show you how to setup and run the Seer Equities Loan Approval application on OCI. This guide is designed to walk you through the complete setup process, which includes provisioning required services and installing dependencies enabling you to launch and run the application on OCI.
+This lab will show you how to set up and run the Seer Construction procurement application on OCI. This guide walks you through the complete setup process, including provisioning the required services and installing the dependencies needed to launch and run the application on OCI.
The document is structured to help you meet all prerequisites, configure both the Autonomous AI Database and the OCI Generative AI Service, and troubleshoot any issues that may arise during setup. Whether you're new to Oracle Cloud Infrastructure or simply deploying for development and testing, this step-by-step guide will ensure a smooth setup experience.
@@ -22,7 +22,9 @@ By the end of this section, you will be able to:
- Launch and interact with the application using Streamlit.
-> 💡Note: This guide is intended for development and testing purposes. For production deployment, additional configuration and security hardening will be required.
+> 💡Note: This guide is intended for development and testing purposes.
+> For production deployment, additional configuration and security
+> hardening will be required.
Let’s get started!
@@ -72,47 +74,51 @@ Let’s get started!

-12. The instance will begin provisioning and in a few moments the state will change to **Succeeded** and then to **Running**.
+12. The instance will begin provisioning and in a few moments the state
+ will change to **Succeeded** and then to **Running**.
- 
+ 
-In the next step, you'll add 5 ingress rules to allow traffic on specific ports within your VCN.
+ In the next step, you'll add 5 ingress rules to allow traffic on
+ specific ports within your VCN.
13. Click on the **Navigation Menu** and select **Networking** then **Virtual Cloud Networks**.
-
+ 
14. Click the VCN link that was created along with your compute instance.
15. Click the **Security** tab, then click on the **Default Security List for vcn-xxxxx**.
-
+ 
16. Click the **Security Rules** tab, then click the **Add Ingress Rules** under the Ingress Rules section. Note that port 22 is already enabled for SSH communication.

-17. For each rule, add 0.0.0.0/0 as the **Source CIDR** and add the specific port below to the **Destination Port Range** field. Click **+ Another Ingress Rule** after each entry.
+17. For each rule, add `0.0.0.0/0` as the **Source CIDR** and add the
+ specific port below to the **Destination Port Range** field. Click
+ **+ Another Ingress Rule** after each entry.
-Add 5 rules using the below information.
+ Add 5 rules using the following information.
-| Ingress Rule # | Source CIDR | Port # |
-| ------------- | ------------- | ------------ |
-| 1 | 0.0.0.0/0 | 80 |
-| 2 | 0.0.0.0/0 | 1521 |
-| 3 | 0.0.0.0/0 | 1522 |
-| 4 | 0.0.0.0/0 | 8501 |
-| 5 | 0.0.0.0/0 | 8502 |
+ | Ingress Rule # | Source CIDR | Port # |
+ | --- | --- | --- |
+ | 1 | 0.0.0.0/0 | 80 |
+ | 2 | 0.0.0.0/0 | 1521 |
+ | 3 | 0.0.0.0/0 | 1522 |
+ | 4 | 0.0.0.0/0 | 8501 |
+ | 5 | 0.0.0.0/0 | 8502 |
{: title="Ingress rules"}
+ When you've added all 5 ingress rules, click the **Add Ingress
+ Rules** button at the bottom right of the page.
-When you've added all 5 ingress rules, click the **Add Ingress Rules** button at the bottom right of the page.
+ 
- 
+ Your default security list should look like the screenshot below.
-Your default security list should look like the below screenshot.
-
- 
+ 
## Task 2: Access and update the VM
@@ -126,7 +132,11 @@ Your default security list should look like the below screenshot.

-4. Type or copy/paste the following command into your terminal. Replace ssh\_key\_name with the name of your private key. Replace public\_ip with the public IP you just copied from your VM. The '-i' switch allows you to specify the location where your SSH keys are stored.
+4. Type or copy/paste the following command into your terminal. Replace
+ `ssh_key_name` with the name of your private key. Replace
+ `public_ip` with the public IP you just copied from your VM. The
+ `-i` switch allows you to specify the location where your SSH keys
+ are stored.
````
@@ -137,7 +147,7 @@ Your default security list should look like the below screenshot.

-6. Run the command below to update the VM. It will take a few minutes.
+5. Run the command below to update the VM. It will take a few minutes.
````
@@ -147,7 +157,8 @@ Your default security list should look like the below screenshot.

-7. Once the VM has been updated install python3.11, pip, and the oci cli application. Run the commands below:
+6. Once the VM has been updated, install Python 3.11, pip, and the OCI
+ CLI application. Run the commands below:
````
@@ -173,66 +184,11 @@ Your default security list should look like the below screenshot.
````
- ```
-
- sudo dnf install python39-oci-cli -y
-
-
-
-
## Task 3: Provision an Autonomous AI Database
@@ -240,11 +196,11 @@ The application is built for Autonomous AI Database. Follow the steps to provisi
1. Click the navigation menu in the upper left of the OCI console, choose **Oracle AI Database** then **Autonomous AI Database**.
- 
+ 
2. Verify that the filter option reflects the correct compartment and click the **Create Autonomous AI Database** button.
- 
+ 
3. Use the information in the table below to fill out the **Create Autonomous AI Database Serverless** form. Proceed to the next step for instructions on setting up **Network Access**.
@@ -259,17 +215,22 @@ The application is built for Autonomous AI Database. Follow the steps to provisi
| Password | Password1234! |
{: title="ADB configuration details overview"}
- 
+ 
-1. In the **Network access** section, choose **Secure access from allowed IPs and VCNs only**. In the **IP notation type** drop-down, choose **CIDR block**. For values, enter **0.0.0.0/0**. Verify that **Require mutual TLS (mTLS) authentication** is disabled. Click the **Create** button.
+4. In the **Network access** section, choose **Secure access from
+ allowed IPs and VCNs only**. In the **IP notation type**
+ drop-down, choose **CIDR block**. For values, enter
+ **0.0.0.0/0**. Verify that **Require mutual TLS (mTLS)**
+ authentication is disabled. Click the **Create** button.
- 
+ 
-2. The ATP Database will enter the provisioning state.
+5. The ATP Database will enter the provisioning state.

-3. Once the state changes to **Available**, the Autonomous Transaction Processing database is ready to use!
+6. Once the state changes to **Available**, the Autonomous Transaction
+ Processing database is ready to use.

@@ -277,23 +238,28 @@ The application is built for Autonomous AI Database. Follow the steps to provisi
The application environment has been created and zipped up for you in a downloadable package.
-1. Return to the terminal connected to the VM. From the /home/opc directory, enter the following command in your terminal to download the application package to your virtual machine.
+1. Return to the terminal connected to the VM. From the `/home/opc`
+ directory, enter the following command to download the application
+ package to your virtual machine.
-```
+ ````
wget https://c4u04.objectstorage.us-ashburn-1.oci.customer-oci.com/p/EcTjWk2IuZPZeNnD_fYMcgUhdNDIDA6rt9gaFj_WZMiL7VvxPBNMY60837hu5hga/n/c4u04/b/livelabsfiles/o/database/ai-app-build-local.zip
-```
+ ````
2. Unzip the file.
-```
+ ````
unzip ai-app-build-local.zip
-```
+ ````
-Next we're going to generate an oci configuration file that will contain user credentials and other settings needed for interacting with Oracle Cloud. In order to prepare for this step you'll need to gather the user OCID, the tenancy OCID, and the tenancy region and store these in a text file.
+ Next, generate an OCI configuration file that will contain user
+ credentials and other settings needed for interacting with Oracle
+ Cloud. To prepare for this step, gather the user OCID, tenancy
+ OCID, and tenancy region, then store them in a text file.
3. Find the user OCID: Click the profile icon in the upper right corner of the OCI console and choose **User settings**.
@@ -303,25 +269,28 @@ Next we're going to generate an oci configuration file that will contain user cr

-5. Tenancy OCID: Click the profile icon in the upper right corner of the OCI console and choose **Tenancy:*your tenancy name***
+5. To find the tenancy OCID, click the profile icon in the upper right
+ corner of the OCI console and choose **Tenancy: _your tenancy
+ name_**.
- 
+ 
6. Locate the tenancy OCID and click the **Copy** button to copy the OCID. Paste it into your text file.
- 
+ 
7. Identify the home region of your tenancy located on the top bar of the console toward the right. Note that information in your text file.
- 
+ 
8. With the above information handy, run the following command in the terminal.
-```
+ ````
oci setup config
-```
+ ````
+
9. Hit return to accept the default config file location of /home/opc/.oci/config
10. Enter your user OCID, tenancy OCID, and select your region from the list by using the corresponding number.
@@ -332,17 +301,18 @@ Next we're going to generate an oci configuration file that will contain user cr
13. Press **Enter** to accept the default name of *oci_api_key*.
-14. Enter *N/A* twice to eliminate the need for a passphrase. (Your output won't show up in the terminal screen.)
+14. Enter *N/A* twice to eliminate the need for a passphrase. (Your
+ output won't show up in the terminal screen.)
-Next you'll create an environment file for the application.
+ Next, you'll create an environment file for the application.
15. Create the .env file that will hold connection information for your application.
-````
+ ````
touch .env
-````
+ ````
16. Use your favorite editor to open and edit the file.
@@ -354,7 +324,7 @@ Next you'll create an environment file for the application.
17. The following information needs to be collected and inserted into the .env file. Copy the 9 lines below and paste them in the .env file. Follow the steps below to gather the required information and place it in the file.
- ```
+ ````
USERNAME=""
DBPASSWORD=""
@@ -366,7 +336,7 @@ Next you'll create an environment file for the application.
TENANCY_OCID=""
ENDPOINT=https://inference.generativeai.us-chicago-1.oci.oraclecloud.com
- ```
+ ````
18. The database username should be 'admin'. Use the password that you assigned to the admin user. (Password1234!). Make sure all the information you enter into the file stays between the quotes.
@@ -420,11 +390,11 @@ Next you'll create an environment file for the application.
````
- python3.11 -m venv loan_env
+ python3.11 -m venv construction_env
````
- This will create a directory called loan_env that will contain your virtual environment.
+ This will create a directory called `construction_env` that will contain your virtual environment.
2. Enable the firewall for the application port. Run the following commands:
@@ -462,13 +432,13 @@ Next you'll create an environment file for the application.
````
[Unit]
- Description=Streamlit Loan Approval App
+ Description=Streamlit Construction Procurement App
After=network.target
[Service]
User=opc
WorkingDirectory=/home/opc
- ExecStart=/bin/bash -c 'source /home/opc/loan_env/bin/activate && streamlit run 1-Introduction.py --server.port 8501 --server.address 0.0.0.0'
+ ExecStart=/bin/bash -c 'source /home/opc/construction_env/bin/activate && streamlit run 1-Introduction.py --server.port 8501 --server.address 0.0.0.0'
Restart=always
[Install]
@@ -477,36 +447,11 @@ Next you'll create an environment file for the application.
````
-
-
5. Activate the virtual environment. Enter the following command.
````
- source loan_env/bin/activate
+ source construction_env/bin/activate
````
@@ -518,21 +463,6 @@ Next you'll create an environment file for the application.
````
-
-
7. Install the required applications from the supplied requirements.txt file.
```
@@ -549,14 +479,14 @@ fpdf
````
-9. Install sqlcl
+9. Install sqlcl.
````
sudo yum install sqlcl -y
````
-10. Reload the daemons and enable streamlit
+10. Reload the daemons and enable Streamlit.
````
@@ -582,7 +512,8 @@ fpdf
````
-Streamlit is up and running. Press Control + C on your keyboard to escape.
+ Streamlit is up and running. Press **Control+C** on your keyboard
+ to exit the status view.
## Task 5: Launch the Application
@@ -613,13 +544,17 @@ Streamlit is up and running. Press Control + C on your keyboard to escape.
4. Open a web browser.
-5. Type in the IP address of the VM followed by :8501 into the incognito window.. You can obtain it from the OCI Console - VM details screen.
+5. Type the IP address of the VM followed by `:8501` into the
+ incognito window. You can obtain it from the OCI Console VM details
+ screen.
6. Success! You should see the application start screen.

-Congratulations, you have built and configured the Loan Management application using Oracle Cloud Insfrastructure, Oracle Autonomous AI Database, and Oracle GenAI!
+ Congratulations, you have built and configured the construction
+ procurement application using Oracle Cloud Infrastructure, Oracle
+ Autonomous AI Database, and Oracle GenAI.
## Troubleshooting
@@ -632,14 +567,17 @@ If you encounter any issues during the setup, here are a few common troubleshoot
````
pip install oci
-
````
* **GenAI Access Issues**: Verify your user/group has the correct IAM policy applied.
* **Virtual Environment Not Activating**: Ensure that you're using the correct command for your operating system. If the issue persists, try recreating the virtual environment.
-* **Dependencies Installation Issues**: Double-check the requirements.txt file to ensure it contains the correct package names. If a specific package fails, you can try installing it manually with pip install .
+* **Dependencies Installation Issues**: Double-check the
+ `requirements.txt` file to ensure it contains the correct package
+ names. If a specific package fails, you can try installing it
+ manually with `pip install your-package-name`.
* **Database Connection Errors**: Ensure that the database credentials in the .env file are correct and that you have access to the Autonomous AI Database.
@@ -668,4 +606,4 @@ You may now **proceed to the next lab**.
## Acknowledgements
- **Created By/Date** - Linda Foinding
-- **Last Updated By/Date** - Linda Foinding, July 2025
\ No newline at end of file
+- **Last Updated By/Date** - Linda Foinding, July 2025
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/user-story/files/starter-file.sql b/dev-ai-app-dev-constructioneng-aiexperience/user-story/files/starter-file.sql
index 9d7e762e8..b29250621 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/user-story/files/starter-file.sql
+++ b/dev-ai-app-dev-constructioneng-aiexperience/user-story/files/starter-file.sql
@@ -1,101 +1,66 @@
-/* NOTE: Files cannot contain empty lines (line breaks) */
-/* Specify the base URL that you copied from your files in OCI Object Storage in the define base_URL line below*/
-/* change idthydc0kinr to your real namespace. The name is case-sensitive. */
-/* change ADWCLab to your real bucket name. The name is case-sensitive. */
-/* change us-phoenix-1 to your real region name. The name is case-sensitive. */
-/* you can find these values on the OCI Console .. Storage .. Object Storage screen */
-set define on
-define base_URL='https://objectstorage.us-phoenix-1.oraclecloud.com/n/idthydc0kinr/b/ADWCLab/o'
-/* copy Channels table */
-begin
- dbms_cloud.copy_data(
- table_name =>'CHANNELS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/chan_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true')
- );
-end;
-/
-/* copy Countries table */
-begin
- dbms_cloud.copy_data(
- table_name =>'COUNTRIES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/coun_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true')
- );
-end;
-/
-/* Copy customers */
-begin
- dbms_cloud.copy_data(
- table_name =>'CUSTOMERS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/cust1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'SUPPLEMENTARY_DEMOGRAPHICS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/dem1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'SALES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/dmsal_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'PRODUCTS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/prod1v3.dat',
- format => json_object('delimiter' value '|', 'quote' value '^', 'ignoremissingcolumns' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'PROMOTIONS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/prom1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'SALES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/sale1v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'TIMES',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/time_v3.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true', 'dateformat' value 'YYYY-MM-DD-HH24-MI-SS', 'blankasnull' value 'true')
- );
-end;
-/
-begin
- dbms_cloud.copy_data(
- table_name =>'COSTS',
- credential_name =>'OBJ_STORE_CRED',
- file_uri_list =>'&base_URL/costs.dat',
- format => json_object('ignoremissingcolumns' value 'true', 'dateformat' value 'YYYY-MM-DD', 'blankasnull' value 'true')
- );
-end;
-/
+/* Construction procurement starter schema for the AI Experience workshop */
+
+drop view if exists procurement_profiles_dv;
+drop table if exists procurement_recommendation_chunk;
+drop table if exists supplier_option_catalog;
+drop table if exists construction_procurements;
+
+create table if not exists construction_procurements (
+ project_id varchar2(30) primary key,
+ project_code varchar2(30),
+ project_name varchar2(200),
+ location varchar2(200),
+ project_phase varchar2(100),
+ required_trade varchar2(100),
+ procurement_urgency varchar2(50),
+ budget_range varchar2(50),
+ risk_level varchar2(50),
+ project_status varchar2(40)
+);
+
+create table if not exists supplier_option_catalog (
+ supplier_option_id number primary key,
+ supplier_name varchar2(200),
+ trade_specialty varchar2(120),
+ experience_summary varchar2(400),
+ compliance_status varchar2(120),
+ on_time_delivery_rate varchar2(50),
+ delivery_window_weeks number,
+ capacity_status varchar2(100),
+ project_fit varchar2(200),
+ recommendation_status varchar2(40)
+);
+
+create table if not exists procurement_recommendation_chunk (
+ project_id varchar2(30) not null,
+ chunk_id number not null,
+ chunk_text clob,
+ chunk_vector vector(384, float32),
+ constraint procurement_recommendation_chunk_pk primary key (project_id, chunk_id)
+);
+
+insert into construction_procurements (project_id, project_code, project_name, location, project_phase, required_trade, procurement_urgency, budget_range, risk_level, project_status) values
+('1001', 'P1001', 'Downtown Mixed-Use Tower', 'Chicago, IL', 'Structural Frame', 'Structural Steel', 'High', '$4.0-5.5M', 'Low Risk', 'Pending Review'),
+('1003', 'P1003', 'Harbor Seismic Retrofit', 'Long Beach, CA', 'Retrofit', 'Seismic Steel Retrofit', 'Critical', '$6.5-8.0M', 'High Risk', 'Pending Review'),
+('1004', 'P1004', 'North Campus Lab Expansion', 'Austin, TX', 'Procurement Planning', 'Mechanical + Lab Fit-Out', 'Medium', '$1.1-1.6M', 'Medium Risk', 'Pending Review');
+
+insert into supplier_option_catalog (supplier_option_id, supplier_name, trade_specialty, experience_summary, compliance_status, on_time_delivery_rate, delivery_window_weeks, capacity_status, project_fit, recommendation_status) values
+(7001, 'Atlas Structural Fabrication', 'Structural Steel', 'Strong mid-rise steel frame project experience', 'Current AISC and AWS documentation', '96%', 6, 'Confirmed', 'High fit for six-week downtown tower delivery', 'Recommended'),
+(7002, 'Metro Build Systems', 'Structural Steel', 'Broad tower podium and transfer deck experience', 'AISC current, AWS renewal pending', '92%', 8, 'Limited', 'Good fit but tighter capacity window', 'Review'),
+(7003, 'Coastal Retrofit Metals', 'Seismic Retrofit Steel', 'Extensive retrofit portfolio in coastal zones', 'Compliance gaps under review', '88%', 10, 'Conditional', 'Technically aligned but elevated risk profile', 'Denied'),
+(7004, 'Northline MEP Supply', 'Mechanical + Lab Fit-Out', 'University and life-science lab package experience', 'Current QA and safety files', '94%', 7, 'Confirmed', 'Good fit for updated lab expansion budget', 'Recommended');
+
+create or replace json relational duality view procurement_profiles_dv as
+ construction_procurements @insert @update @delete
+ {
+ _id : project_id,
+ projectCode : project_code,
+ projectName : project_name,
+ location,
+ projectPhase : project_phase,
+ requiredTrade : required_trade,
+ procurementUrgency : procurement_urgency,
+ budgetRange : budget_range,
+ riskLevel : risk_level,
+ projectStatus : project_status
+ };
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/user-story/user-story.md b/dev-ai-app-dev-constructioneng-aiexperience/user-story/user-story.md
index c6eb2d0db..092eda710 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/user-story/user-story.md
+++ b/dev-ai-app-dev-constructioneng-aiexperience/user-story/user-story.md
@@ -104,13 +104,13 @@ In this first example, you will use the application to approve a project with lo

-**Conclusion**
+ **Conclusion**
Once you select and save one of the 3 supplier recommended by the AI:
✅ The project's risk level status is updated.
-✅ A finalized PDF decision document is generated.
+ ✅ A finalized PDF decision document is generated.
✅ The dashboard reflects the change in real-time — marking P1001 as Approved.
@@ -137,6 +137,7 @@ In this example, you will navigate the projects to review a project and deny the
>⁉️ **What is the reason that the AI decided to deny this applicant?** ⁉️
+4. Expand **Interactive Graph: Project, Supplier Recommendation & Risk** to view the graph.
4. Expand **Interactive Graph: Project, Supplier Recommendation & Risk** to view the graph.
@@ -176,9 +177,9 @@ In this example, you will navigate the projects to review a project and deny the

-**Conclusion**
+ **Conclusion**
-Congratulations, you have finished reviewing a customer with high financial risk! Proceed to the next task.
+ Congratulations, you have finished reviewing a customer with high financial risk! Proceed to the next task.
## Task 4: Demo - Update Customer Details
@@ -203,9 +204,9 @@ Lastly, let’s explore how the system uses JSON Duality Views to handle profile

-**Conclusion**
+ Once the document is uploaded:
-Once the document is uploaded:
+ ✅ The system automatically detects the new budget data.
✅ The system automatically detects the new budget data.
@@ -226,7 +227,7 @@ In conclusion our Construction Procurement App was able to leverage Oracle AI Da
✅ Empower construction procurement officers with actionable insights through Operational Property Graphs
By combining these advanced tools, the application enables faster, smarter decisions and delivers clear guidance on how customers can improve their eligibility.
-
+
**Next:** How about learning how the application was implemented in Python? Continue with the next labs and start developing!
## Learn More
@@ -236,4 +237,4 @@ By combining these advanced tools, the application enables faster, smarter decis
## Acknowledgements
* **Authors** - Linda Foinding, Francis Regalado
* **Contributors** - Eddie Ambler, Ramona Magadan, Mark Nelson, Andy Tael, Anders Swanson, Rahul Tasker
-* **Last Updated By/Date** - Taylor Zheng, Uma Kumar, Deion Locklear, Daniet Hart, July 2026
\ No newline at end of file
+* **Last Updated By/Date** - Taylor Zheng, Uma Kumar, Deion Locklear, Daniet Hart, July 2026
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox/manifest.json b/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox/manifest.json
index 9c02fa355..327f2bdd9 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox/manifest.json
+++ b/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox/manifest.json
@@ -1,5 +1,5 @@
{
- "workshoptitle": "Build a GenAI App on Oracle AI Database – Finance Edition",
+ "workshoptitle": "Build a GenAI App on Oracle AI Database – Construction Procurement Edition",
"help": "livelabs-help-database_us@oracle.com",
"tutorials": [
{
@@ -28,4 +28,4 @@
"filename": "https://livelabs.oracle.com/cdn/common/labs/need-help/need-help-freetier.md"
}
]
-}
\ No newline at end of file
+}
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox_aiw/manifest.json b/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox_aiw/manifest.json
index 0b961bb3b..556c05b18 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox_aiw/manifest.json
+++ b/dev-ai-app-dev-constructioneng-aiexperience/workshops/sandbox_aiw/manifest.json
@@ -1,5 +1,5 @@
{
- "workshoptitle": "Build a GenAI-Powered Financial Services Loan Approval Application with Oracle AI Database",
+ "workshoptitle": "Build a GenAI-Powered Construction Procurement Application with Oracle AI Database",
"help": "livelabs-help-database_us@oracle.com",
"tutorials": [
{
@@ -38,4 +38,4 @@
"filename": "https://livelabs.oracle.com/cdn/common/labs/need-help/need-help-freetier.md"
}
]
-}
\ No newline at end of file
+}
diff --git a/dev-ai-app-dev-constructioneng-aiexperience/workshops/tenancy/manifest.json b/dev-ai-app-dev-constructioneng-aiexperience/workshops/tenancy/manifest.json
index 9737e2c48..948108e48 100644
--- a/dev-ai-app-dev-constructioneng-aiexperience/workshops/tenancy/manifest.json
+++ b/dev-ai-app-dev-constructioneng-aiexperience/workshops/tenancy/manifest.json
@@ -1,5 +1,5 @@
{
- "workshoptitle": "Build a GenAI-Powered Financial Services Loan Approval Application with Oracle AI Database",
+ "workshoptitle": "Build a GenAI-Powered Construction Procurement Application with Oracle AI Database",
"help": "livelabs-help-database_us@oracle.com",
"tutorials": [
{
@@ -93,4 +93,4 @@
"filename": "https://livelabs.oracle.com/cdn/common/labs/need-help/need-help-freetier.md"
}
]
-}
\ No newline at end of file
+}
diff --git a/dev-ai-app-dev-finance-aiexperience/app-architecture/app-architecture.md b/dev-ai-app-dev-finance-aiexperience/app-architecture/app-architecture.md
index c23208eb2..19af72d1b 100644
--- a/dev-ai-app-dev-finance-aiexperience/app-architecture/app-architecture.md
+++ b/dev-ai-app-dev-finance-aiexperience/app-architecture/app-architecture.md
@@ -6,6 +6,16 @@ In this lab, you will explore the architecture behind the workshop that supports
Estimated Lab Time: 15 minutes
+### Objectives
+
+In this lab, you will:
+
+* Review the OCI architecture that supports the SeerEquities loan
+ application
+* Understand how JSON Duality Views, AI Vector Search, and Property
+ Graph support the loan approval workflow
+* Connect the workshop labs to the application design used in the demo
+
## Physical Architecture
The SeerEquities loan application runs in an **Oracle Cloud Infrastructure (OCI)** Region, with its application layer in a public subnet inside a **Virtual Cloud Network (VCN)**.
@@ -69,4 +79,4 @@ Property graphs simplify working with connected data, such as identifying influe
## Acknowledgements
* **Authors** - Linda Foinding, Francis Regalado
* **Contributors** - Eddie Ambler
-* **Last Updated By/Date** - Linda Foinding, April 2025
\ No newline at end of file
+* **Last Updated By/Date** - Linda Foinding, April 2025
diff --git a/dev-ai-app-dev-finance-aiexperience/build/build.md b/dev-ai-app-dev-finance-aiexperience/build/build.md
index 24b6281a3..2e4467c0f 100644
--- a/dev-ai-app-dev-finance-aiexperience/build/build.md
+++ b/dev-ai-app-dev-finance-aiexperience/build/build.md
@@ -162,7 +162,9 @@ else:

-If you completed Lab 1: Run the Demo earlier, this is what gets printed out when the loan officer clicks on the customer 1000. You just built it, well done!
+ If you completed Lab 1: Run the Demo earlier, this is what gets
+ printed out when the loan officer clicks on customer `1000`. You
+ just built it, well done!
## Task 6: Create a function to generate recommendations for the customer
@@ -498,4 +500,4 @@ You may now proceed to the next lab.
## Acknowledgements
* **Authors** - Francis Regalado
-* **Last Updated By/Date** - Uma Kumar, December 2025
\ No newline at end of file
+* **Last Updated By/Date** - Uma Kumar, December 2025
diff --git a/dev-ai-app-dev-finance-aiexperience/codingbasics/codingbasics.md b/dev-ai-app-dev-finance-aiexperience/codingbasics/codingbasics.md
index 9d1abd611..5e1c66ba8 100644
--- a/dev-ai-app-dev-finance-aiexperience/codingbasics/codingbasics.md
+++ b/dev-ai-app-dev-finance-aiexperience/codingbasics/codingbasics.md
@@ -86,7 +86,15 @@ In this first task, you will connect to an Oracle AI Database instance using Ora

->**Note:** The last line, `cursor = connection.cursor()`, creates a cursor object from the established Oracle AI Database connection. A cursor acts as a control structure that enables the execution of SQL queries and retrieval of results from the database. It is essential for sending SQL commands, fetching data, and iterating through query results. We will be using the cursor object in later steps of this lab. The object persists in the notebook session, so you can use it in subsequent cells without re-establishing the connection.
+ > **Note:** The last line, `cursor = connection.cursor()`, creates
+ > a cursor object from the established Oracle AI Database
+ > connection. A cursor acts as a control structure that enables the
+ > execution of SQL queries and retrieval of results from the
+ > database. It is essential for sending SQL commands, fetching
+ > data, and iterating through query results. We will be using the
+ > cursor object in later steps of this lab. The object persists in
+ > the notebook session, so you can use it in subsequent cells
+ > without re-establishing the connection.
## Task 3: Create tables and insert data
@@ -141,7 +149,9 @@ Now, that we have established a connection, we can start creating our tables and
```
->**Note:** We are creating a function called `query_orders()` that will allow us to query our table. We can use the same function in one of the following tasks
+ > **Note:** We are creating a function called `query_orders()`
+ > that will allow us to query our table. We can use the same
+ > function in one of the following tasks.
3. Run your code (**shift+enter**) and see what happens. You should get a list of all the orders in our table.
@@ -197,11 +207,13 @@ Now, that we have established a connection, we can start creating our tables and

-### **Task Summary**
+ ### **Task Summary**
-Congratulations! You successfully created two new tables with sample data using Python and Oracle AI Database.
+ Congratulations! You successfully created two new tables with
+ sample data using Python and Oracle AI Database.
-You also created a function that allows you to query your new table which we will use in some of the following tasks
+ You also created a function that allows you to query your new table
+ which we will use in some of the following tasks.
## Task 4: Create a JSON Duality View
@@ -269,7 +281,12 @@ Next, we want to explore how we can use a **JSON Duality View** to query our new

->💡 **JSON Duality Views** automatically maps relational columns to JSON documents (and vice versa) in the same table, letting you store data in a traditional schema but also access it as if it were a JSON object. So even though you’ve coded a JSON view in Python, you can switch over to standard SQL queries without duplicating data or maintaining extra structures. Super cool!
+ > 💡 **JSON Duality Views** automatically maps relational columns
+ > to JSON documents (and vice versa) in the same table, letting you
+ > store data in a traditional schema but also access it as if it
+ > were a JSON object. So even though you have coded a JSON view in
+ > Python, you can switch over to standard SQL queries without
+ > duplicating data or maintaining extra structures.
3. Let's create a new function that allows us to query our new JSON Duality View. This time however, we will enhance our function to allow using input parameters. Instead of retrieving all rows, we want to write a function that returns only a specific row based on the first name of a customer. Copy the following code into a new cell and run it.
@@ -311,7 +328,9 @@ Next, we want to explore how we can use a **JSON Duality View** to query our new
🔴 **`query_dv("Dan")`** - Here we are calling our query function again, but this time passing in the string `"Dan"` as a parameter. This will return all rows where `first_name` is equal to `"Dan"`. The result is displayed in JSON format.
->**Note:** Notice that our output is a nicely formatted document that now not only includes our customer data but also all orders for that customer.
+ > **Note:** Notice that our output is a nicely formatted document
+ > that now not only includes our customer data but also all orders
+ > for that customer.
## Task 5: Connect to the database using pymongo
diff --git a/dev-ai-app-dev-finance-aiexperience/introduction/introduction.md b/dev-ai-app-dev-finance-aiexperience/introduction/introduction.md
index 2e9c1808c..bdca7e13e 100644
--- a/dev-ai-app-dev-finance-aiexperience/introduction/introduction.md
+++ b/dev-ai-app-dev-finance-aiexperience/introduction/introduction.md
@@ -10,6 +10,8 @@ This workshop shows how SeerGroup tackles that problem with Oracle AI Database
You’ll see how SeerGroup’s teams can move from manual, fragmented workflows to AI-powered applications—and you’ll build the same capabilities yourself in the labs that follow.
+Estimated Workshop Time: 90 minutes
+
✅ **Start with the demo! (Lab 1)**
Step into SeerGroup’s Finance division as a Loan Officer. You’ll use an AI-powered loan approval app built on Oracle AI Database to:
@@ -36,7 +38,7 @@ Wire Oracle AI Database and OCI Generative AI into reusable MCP tools. Call them
By the end, you’ll have a complete toolkit—from clean data to live AI apps to composable tools—that shows how SeerGroup industries can turn their data into intelligent applications.
-**Objectives**
+### Objectives
* Build and query data with Python + Oracle AI Database
@@ -48,7 +50,7 @@ By the end, you’ll have a complete toolkit—from clean data to live AI apps t
* Deliver industry-grade solutions for SeerGroup’s divisions
-**Prerequisites**
+### Prerequisites
This lab assumes you have:
@@ -65,4 +67,4 @@ This lab assumes you have:
## Acknowledgements
* **Authors** - Uma Kumar
* **Contributors** - Linda Foinding
-* **Last Updated By/Date** - Uma Kumar, December 2025
\ No newline at end of file
+* **Last Updated By/Date** - Uma Kumar, December 2025
diff --git a/dev-ai-app-dev-finance-aiexperience/local-tenancy/local-tenancy.md b/dev-ai-app-dev-finance-aiexperience/local-tenancy/local-tenancy.md
index ccded3061..b3ea33f80 100644
--- a/dev-ai-app-dev-finance-aiexperience/local-tenancy/local-tenancy.md
+++ b/dev-ai-app-dev-finance-aiexperience/local-tenancy/local-tenancy.md
@@ -2,7 +2,11 @@
## Introduction
-This lab will show you how to setup and run the Seer Equities Loan Approval application on OCI. This guide is designed to walk you through the complete setup process, which includes provisioning required services and installing dependencies enabling you to launch and run the application on OCI.
+This lab will show you how to set up and run the Seer Equities Loan
+Approval application on OCI. This guide walks you through the complete
+setup process, including provisioning the required services and
+installing the dependencies needed to launch and run the application on
+OCI.
The document is structured to help you meet all prerequisites, configure both the Autonomous AI Database and the OCI Generative AI Service, and troubleshoot any issues that may arise during setup. Whether you're new to Oracle Cloud Infrastructure or simply deploying for development and testing, this step-by-step guide will ensure a smooth setup experience.
@@ -22,7 +26,9 @@ By the end of this section, you will be able to:
- Launch and interact with the application using Streamlit.
-> 💡Note: This guide is intended for development and testing purposes. For production deployment, additional configuration and security hardening will be required.
+> 💡Note: This guide is intended for development and testing purposes.
+> For production deployment, additional configuration and security
+> hardening will be required.
Let’s get started!
@@ -72,47 +78,51 @@ Let’s get started!

-12. The instance will begin provisioning and in a few moments the state will change to **Succeeded** and then to **Running**.
+12. The instance will begin provisioning and in a few moments the state
+ will change to **Succeeded** and then to **Running**.
- 
+ 
-In the next step, you'll add 5 ingress rules to allow traffic on specific ports within your VCN.
+ In the next step, you'll add 5 ingress rules to allow traffic on
+ specific ports within your VCN.
13. Click on the **Navigation Menu** and select **Networking** then **Virtual Cloud Networks**.
-
+ 
14. Click the VCN link that was created along with your compute instance.
15. Click the **Security** tab, then click on the **Default Security List for vcn-xxxxx**.
-
+ 
16. Click the **Security Rules** tab, then click the **Add Ingress Rules** under the Ingress Rules section. Note that port 22 is already enabled for SSH communication.

-17. For each rule, add 0.0.0.0/0 as the **Source CIDR** and add the specific port below to the **Destination Port Range** field. Click **+ Another Ingress Rule** after each entry.
+17. For each rule, add `0.0.0.0/0` as the **Source CIDR** and add the
+ specific port below to the **Destination Port Range** field. Click
+ **+ Another Ingress Rule** after each entry.
-Add 5 rules using the below information.
+ Add 5 rules using the following information.
-| Ingress Rule # | Source CIDR | Port # |
-| ------------- | ------------- | ------------ |
-| 1 | 0.0.0.0/0 | 80 |
-| 2 | 0.0.0.0/0 | 1521 |
-| 3 | 0.0.0.0/0 | 1522 |
-| 4 | 0.0.0.0/0 | 8501 |
-| 5 | 0.0.0.0/0 | 8502 |
+ | Ingress Rule # | Source CIDR | Port # |
+ | --- | --- | --- |
+ | 1 | 0.0.0.0/0 | 80 |
+ | 2 | 0.0.0.0/0 | 1521 |
+ | 3 | 0.0.0.0/0 | 1522 |
+ | 4 | 0.0.0.0/0 | 8501 |
+ | 5 | 0.0.0.0/0 | 8502 |
{: title="Ingress rules"}
+ When you've added all 5 ingress rules, click the **Add Ingress
+ Rules** button at the bottom right of the page.
-When you've added all 5 ingress rules, click the **Add Ingress Rules** button at the bottom right of the page.
+ 
- 
+ Your default security list should look like the screenshot below.
-Your default security list should look like the below screenshot.
-
- 
+ 
## Task 2: Access and update the VM
@@ -126,7 +136,11 @@ Your default security list should look like the below screenshot.

-4. Type or copy/paste the following command into your terminal. Replace ssh\_key\_name with the name of your private key. Replace public\_ip with the public IP you just copied from your VM. The '-i' switch allows you to specify the location where your SSH keys are stored.
+4. Type or copy/paste the following command into your terminal. Replace
+ `ssh_key_name` with the name of your private key. Replace
+ `public_ip` with the public IP you just copied from your VM. The
+ `-i` switch allows you to specify the location where your SSH keys
+ are stored.
````
@@ -137,7 +151,7 @@ Your default security list should look like the below screenshot.

-6. Run the command below to update the VM. It will take a few minutes.
+5. Run the command below to update the VM. It will take a few minutes.
````
@@ -147,7 +161,8 @@ Your default security list should look like the below screenshot.

-7. Once the VM has been updated install python3.11, pip, and the oci cli application. Run the commands below:
+6. Once the VM has been updated, install Python 3.11, pip, and the OCI
+ CLI application. Run the commands below:
````
@@ -173,66 +188,11 @@ Your default security list should look like the below screenshot.
````
- ```
-
- sudo dnf install python39-oci-cli -y
-
-
-
-
## Task 3: Provision an Autonomous AI Database
@@ -240,11 +200,11 @@ The application is built for Autonomous AI Database. Follow the steps to provisi
1. Click the navigation menu in the upper left of the OCI console, choose **Oracle AI Database** then **Autonomous AI Database**.
- 
+ 
2. Verify that the filter option reflects the correct compartment and click the **Create Autonomous AI Database** button.
- 
+ 
3. Use the information in the table below to fill out the **Create Autonomous AI Database Serverless** form. Proceed to the next step for instructions on setting up **Network Access**.
@@ -259,17 +219,22 @@ The application is built for Autonomous AI Database. Follow the steps to provisi
| Password | Password1234! |
{: title="ADB configuration details overview"}
- 
+ 
-1. In the **Network access** section, choose **Secure access from allowed IPs and VCNs only**. In the **IP notation type** drop-down, choose **CIDR block**. For values, enter **0.0.0.0/0**. Verify that **Require mutual TLS (mTLS) authentication** is disabled. Click the **Create** button.
+4. In the **Network access** section, choose **Secure access from
+ allowed IPs and VCNs only**. In the **IP notation type**
+ drop-down, choose **CIDR block**. For values, enter
+ **0.0.0.0/0**. Verify that **Require mutual TLS (mTLS)**
+ authentication is disabled. Click the **Create** button.
- 
+ 
-2. The ATP Database will enter the provisioning state.
+5. The ATP Database will enter the provisioning state.

-3. Once the state changes to **Available**, the Autonomous Transaction Processing database is ready to use!
+6. Once the state changes to **Available**, the Autonomous Transaction
+ Processing database is ready to use.

@@ -277,23 +242,28 @@ The application is built for Autonomous AI Database. Follow the steps to provisi
The application environment has been created and zipped up for you in a downloadable package.
-1. Return to the terminal connected to the VM. From the /home/opc directory, enter the following command in your terminal to download the application package to your virtual machine.
+1. Return to the terminal connected to the VM. From the `/home/opc`
+ directory, enter the following command to download the application
+ package to your virtual machine.
-```
+ ````
wget https://c4u04.objectstorage.us-ashburn-1.oci.customer-oci.com/p/EcTjWk2IuZPZeNnD_fYMcgUhdNDIDA6rt9gaFj_WZMiL7VvxPBNMY60837hu5hga/n/c4u04/b/livelabsfiles/o/database/ai-app-build-local.zip
-```
+ ````
2. Unzip the file.
-```
+ ````
unzip ai-app-build-local.zip
-```
+ ````
-Next we're going to generate an oci configuration file that will contain user credentials and other settings needed for interacting with Oracle Cloud. In order to prepare for this step you'll need to gather the user OCID, the tenancy OCID, and the tenancy region and store these in a text file.
+ Next, generate an OCI configuration file that will contain user
+ credentials and other settings needed for interacting with Oracle
+ Cloud. To prepare for this step, gather the user OCID, tenancy
+ OCID, and tenancy region, then store them in a text file.
3. Find the user OCID: Click the profile icon in the upper right corner of the OCI console and choose **User settings**.
@@ -303,25 +273,28 @@ Next we're going to generate an oci configuration file that will contain user cr

-5. Tenancy OCID: Click the profile icon in the upper right corner of the OCI console and choose **Tenancy:*your tenancy name***
+5. To find the tenancy OCID, click the profile icon in the upper right
+ corner of the OCI console and choose **Tenancy: _your tenancy
+ name_**.
- 
+ 
6. Locate the tenancy OCID and click the **Copy** button to copy the OCID. Paste it into your text file.
- 
+ 
7. Identify the home region of your tenancy located on the top bar of the console toward the right. Note that information in your text file.
- 
+ 
8. With the above information handy, run the following command in the terminal.
-```
+ ````
oci setup config
-```
+ ````
+
9. Hit return to accept the default config file location of /home/opc/.oci/config
10. Enter your user OCID, tenancy OCID, and select your region from the list by using the corresponding number.
@@ -332,17 +305,18 @@ Next we're going to generate an oci configuration file that will contain user cr
13. Press **Enter** to accept the default name of *oci_api_key*.
-14. Enter *N/A* twice to eliminate the need for a passphrase. (Your output won't show up in the terminal screen.)
+14. Enter *N/A* twice to eliminate the need for a passphrase. (Your
+ output won't show up in the terminal screen.)
-Next you'll create an environment file for the application.
+ Next, you'll create an environment file for the application.
15. Create the .env file that will hold connection information for your application.
-````
+ ````
touch .env
-````
+ ````
16. Use your favorite editor to open and edit the file.
@@ -354,7 +328,7 @@ Next you'll create an environment file for the application.
17. The following information needs to be collected and inserted into the .env file. Copy the 9 lines below and paste them in the .env file. Follow the steps below to gather the required information and place it in the file.
- ```
+ ````
USERNAME=""
DBPASSWORD=""
@@ -366,7 +340,7 @@ Next you'll create an environment file for the application.
TENANCY_OCID=""
ENDPOINT=https://inference.generativeai.us-chicago-1.oci.oraclecloud.com
- ```
+ ````
18. The database username should be 'admin'. Use the password that you assigned to the admin user. (Password1234!). Make sure all the information you enter into the file stays between the quotes.
@@ -424,7 +398,8 @@ Next you'll create an environment file for the application.
````
- This will create a directory called loan_env that will contain your virtual environment.
+ This will create a directory called `loan_env` that will contain
+ your virtual environment.
2. Enable the firewall for the application port. Run the following commands:
@@ -477,31 +452,6 @@ Next you'll create an environment file for the application.
````
-
-
5. Activate the virtual environment. Enter the following command.
````
@@ -518,21 +468,6 @@ Next you'll create an environment file for the application.
````
-
-
7. Install the required applications from the supplied requirements.txt file.
```
@@ -549,14 +484,14 @@ fpdf
````
-9. Install sqlcl
+9. Install sqlcl.
````
sudo yum install sqlcl -y
````
-10. Reload the daemons and enable streamlit
+10. Reload the daemons and enable Streamlit.
````
@@ -582,7 +517,8 @@ fpdf
````
-Streamlit is up and running. Press Control + C on your keyboard to escape.
+ Streamlit is up and running. Press **Control+C** on your keyboard
+ to exit the status view.
## Task 5: Launch the Application
@@ -613,13 +549,17 @@ Streamlit is up and running. Press Control + C on your keyboard to escape.
4. Open a web browser.
-5. Type in the IP address of the VM followed by :8501 into the incognito window.. You can obtain it from the OCI Console - VM details screen.
+5. Type the IP address of the VM followed by `:8501` into the
+ incognito window. You can obtain it from the OCI Console VM details
+ screen.
6. Success! You should see the application start screen.

-Congratulations, you have built and configured the Loan Management application using Oracle Cloud Insfrastructure, Oracle Autonomous AI Database, and Oracle GenAI!
+ Congratulations, you have built and configured the loan approval
+ application using Oracle Cloud Infrastructure, Oracle Autonomous AI
+ Database, and Oracle GenAI.
## Troubleshooting
@@ -632,14 +572,17 @@ If you encounter any issues during the setup, here are a few common troubleshoot
````
pip install oci
-
````
* **GenAI Access Issues**: Verify your user/group has the correct IAM policy applied.
* **Virtual Environment Not Activating**: Ensure that you're using the correct command for your operating system. If the issue persists, try recreating the virtual environment.
-* **Dependencies Installation Issues**: Double-check the requirements.txt file to ensure it contains the correct package names. If a specific package fails, you can try installing it manually with pip install .
+* **Dependencies Installation Issues**: Double-check the
+ `requirements.txt` file to ensure it contains the correct package
+ names. If a specific package fails, you can try installing it
+ manually with `pip install your-package-name`.
* **Database Connection Errors**: Ensure that the database credentials in the .env file are correct and that you have access to the Autonomous AI Database.
@@ -668,4 +611,4 @@ You may now **proceed to the next lab**.
## Acknowledgements
- **Created By/Date** - Linda Foinding
-- **Last Updated By/Date** - Linda Foinding, July 2025
\ No newline at end of file
+- **Last Updated By/Date** - Linda Foinding, July 2025
diff --git a/dev-ai-app-dev-finance-aiexperience/user-story/user-story.md b/dev-ai-app-dev-finance-aiexperience/user-story/user-story.md
index 354755dc9..a2f8c76e2 100644
--- a/dev-ai-app-dev-finance-aiexperience/user-story/user-story.md
+++ b/dev-ai-app-dev-finance-aiexperience/user-story/user-story.md
@@ -103,17 +103,19 @@ In this first example, you will use the application to approve a customer with s

-**Conclusion**
+ **Conclusion**
-Once you select and save one of the 3 loans recommended by the AI:
+ Once you select and save one of the 3 loans recommended by the AI:
-✅ The customer's loan status is updated.
+ ✅ The customer's loan status is updated.
-✅ A finalized PDF decision document is generated.
+ ✅ A finalized PDF decision document is generated.
-✅ The dashboard reflects the change in real-time — marking James as Approved.
+ ✅ The dashboard reflects the change in real-time — marking James
+ as Approved.
-Congratulations, you have just approved your first customer loan! Proceed to the next task.
+ Congratulations, you have just approved your first customer loan!
+ Proceed to the next task.
## Task 3: Demo - Denying a customer with high risk
In this example, you will navigate the application to review a customer and deny them as part of the exercise. The second user on your to-do list is James Woods.
@@ -179,9 +181,10 @@ In this example, you will navigate the application to review a customer and deny

-**Conclusion**
+ **Conclusion**
-Congratulations, you have finished reviewing a customer with high financial risk! Proceed to the next task.
+ Congratulations, you have finished reviewing a customer with high
+ financial risk! Proceed to the next task.
## Task 4: Demo - Update customer details
@@ -209,15 +212,17 @@ Lastly, let’s explore how the system uses JSON Duality Views to handle profile

-**Conclusion**
+ **Conclusion**
-Once the document is uploaded:
+ Once the document is uploaded:
-✅ The system automatically detects the new income data.
+ ✅ The system automatically detects the new income data.
-✅ Then their profile will be updated from $25,000 to $65,000.
+ ✅ Then their profile will be updated from $25,000 to $65,000.
-✅ And thanks to JSON Transform and JSON Duality Views, only the relevant field is modified — leaving the rest of the profile UNTOUCHED.
+ ✅ And thanks to JSON Transform and JSON Duality Views, only the
+ relevant field is modified — leaving the rest of the profile
+ UNTOUCHED.
## Summary
@@ -242,4 +247,4 @@ By combining these advanced tools, the application enables faster, smarter decis
## Acknowledgements
* **Authors** - Linda Foinding, Francis Regalado
* **Contributors** - Eddie Ambler, Ramona Magadan, Mark Nelson, Andy Tael, Anders Swanson, Rahul Tasker
-* **Last Updated By/Date** - Linda Foinding, September 2025
\ No newline at end of file
+* **Last Updated By/Date** - Linda Foinding, September 2025