diff --git a/dev-ai-app-dev-constructioneng-aiexperience/build/build.md b/dev-ai-app-dev-constructioneng-aiexperience/build/build.md index 7e8bdf53e..f275853bd 100644 --- a/dev-ai-app-dev-constructioneng-aiexperience/build/build.md +++ b/dev-ai-app-dev-constructioneng-aiexperience/build/build.md @@ -52,7 +52,10 @@ This lab assumes you have: ![Open Terminal](./images/terminal.png " ") -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. +2. Navigate to `db_setup_CONSTENG_script_2.sql` under the + `dbinit` folder. This script provisions the construction + engineering tables, the `construction_projects_dv` JSON duality + view, and the `CE_PROJECT_CHUNKS` table used later in the RAG flow. ![Tables](./images/tables.png " ") @@ -100,57 +103,100 @@ This lab assumes you have: ![Connect to Database](./images/lab4task1.png " ") -## Task 5: Create a function to retrieve procurement data from the database +## Task 5: Create a function to retrieve project 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 project data from the `construction_projects_dv` JSON +duality view, which combines `CE_PROJECTS`, +`CE_PROJECT_REQUIREMENTS`, `CE_SUPPLIER_EVALUATION`, and +`CE_SUPPLIER_RECOMMENDATION` into one JSON document. This task will: -- **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. +- **Define a Function**: Create a reusable function + `fetch_project_data` to query the database by project ID and + extract the JSON data for one construction project. +- **Use an Example**: Fetch data for project `1001` + (`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 the project + phase, required trade, procurement urgency, budget range, risk + level, and current supplier evaluation. 1. Copy and paste the code below into the new notebook. ```python -def fetch_procurement_data(project_id): + def fetch_project_data(project_id): cursor.execute( - "SELECT data FROM procurement_profiles_dv WHERE JSON_VALUE(data, '$._id') = :project_id", - {'project_id': project_id} + """ + SELECT data + FROM construction_projects_dv + WHERE JSON_VALUE(data, '$._id') = :project_id + """, + {"project_id": project_id} + ) + row = cursor.fetchone() + if not row: + return None + return json.loads(row[0]) if isinstance(row[0], str) else row[0] + + + selected_project_id = 1001 + project_json = fetch_project_data(selected_project_id) + + if project_json: + requirement = (project_json.get("requirements") or [{}])[0] + evaluation = (project_json.get("supplierEvaluations") or [{}])[0] + recommendation = evaluation.get("recommendation") or {} + supplier = recommendation.get("supplier") or {} + + print(f"Project: {project_json.get('projectName', '')}") + print( + "Status:", + evaluation.get( + "evaluationStatus", + project_json.get("evaluationStatus", "Pending Review") + ) ) - result = cursor.fetchone() - return json.loads(result[0]) if result and isinstance(result[0], str) else result[0] if result else None - -selected_project_id = "1001" -procurement_json = fetch_procurement_data(selected_project_id) - -if procurement_json: - print(f"Project: {procurement_json['projectName']}") - print(f"Status: {procurement_json['projectStatus']}") desired_fields = [ ("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")) + ("Project Name", project_json.get("projectName", "")), + ("Location", project_json.get("location", "")), + ("Project Type", project_json.get("projectType", "")), + ("Project Phase", project_json.get("projectPhase", "")), + ("Required Trade", requirement.get("tradeCategory", "")), + ("Material Need", requirement.get("materialNeed", "")), + ( + "Procurement Urgency", + requirement.get("procurementUrgency", "") + ), + ("Budget Range", requirement.get("budgetRange", "")), + ("Risk Level", requirement.get("riskLevel", "")), + ("Evaluation ID", evaluation.get("evaluationId", "")), + ("Recommended Supplier", supplier.get("supplierName", "")), + ("Supplier Fit Score", recommendation.get("fitScore", "")), + ( + "Evaluation Status", + evaluation.get( + "evaluationStatus", + project_json.get("evaluationStatus", "Pending Review") + ) + ) ] - df_procurement_details = pd.DataFrame( + df_project_details = pd.DataFrame( {field_name: [field_value] for field_name, field_value in desired_fields} ) - display(df_procurement_details) - -else: + display(df_project_details) + else: print("No data found for project ID:", selected_project_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. +2. Click the **Run** button to see `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 and help you debug an incorrect project ID or an + incomplete setup script. ![Open Terminal](./images/lab4task3.png " ") @@ -158,43 +204,159 @@ else: printed out when the construction procurement officer opens project `1001`. -## Task 6: Create a function to generate procurement recommendations +## Task 6: Create a function to generate supplier recommendations -In a new cell, define a function `generate_procurement_recommendations` to generate supplier recommendations. +In a new cell, define a function `generate_supplier_recommendations` +to generate supplier recommendations. -With procurement profiles in place, you will use OCI Generative AI to generate personalized procurement recommendations. +With the project profile in place, you will use OCI Generative AI to +generate a construction-specific supplier evaluation. Here’s what we’ll do: -- **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. +- **Fetch Supplier Recommendation Records**: Retrieve the supplier + recommendation rows already staged in `CE_SUPPLIER_RECOMMENDATION` + and combine them with the selected project data. +- **Build a Prompt**: Construct a structured prompt that combines + the project profile, sourcing requirements, and supplier records. + The LLM must choose only from `APPROVE`, `REQUEST INFO`, or `DENY`. +- **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 recommendation using the same + supplier-evaluation sections used in the Seer Construction app. 1. Copy and paste the code in a new cell: ```python - # 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_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') + cursor.execute( + """ + SELECT + eval.EVALUATION_ID, + rec.RECOMMEND_ID, + rec.RECOMMENDATION, + rec.FIT_SCORE, + rec.RISK_LEVEL, + rec.EXPLANATION, + rec.STRENGTHS, + rec.MISSING_INFORMATION, + supplier.SUPPLIER_ID, + supplier.SUPPLIER_NAME, + supplier.CATEGORY, + supplier.REGION, + supplier.CAPACITY_STATUS, + supplier.CAPABILITY_SUMMARY + FROM CE_SUPPLIER_EVALUATION eval + JOIN CE_SUPPLIER_RECOMMENDATION rec + ON rec.RECOMMEND_ID = eval.RECOMMEND_ID + JOIN CE_SUPPLIERS supplier + ON supplier.SUPPLIER_ID = rec.SUPPLIER_ID + WHERE eval.PROJECT_ID = :project_id + ORDER BY rec.FIT_SCORE DESC, eval.EVALUATION_ID + """, + {"project_id": selected_project_id} + ) + df_supplier_recommendations = pd.DataFrame( + cursor.fetchall(), + columns=[ + "EVALUATION_ID", + "RECOMMEND_ID", + "RECOMMENDATION", + "FIT_SCORE", + "RISK_LEVEL", + "EXPLANATION", + "STRENGTHS", + "MISSING_INFORMATION", + "SUPPLIER_ID", + "SUPPLIER_NAME", + "CATEGORY", + "REGION", + "CAPACITY_STATUS", + "CAPABILITY_SUMMARY" + ] + ) + + + def generate_supplier_recommendations(project_id, project_json, df_supplier_recommendations): + requirement = (project_json.get("requirements") or [{}])[0] + evaluation = (project_json.get("supplierEvaluations") or [{}])[0] + recommendation = evaluation.get("recommendation") or {} + + available_data_text = "\n".join([ + ( + f"Supplier Evaluation {row['EVALUATION_ID']}: " + f"{row['SUPPLIER_NAME']} | Decision: {row['RECOMMENDATION']} | " + f"Fit Score: {row['FIT_SCORE']} | Risk: {row['RISK_LEVEL']} | " + f"Capacity: {row['CAPACITY_STATUS']} | " + f"Explanation: {row['EXPLANATION']} | " + f"Missing Information: {row['MISSING_INFORMATION']}" + ) + for row in df_supplier_recommendations.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"] + + project_profile_text = "\n".join([ + f"- Project Name: {project_json.get('projectName', '')}", + f"- Location: {project_json.get('location', '')}", + f"- Project Type: {project_json.get('projectType', '')}", + f"- Project Phase: {project_json.get('projectPhase', '')}", + f"- Project Summary: {project_json.get('projectSummary', '')}", + f"- Required Trade: {requirement.get('tradeCategory', '')}", + f"- Material Need: {requirement.get('materialNeed', '')}", + f"- Required Certification: {requirement.get('requiredCertification', '')}", + f"- Delivery Window: {requirement.get('deliveryWindow', '')}", + f"- Procurement Urgency: {requirement.get('procurementUrgency', '')}", + f"- Budget Range: {requirement.get('budgetRange', '')}", + f"- Risk Level: {requirement.get('riskLevel', '')}", + f"- Current Evaluation Status: {evaluation.get('evaluationStatus', '')}", + f"- Current Recommended Supplier: {recommendation.get('supplier', {}).get('supplierName', '')}" ]) - 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""" + question = "Generate a supplier evaluation for this project." + prompt = f""" +You are an AI supplier evaluation assistant for construction engineering procurement. + +Analyze the selected project and supplier data below. Do not ask for more +project details unless the supplied data is actually missing. Produce the +analysis now. + +Industry: +Construction Engineering + +User request: +{question} + +Selected project profile: +{project_profile_text} + +Project and supplier JSON: +{json.dumps(project_json, default=str)} + +Available supplier recommendation records: +{available_data_text} + +Decision rules: +- Use APPROVE when the supplier is a strong fit and material risks are controlled. +- Use REQUEST INFO when inspection logs, capacity confirmation, certificates, + submittals, RFIs, safety records, or schedule evidence are missing. +- Use DENY when the supplier cannot satisfy core technical, compliance, + delivery, or safety requirements. +- For evidence that says documentation is complete and risk is Low, + recommend APPROVE. +- For Harbor Seismic Retrofit, deny the current suppliers and recommend + submitting a new RFP because the supplier pool does not meet DBE, AISC, + NCR, and logistics requirements. +- For North Campus Lab Expansion, treat an uploaded technical addendum PDF + as new evidence and explicitly reflect it in the re-analysis. + +Return a concise, decision-ready supplier evaluation with these exact sections: + +Project Summary +Key Sourcing Requirements +Top 3 Supplier Recommendations +Risks and Missing Information +Actionable Steps +""" print("Generating AI response...") print(" ") @@ -218,20 +380,27 @@ def generate_procurement_recommendations(project_id, procurement_json, df_suppli ) ) chat_response = genai_client.chat(chat_detail) - recommendations = chat_response.data.chat_response.choices[0].message.content[0].text + return chat_response.data.chat_response.choices[0].message.content[0].text - return recommendations -recommendations = generate_procurement_recommendations(selected_project_id, procurement_json, df_supplier_options) -print(recommendations) + recommendations = generate_supplier_recommendations( + selected_project_id, + project_json, + df_supplier_recommendations + ) + print(recommendations) ``` -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. +2. Click the **Run** button to execute the code. Note that this will + take time to run. Be patient while the LLM evaluates the project + and returns its supplier recommendations. ![Run task 4](./images/lab4task4.png " ") -3. Review the output. In the demo, this is where you selected the **Navigate To Project Decisions** button as the construction procurement officer. +3. Review the output. In the demo, this is where you selected the + **Navigate To Project Decisions** button as the construction + procurement manager. >*Note:* Your result may be different due to the non-deterministic nature of generative AI. @@ -241,67 +410,109 @@ print(recommendations) In this section we will chunk and store the recommendations. -- We delete prior chunks for this project. -- We use `VECTOR_CHUNKS` to insert the chunks. -- 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. +- We delete only the prior `AI Recommendation` chunks for this + project and keep the seeded construction context rows. +- We use `VECTOR_CHUNKS` to split the generated recommendation text. +- The chunks are inserted into `CE_PROJECT_CHUNKS` with a + collision-safe `CHUNK_ID` based on the current maximum chunk ID. +- We display a data frame summary so you can confirm the chunks that + will be used by RAG. 1. Copy the following code and run it in a new cell: ```python - # 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() + if not recommendations: + raise ValueError( + "No recommendations text available to chunk. Run Task 6 first." + ) + + cursor.execute( + """ + DELETE FROM CE_PROJECT_CHUNKS + WHERE PROJECT_ID = :project_id + AND SOURCE_TYPE = 'AI Recommendation' + """, + {"project_id": selected_project_id} + ) + connection.commit() + + cursor.execute("SELECT NVL(MAX(CHUNK_ID), 0) FROM CE_PROJECT_CHUNKS") + base_chunk_id = (cursor.fetchone()[0] or 0) + 1 -chunk_sizes = [50] + chunk_sizes = [50] -for size in chunk_sizes: + for size in chunk_sizes: insert_sql = f""" - INSERT INTO PROCUREMENT_RECOMMENDATION_CHUNK (PROJECT_ID, CHUNK_ID, CHUNK_TEXT) - SELECT :project_id, - :chunk_size + vc.chunk_offset, + INSERT INTO CE_PROJECT_CHUNKS ( + CHUNK_ID, + PROJECT_ID, + SUPPLIER_ID, + SOURCE_TYPE, + CHUNK_TEXT + ) + SELECT + :base_chunk_id + vc.chunk_offset, + :project_id, + NULL, + 'AI Recommendation', vc.chunk_text FROM (SELECT :rec_text AS txt FROM dual) s, VECTOR_CHUNKS( - dbms_vector_chain.utl_to_text(s.txt) - BY words - MAX {size} - OVERLAP 0 - SPLIT BY sentence - LANGUAGE american - NORMALIZE all + dbms_vector_chain.utl_to_text(s.txt) + BY words + MAX {size} + OVERLAP 0 + SPLIT BY sentence + LANGUAGE american + NORMALIZE all ) vc """ cursor.execute( insert_sql, - {'project_id': selected_project_id, 'chunk_size': size, 'rec_text': recommendations} + { + "base_chunk_id": base_chunk_id, + "project_id": selected_project_id, + "rec_text": recommendations + } ) -cursor.execute(""" - SELECT CHUNK_ID, CHUNK_TEXT - FROM PROCUREMENT_RECOMMENDATION_CHUNK - WHERE PROJECT_ID = :project_id - ORDER BY CHUNK_ID -""", {'project_id': selected_project_id}) -rows = cursor.fetchall() + cursor.execute( + """ + SELECT CHUNK_ID, CHUNK_TEXT + FROM CE_PROJECT_CHUNKS + WHERE PROJECT_ID = :project_id + AND SOURCE_TYPE = 'AI Recommendation' + ORDER BY CHUNK_ID + """, + {"project_id": selected_project_id} + ) + rows = cursor.fetchall() + -def _lob_to_str(v): return v.read() if isinstance(v, oracledb.LOB) else v + def _lob_to_str(v): + return v.read() if isinstance(v, oracledb.LOB) else v -items = [] -for cid, ctext in rows: + + items = [] + for cid, ctext in rows: txt = _lob_to_str(ctext) or "" - items.append({ - "CHUNK_ID": cid, - "Chars": len(txt), - "Words": len(txt.split()), - "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 project {selected_project_id} (sizes: {chunk_sizes}).") -display(df_chunks) + items.append( + { + "CHUNK_ID": cid, + "Chars": len(txt), + "Words": len(txt.split()), + "Preview": (txt[:160] + "…") if len(txt) > 160 else txt + } + ) + + df_chunks = pd.DataFrame(items).sort_values("CHUNK_ID") + connection.commit() + print( + "✅ Task 7 complete: recommendation chunked for project " + f"{selected_project_id} (sizes: {chunk_sizes})." + ) + display(df_chunks) ``` @@ -309,35 +520,58 @@ display(df_chunks) ![Run task 7](./images/task5.png " ") -3. Review the output to see the chunked procurement recommendations. +3. Review the output to see the chunked supplier recommendation text. ![Run task 7](./images/task7recs.png " ") ## Task 8: 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 procurement and provide recommendations based on the 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 answer +questions about the project and supplier recommendation. -Before answering questions, we need to prepare the data by vectorizing the recommendations. This step: +Before answering questions, we need to prepare the data by +vectorizing the recommendation chunks. This step: -- **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`. +- **Uses the Recommendation Chunks**: Works with the `AI Recommendation` + rows you inserted into `CE_PROJECT_CHUNKS` in Task 7. +- **Generates Embeddings**: Uses + `dbms_vector_chain.utl_to_embedding` to create vectors directly + in the database. +- **Stores Embeddings**: Updates the `CHUNK_VECTOR` column in + `CE_PROJECT_CHUNKS`. 1. Run and review the code in a new cell: ```python - # Create embeddings for procurement recommendation chunks -cursor.execute(""" - UPDATE PROCUREMENT_RECOMMENDATION_CHUNK - SET CHUNK_VECTOR = dbms_vector_chain.utl_to_embedding( - CHUNK_TEXT, - JSON('{"provider":"database","model":"DEMO_MODEL","dimensions":384}') - ) - WHERE PROJECT_ID = :project_id -""", {'project_id': selected_project_id}) -connection.commit() -print("✅ Task 8 complete: embedded vectors for PROCUREMENT_RECOMMENDATION_CHUNK rows.") + vp = json.dumps( + { + "provider": "database", + "model": "DEMO_MODEL", + "dimensions": 384 + } + ) + + cursor.execute( + """ + UPDATE CE_PROJECT_CHUNKS + SET CHUNK_VECTOR = dbms_vector_chain.utl_to_embedding( + CHUNK_TEXT, + JSON(:vp) + ) + WHERE PROJECT_ID = :project_id + AND SOURCE_TYPE = 'AI Recommendation' + """, + {"vp": vp, "project_id": selected_project_id} + ) + updated = cursor.rowcount or 0 + connection.commit() + print( + "✅ Task 8 complete: embedded vectors for " + f"{updated} CE_PROJECT_CHUNKS row(s)." + ) ``` @@ -347,94 +581,132 @@ print("✅ Task 8 complete: embedded vectors for PROCUREMENT_RECOMMENDATION_CHUN ## Task 9: Implement RAG with Oracle AI Database's Vector Search -Now that the recommendations are vectorized, we can process a user’s question: +Now that the recommendations are vectorized, we can process a user’s +question: -```Which supplier option best fits the Downtown Mixed-Use Tower procurement if we prioritize strong compliance and delivery reliability?``` +```text +Which supplier is the best fit for Downtown Mixed-Use Tower if we +prioritize complete documentation 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**: Retrieves the most relevant recommendation text from `PROCUREMENT_RECOMMENDATION_CHUNK`. -- **Uses RAG**: Combines the procurement profile, supplier options, and 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 `CE_PROJECT_CHUNKS`. +- **Uses RAG**: Combines the project profile, supplier + recommendation records, and retrieved chunk context. +- **Prevents Hallucinations**: Constrains the answer to supplier + names that appear verbatim in the retrieved records and project + context. 1. Copy the code block below to implement RAG: ```python -question = "Which supplier option best fits the Downtown Mixed-Use Tower procurement if we prioritize strong compliance and delivery reliability?" + question = ( + "Which supplier is the best fit for Downtown Mixed-Use Tower " + "if we prioritize complete documentation and delivery reliability?" + ) + -def vectorize_question(q): - cursor.execute(""" + def vectorize_question(q): + cursor.execute( + """ SELECT dbms_vector_chain.utl_to_embedding( :q, JSON('{"provider":"database","model":"DEMO_MODEL","dimensions":384}') - ) FROM DUAL - """, {'q': q}) + ) + FROM DUAL + """, + {"q": q} + ) return cursor.fetchone()[0] -print("Processing your question using AI Vector Search across chunked recommendations...") -try: + print("Processing your question using AI Vector Search...") + + try: q_vec = vectorize_question(question) - cursor.execute(""" + cursor.execute( + """ SELECT CHUNK_ID, CHUNK_TEXT - FROM PROCUREMENT_RECOMMENDATION_CHUNK + FROM CE_PROJECT_CHUNKS WHERE PROJECT_ID = :project_id - AND CHUNK_VECTOR IS NOT NULL + AND CHUNK_VECTOR IS NOT NULL ORDER BY VECTOR_DISTANCE(CHUNK_VECTOR, :qv, COSINE) FETCH FIRST 4 ROWS ONLY - """, {'project_id': selected_project_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() + ( + row[0], + row[1].read() if isinstance(row[1], oracledb.LOB) else row[1] + ) + for row in cursor.fetchall() ] if not retrieved: retrieved = [(0, recommendations)] - cleaned = [re.sub(r"[^\\w\\s\\d.,\\-'\"]", " ", t).strip() for _, t in retrieved] - docs_as_one_string = "\n=========\n".join(cleaned) + "\n=========\n" - - 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') + requirement = (project_json.get("requirements") or [{}])[0] + available_data_text = "\n".join([ + ( + f"Supplier Evaluation {row['EVALUATION_ID']}: " + f"{row['SUPPLIER_NAME']} | Decision: {row['RECOMMENDATION']} | " + f"Fit Score: {row['FIT_SCORE']} | Risk: {row['RISK_LEVEL']} | " + f"Capacity: {row['CAPACITY_STATUS']} | " + f"Explanation: {row['EXPLANATION']} | " + f"Missing Information: {row['MISSING_INFORMATION']}" + ) + for row in df_supplier_recommendations.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"] + project_profile_text = "\n".join([ + f"- Project Name: {project_json.get('projectName', '')}", + f"- Location: {project_json.get('location', '')}", + f"- Project Phase: {project_json.get('projectPhase', '')}", + f"- Required Trade: {requirement.get('tradeCategory', '')}", + f"- Delivery Window: {requirement.get('deliveryWindow', '')}", + f"- Budget Range: {requirement.get('budgetRange', '')}", + f"- Risk Level: {requirement.get('riskLevel', '')}" ]) - - rag_prompt = f"""\ -[INST] <> -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. + context_text = "\n========\n".join(text for _, text in retrieved) + + rag_prompt = f"""[INST] <> +You are the AI Procurement Guru for construction engineering. +Use only the supplied project profile, supplier recommendation +records, and retrieved context. +Do not invent supplier names. +Only use supplier names that appear verbatim in the supplier +recommendation records or retrieved context. +If the evidence is insufficient, say so plainly. +Keep the answer under 220 words and make it decision-ready. <> [/INST] [INST] Question: "{question}" -# Context (top chunks from prior AI recommendations): -{docs_as_one_string} +Selected Project Profile: +{project_profile_text} -# Available Supplier Options: -{available_suppliers_text} +Available Supplier Recommendation Records: +{available_data_text} -# Procurement Profile: -{procurement_profile_text} +Retrieved Context: +{context_text} Tasks: -1) Provide a direct answer to the question. -2) Briefly justify based on the procurement profile and available supplier options. -[/INST]""" +1. Answer the question directly. +2. Justify the answer using fit, risk, delivery, and documentation signals. +3. If there is a reasonable backup supplier, name it briefly. + [/INST]""" print("Generating AI response...") genai_client = oci.generative_ai_inference.GenerativeAiInferenceClient( - config=oci.config.from_file(os.getenv("OCI_CONFIG_PATH","~/.oci/config")), + 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( @@ -451,18 +723,22 @@ 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 = ( + chat_response.data.chat_response.choices[0] + .message.content[0].text + ) - print("\n🤖 AI Procurement Guru Response:") + print("\\n🤖 AI Procurement Guru Response:") print(ai_response) - print("\n📑 Retrieved Chunks Used in Response:") + print("\\n📑 Retrieved Chunks Used in Response:") for cid, text in retrieved: - preview = text[:140].replace("\n", " ") + ("..." if len(text) > 140 else "") + preview = text[:140].replace("\\n", " ") + if len(text) > 140: + preview += "..." print(f"[Chunk {cid}] : {preview}") -except Exception as e: + except Exception as e: print(f"RAG flow error: {e}") ``` @@ -484,9 +760,11 @@ 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 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. +* You created a function to retrieve construction project data. +* You created a function to connect to OCI Generative AI and create + supplier recommendations. +* You created embeddings of supplier recommendation chunks using + Oracle AI Database. * And finally, you implemented a RAG process in Oracle AI Database using Python. Congratulations, you completed the lab. 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 b29250621..52397f1ae 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,66 +1,302 @@ -/* 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) +-- Construction Engineering supplier evaluation model +DROP TABLE IF EXISTS CE_SUPPLIER_DEPENDENCIES CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_PROJECT_CHUNKS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_DECISION CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPORTING_DOCS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_EVALUATION CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_RECOMMENDATION CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_PERFORMANCE CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_CERTIFICATIONS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIERS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_PROJECT_REQUIREMENTS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_PROJECTS CASCADE CONSTRAINTS PURGE; +DROP VIEW IF EXISTS CONSTRUCTION_PROJECTS_DV; +DROP PROPERTY GRAPH IF EXISTS CONSTRUCTION_ENGINEERING_GRAPH; + +CREATE TABLE IF NOT EXISTS CE_PROJECTS ( + PROJECT_ID NUMBER PRIMARY KEY, + PROJECT_NAME VARCHAR2(200) NOT NULL, + LOCATION VARCHAR2(200), + PROJECT_TYPE VARCHAR2(100), + PROJECT_PHASE VARCHAR2(100), + PROJECT_SUMMARY CLOB, + START_DATE DATE, + TARGET_DELIVERY_DATE DATE, + EVALUATION_STATUS VARCHAR2(50), + CREATED_BY VARCHAR2(100) +); + +CREATE TABLE IF NOT EXISTS CE_PROJECT_REQUIREMENTS ( + REQUIREMENT_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + TRADE_CATEGORY VARCHAR2(100), + MATERIAL_NEED VARCHAR2(200), + TECHNICAL_SPEC CLOB, + REQUIRED_CERTIFICATION VARCHAR2(200), + DELIVERY_WINDOW VARCHAR2(100), + PROCUREMENT_URGENCY VARCHAR2(50), + BUDGET_RANGE VARCHAR2(100), + RISK_LEVEL VARCHAR2(50) +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIERS ( + SUPPLIER_ID NUMBER PRIMARY KEY, + SUPPLIER_NAME VARCHAR2(200) NOT NULL, + CATEGORY VARCHAR2(100), + REGION VARCHAR2(100), + EMAIL VARCHAR2(100), + PHONE_NUMBER VARCHAR2(20), + ACTIVE CHAR(1), + CAPACITY_STATUS VARCHAR2(50), + CAPABILITY_SUMMARY CLOB +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_CERTIFICATIONS ( + CERT_ID NUMBER PRIMARY KEY, + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + CERTIFICATION_NAME VARCHAR2(200), + ISSUED_BY VARCHAR2(200), + EXPIRES_ON DATE, + STATUS VARCHAR2(50) +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_PERFORMANCE ( + PERFORMANCE_ID NUMBER PRIMARY KEY, + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + PROJECT_TYPE VARCHAR2(100), + SIMILAR_PROJECT_COUNT NUMBER, + ON_TIME_DELIVERY_RATE NUMBER(5,2), + COST_VARIANCE_PCT NUMBER(5,2), + UNRESOLVED_NCR_COUNT NUMBER, + SAFETY_SCORE NUMBER(5,2), + LAST_EVALUATED DATE +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_RECOMMENDATION ( + RECOMMEND_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + RECOMMENDATION VARCHAR2(50), + FIT_SCORE NUMBER(5,2), + RISK_LEVEL VARCHAR2(50), + EXPLANATION CLOB, + STRENGTHS CLOB, + MISSING_INFORMATION CLOB, + GENERATED_DATE DATE DEFAULT SYSDATE +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_EVALUATION ( + EVALUATION_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + RECOMMEND_ID NUMBER REFERENCES CE_SUPPLIER_RECOMMENDATION(RECOMMEND_ID), + REQUEST_DATE DATE, + EVALUATION_STATUS VARCHAR2(50), + FINAL_DECISION VARCHAR2(50), + DECISION_DATE DATE +); + +CREATE TABLE IF NOT EXISTS CE_SUPPORTING_DOCS ( + DOC_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + DOC_TYPE VARCHAR2(100), + FILE_NAME VARCHAR2(255), + DOC_TEXT CLOB, + UPLOAD_TIME DATE DEFAULT SYSDATE +); + +CREATE TABLE IF NOT EXISTS CE_DECISION ( + DEC_ID NUMBER PRIMARY KEY, + EVALUATION_ID NUMBER REFERENCES CE_SUPPLIER_EVALUATION(EVALUATION_ID), + DECISION_TYPE VARCHAR2(50), + LETTER_TEXT CLOB, + GENERATED_ON DATE DEFAULT SYSDATE ); -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 CE_PROJECT_CHUNKS ( + CHUNK_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + SOURCE_TYPE VARCHAR2(50), + CHUNK_TEXT CLOB, + CHUNK_VECTOR VECTOR(384,*,DENSE) ); -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) +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_DEPENDENCIES ( + DEPENDENCY_ID NUMBER PRIMARY KEY, + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + RELATED_SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + DEPENDENCY_TYPE VARCHAR2(100), + RISK_NOTE VARCHAR2(1000) ); -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 - }; +INSERT INTO CE_PROJECTS VALUES (1001, 'Downtown Mixed-Use Tower', 'San Jose, California', 'Mixed-use commercial building', 'Procurement', 'Mid-rise mixed-use project requiring structural steel framing, fire-rated assemblies, shop drawing support, inspection documentation, and regional delivery within a compressed schedule. Atlas Structural Fabrication has complete documentation and low supplier risk, so this project is ready for approval.', DATE '2026-06-01', DATE '2026-08-15', 'Pending Review', 'Maya Chen'); +INSERT INTO CE_PROJECTS VALUES (1002, 'Bayfront Utility Upgrade', 'Oakland, California', 'Infrastructure', 'Preconstruction', 'Public works utility upgrade requiring concrete vaults, electrical gear, traffic controls, and suppliers with public-sector documentation history.', DATE '2026-07-10', DATE '2026-10-01', 'In Progress', 'Jordan Patel'); +INSERT INTO CE_PROJECTS VALUES (1003, 'Harbor Seismic Retrofit', 'Long Beach, California', 'Public works retrofit', 'Procurement', 'Seismic retrofit project requiring specialty steel bracing, strict public works documentation, DBE participation, and suppliers with clean nonconformance history. Existing supplier pool does not meet core compliance requirements, so the recommended action is to deny current suppliers and issue a new RFP.', DATE '2026-07-15', DATE '2026-09-30', 'Pending Review', 'Elena Ruiz'); +INSERT INTO CE_PROJECTS VALUES (1004, 'North Campus Lab Expansion', 'Palo Alto, California', 'Laboratory expansion', 'Procurement', 'Laboratory expansion requiring HVAC equipment, cleanroom-compatible ductwork, seismic anchorage documentation, and manufacturer startup support. The evaluation is waiting for an uploaded technical addendum before AI re-analysis.', DATE '2026-08-01', DATE '2026-11-15', 'Pending Review', 'Priya Raman'); + +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2001, 1001, 'Structural Steel', 'Fabricated beams, columns, and connection assemblies', 'AISC-compliant structural steel package for a mid-rise commercial frame, including mill certificates, weld procedures, shop drawings, and inspection documentation.', 'AISC Certification; AWS Certified Welders', 'Six weeks', 'High', '$2.4M - $2.9M', 'Low'); +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2002, 1002, 'Electrical Systems', 'Switchgear and underground utility components', 'Utility-grade electrical equipment with public works submittals, delivery traceability, and site coordination documentation.', 'UL Listed Components; OSHA Safety Program', 'Ten weeks', 'Medium', '$900K - $1.3M', 'Medium'); +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2003, 1003, 'Seismic Steel Bracing', 'Buckling-restrained braces, embeds, and retrofit connection plates', 'Public works seismic retrofit package requiring documented AISC fabrication, DBE participation, certified welding procedures, unresolved NCR count of zero, and verified delivery access for night work.', 'AISC Certification; AWS Certified Welders; DBE Participation', 'Four weeks', 'Critical', '$1.8M - $2.2M', 'High'); +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2004, 1004, 'Mechanical Systems', 'Cleanroom HVAC units, ductwork, controls, and startup support', 'Laboratory HVAC package requiring cleanroom-compatible ductwork, seismic anchorage calculations, TAB plan, manufacturer startup support, and submittal-ready technical documentation.', 'OSHPD/Seismic Anchorage Documentation; Factory Startup Authorization', 'Eight weeks', 'Medium', '$1.1M - $1.6M', 'Medium'); + +INSERT INTO CE_SUPPLIERS VALUES (3001, 'Atlas Structural Fabrication', 'Structural Steel', 'Northern California', 'estimating@atlasstructural.example', '408-555-0140', 'Y', 'Constrained', 'Certified structural steel fabricator with mid-rise commercial experience, shop drawing support, weld procedure documentation, and strong regional delivery history.'); +INSERT INTO CE_SUPPLIERS VALUES (3002, 'WestBridge Steel Supply', 'Structural Steel', 'Bay Area', 'bids@westbridgesteel.example', '510-555-0188', 'Y', 'Available', 'Regional steel supplier with competitive cost history and broad material availability; updated inspection package is still pending.'); +INSERT INTO CE_SUPPLIERS VALUES (3003, 'Northline Industrial Metals', 'Structural Steel', 'Central California', 'rfq@northlinemetals.example', '559-555-0199', 'Y', 'Available', 'Industrial metals supplier with strong fabrication capabilities and prior commercial work, but recent schedule confirmations are required due to historical delivery delays.'); +INSERT INTO CE_SUPPLIERS VALUES (3004, 'Coastal Retrofit Metals', 'Seismic Steel', 'Southern California', 'bids@coastalretrofit.example', '562-555-0111', 'Y', 'Overloaded', 'Retrofit steel supplier with partial seismic brace experience but missing DBE documentation and open nonconformance items.'); +INSERT INTO CE_SUPPLIERS VALUES (3005, 'Pacific Brace Works', 'Seismic Steel', 'California', 'estimating@pacificbrace.example', '714-555-0122', 'Y', 'Available', 'Specialty bracing supplier with competitive pricing but expired AISC certification and limited public works documentation.'); +INSERT INTO CE_SUPPLIERS VALUES (3006, 'Civic Steel Partners', 'Seismic Steel', 'Western US', 'rfp@civicsteel.example', '916-555-0177', 'Y', 'Available', 'Regional steel supplier with public-sector references but unresolved weld NCRs and no verified night-work delivery plan.'); +INSERT INTO CE_SUPPLIERS VALUES (3007, 'Precision Air Systems', 'Mechanical Systems', 'Northern California', 'labprojects@precisionair.example', '650-555-0133', 'Y', 'Available', 'Mechanical systems supplier with cleanroom HVAC experience, seismic anchorage partners, and factory startup authorization after updated technical package is received.'); +INSERT INTO CE_SUPPLIERS VALUES (3008, 'Valley Mechanical Supply', 'Mechanical Systems', 'Bay Area', 'quotes@valleymechanical.example', '408-555-0166', 'Y', 'Constrained', 'Mechanical supplier with competitive cost history but missing cleanroom TAB documentation and limited startup support availability.'); + +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4001, 3001, 'AISC Certified Fabricator', 'AISC', DATE '2027-05-31', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4002, 3001, 'AWS Certified Welding Program', 'AWS', DATE '2027-03-15', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4003, 3002, 'AISC Certified Fabricator', 'AISC', DATE '2026-12-31', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4004, 3003, 'AWS Certified Welding Program', 'AWS', DATE '2027-01-20', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4005, 3004, 'DBE Participation Letter', 'Agency Self-Report', DATE '2026-08-01', 'Missing'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4006, 3005, 'AISC Certified Fabricator', 'AISC', DATE '2025-12-31', 'Expired'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4007, 3006, 'AWS Certified Welding Program', 'AWS', DATE '2027-02-28', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4008, 3007, 'Factory Startup Authorization', 'HVAC Manufacturer', DATE '2027-06-30', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4009, 3007, 'Seismic Anchorage Partner Letter', 'Structural Engineer', DATE '2027-04-30', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4010, 3008, 'Cleanroom TAB Documentation', 'Independent TAB Agency', DATE '2026-09-01', 'Missing'); + +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5001, 3001, 'Mid-rise commercial', 3, 94.00, 2.10, 0, 96.00, DATE '2026-05-20'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5002, 3002, 'Commercial steel framing', 2, 89.00, -1.80, 1, 91.00, DATE '2026-05-18'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5003, 3003, 'Industrial and commercial', 4, 82.00, 4.70, 2, 88.00, DATE '2026-05-12'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5004, 3004, 'Seismic retrofit', 1, 61.00, 9.40, 3, 74.00, DATE '2026-05-25'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5005, 3005, 'Public works retrofit', 1, 68.00, 6.10, 1, 79.00, DATE '2026-05-28'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5006, 3006, 'Civic infrastructure', 2, 72.00, 8.90, 2, 81.00, DATE '2026-05-29'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5007, 3007, 'Laboratory HVAC', 4, 93.00, 1.80, 0, 95.00, DATE '2026-06-02'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5008, 3008, 'Healthcare and lab mechanical', 3, 84.00, 3.90, 1, 88.00, DATE '2026-06-03'); + +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6001, 1001, 3001, 'Approved', 97.00, 'Low', 'Atlas Structural Fabrication is approved because it has completed three similar mid-rise steel frame projects, maintains current AISC and AWS documentation, has a 96 percent on-time delivery rate, has no unresolved inspection failures in the past 24 months, and has confirmed capacity for the six-week delivery window.', 'AISC certification, certified weld procedures, commercial steel framing experience, complete mill certificates, clean inspection history, confirmed delivery capacity, low supplier risk.', 'No blocking information is missing. Proceed with supplier confirmation and purchase package preparation.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6002, 1001, 3002, 'Request Info', 86.00, 'Medium', 'WestBridge Steel Supply has competitive cost history and good regional availability, but the evaluation is incomplete because current inspection documentation has not been provided.', 'Competitive cost performance, regional availability, current AISC certification.', 'Updated inspection logs, mill certificates, and nonconformance closeout evidence.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6003, 1001, 3003, 'Request Info', 78.00, 'High', 'Northline Industrial Metals has fabrication capability and similar project experience, but prior delivery delays and unresolved nonconformance count require schedule and quality confirmation before selection.', 'Strong fabrication capabilities and similar project references.', 'Delivery schedule confirmation, corrective action evidence, and updated inspection records.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6004, 1003, 3004, 'Denied', 38.00, 'High', 'Coastal Retrofit Metals should be denied because DBE participation documentation is missing, capacity is overloaded, and three unresolved nonconformance reports conflict with the public works retrofit requirements.', 'Some seismic retrofit experience.', 'DBE letter, NCR closeout evidence, and capacity plan are missing. Submit an RFP for new qualified seismic steel suppliers.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6005, 1003, 3005, 'Denied', 34.00, 'High', 'Pacific Brace Works should be denied because AISC certification is expired and public works documentation is incomplete for the required seismic retrofit scope.', 'Competitive pricing.', 'Current AISC certification and public works documentation are missing. Submit an RFP for new qualified seismic steel suppliers.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6006, 1003, 3006, 'Denied', 31.00, 'Very High', 'Civic Steel Partners should be denied because unresolved weld nonconformance reports and no verified night-work logistics plan create unacceptable schedule and quality risk.', 'Public-sector references.', 'NCR closeout evidence and night-work delivery plan are missing. Submit an RFP for new qualified seismic steel suppliers.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6007, 1004, 3007, 'Request Info', 82.00, 'Medium', 'Precision Air Systems is the leading candidate for the lab expansion, but the evaluation is pending the updated technical addendum with cleanroom TAB plan, seismic anchorage package, and factory startup letter. Re-analyze after PDF upload.', 'Laboratory HVAC experience, clean startup support, current factory authorization.', 'Upload technical addendum with TAB plan, seismic anchorage package, startup letter, and updated delivery confirmation.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6008, 1004, 3008, 'Request Info', 68.00, 'Medium', 'Valley Mechanical Supply has cost advantages but lacks cleanroom TAB documentation and has constrained startup support availability.', 'Competitive cost history and regional availability.', 'Cleanroom TAB documentation and startup support confirmation are missing.', SYSDATE); + +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7001, 1001, 6001, SYSDATE, 'Pending Review', NULL, NULL); +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7002, 1002, NULL, SYSDATE, 'In Progress', NULL, NULL); +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7003, 1003, 6004, SYSDATE, 'Pending Review', NULL, NULL); +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7004, 1004, 6007, SYSDATE, 'Pending Review', NULL, NULL); + +INSERT INTO CE_SUPPORTING_DOCS VALUES (8001, 1001, 3001, 'Inspection Log', 'atlas_inspection_log_2026.pdf', 'Inspection log shows no unresolved weld inspection failures for comparable mid-rise commercial projects in the last 24 months.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8002, 1001, 3001, 'Material Certificate', 'atlas_mill_certificates.pdf', 'Mill certificate package covers wide flange beams, columns, and connection assemblies required for the Downtown Mixed-Use Tower.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8003, 1001, 3002, 'Qualification File', 'westbridge_supplier_qualification.pdf', 'Supplier qualification file confirms AISC certification and regional availability but omits the most recent inspection log.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8004, 1003, 3004, 'Supplier Qualification', 'coastal_retrofit_qualification.pdf', 'Supplier package has missing DBE participation letter, overloaded shop capacity, and unresolved NCR history. Existing suppliers should be denied and new RFP should be submitted.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8005, 1004, 3007, 'Pending Technical Addendum', 'Construction_Supplier_Evaluation.pdf', 'Upload PDF contains the lab HVAC technical addendum needed for AI re-analysis, including TAB plan, seismic anchorage package, startup letter, and updated delivery confirmation.', SYSDATE); +INSERT INTO CE_DECISION VALUES (9001, 7001, 'Approve Recommended', 'Atlas Structural Fabrication has complete certification, inspection, capacity, and delivery evidence. Recommended path is to approve and confirm the supplier.', SYSDATE); +INSERT INTO CE_DECISION VALUES (9002, 7003, 'RFP Recommended', 'Current seismic steel suppliers do not meet DBE, AISC, nonconformance, and logistics requirements. Deny current suppliers and submit a new RFP.', SYSDATE); +INSERT INTO CE_DECISION VALUES (9003, 7004, 'Request Info', 'Upload the lab HVAC technical addendum and re-run AI analysis before confirming supplier selection.', SYSDATE); + +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10001, 1001, 3001, 'Project Requirement', 'Downtown Mixed-Use Tower requires structural steel framing, fabricated beams and columns, connection assemblies, AISC certification, AWS certified welders, mill certificates, shop drawings, inspection records, and delivery within six weeks. Required evidence is complete.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10002, 1001, 3001, 'Supplier Profile', 'Atlas Structural Fabrication has completed three similar mid-rise steel frame projects, maintains current AISC certification, has certified weld procedure documentation, confirmed delivery capacity, no unresolved inspection failures, and low supplier risk.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10003, 1001, 3002, 'Supplier Profile', 'WestBridge Steel Supply has competitive cost history and good regional availability, but updated inspection documentation and nonconformance closeout records are missing.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10004, 1003, 3004, 'RFP Trigger', 'Harbor Seismic Retrofit has no acceptable supplier in the current pool. Coastal Retrofit Metals lacks DBE documentation, Pacific Brace Works has expired AISC certification, and Civic Steel Partners has unresolved weld NCRs. Deny suppliers and submit an RFP.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10005, 1004, 3007, 'PDF Upload Scenario', 'North Campus Lab Expansion is awaiting a technical addendum PDF. Upload should add cleanroom TAB plan, seismic anchorage package, factory startup authorization, and updated delivery confirmation for AI re-analysis.'); +INSERT INTO CE_SUPPLIER_DEPENDENCIES VALUES (11001, 3001, 3002, 'Shared coating subcontractor', 'Both suppliers may use the same coating subcontractor, which could create schedule pressure if both are selected for concurrent projects.'); +INSERT INTO CE_SUPPLIER_DEPENDENCIES VALUES (11002, 3004, 3006, 'Shared inspection consultant', 'Both seismic retrofit suppliers rely on the same inspection consultant, creating a hidden review bottleneck for public works closeout.'); + +CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW construction_projects_dv AS +SELECT JSON { + '_id': p.PROJECT_ID, + 'projectName': p.PROJECT_NAME, + 'location': p.LOCATION, + 'projectType': p.PROJECT_TYPE, + 'projectPhase': p.PROJECT_PHASE, + 'projectSummary': p.PROJECT_SUMMARY, + 'startDate': p.START_DATE, + 'targetDeliveryDate': p.TARGET_DELIVERY_DATE, + 'evaluationStatus': p.EVALUATION_STATUS, + 'createdBy': p.CREATED_BY, + 'requirements': [ + SELECT JSON { + 'requirementId': r.REQUIREMENT_ID, + 'tradeCategory': r.TRADE_CATEGORY, + 'materialNeed': r.MATERIAL_NEED, + 'technicalSpec': r.TECHNICAL_SPEC, + 'requiredCertification': r.REQUIRED_CERTIFICATION, + 'deliveryWindow': r.DELIVERY_WINDOW, + 'procurementUrgency': r.PROCUREMENT_URGENCY, + 'budgetRange': r.BUDGET_RANGE, + 'riskLevel': r.RISK_LEVEL + } + FROM CE_PROJECT_REQUIREMENTS r WITH INSERT UPDATE DELETE + WHERE r.PROJECT_ID = p.PROJECT_ID + ], + 'supplierEvaluations': [ + SELECT JSON { + 'evaluationId': e.EVALUATION_ID, + 'requestDate': e.REQUEST_DATE, + 'evaluationStatus': e.EVALUATION_STATUS, + 'finalDecision': e.FINAL_DECISION, + 'decisionDate': e.DECISION_DATE, + 'recommendation': ( + SELECT JSON { + 'recommendId': rec.RECOMMEND_ID, + 'recommendation': rec.RECOMMENDATION, + 'fitScore': rec.FIT_SCORE, + 'riskLevel': rec.RISK_LEVEL, + 'explanation': rec.EXPLANATION, + 'strengths': rec.STRENGTHS, + 'missingInformation': rec.MISSING_INFORMATION, + 'generatedDate': rec.GENERATED_DATE, + 'supplier': ( + SELECT JSON { + 'supplierId': s.SUPPLIER_ID, + 'supplierName': s.SUPPLIER_NAME, + 'category': s.CATEGORY, + 'region': s.REGION, + 'email': s.EMAIL, + 'phone': s.PHONE_NUMBER, + 'active': s.ACTIVE, + 'capacityStatus': s.CAPACITY_STATUS, + 'capabilitySummary': s.CAPABILITY_SUMMARY + } + FROM CE_SUPPLIERS s + WHERE s.SUPPLIER_ID = rec.SUPPLIER_ID + ) + } + FROM CE_SUPPLIER_RECOMMENDATION rec WITH UPDATE + WHERE rec.RECOMMEND_ID = e.RECOMMEND_ID + ) + } + FROM CE_SUPPLIER_EVALUATION e WITH INSERT UPDATE DELETE + WHERE e.PROJECT_ID = p.PROJECT_ID + ] +} +FROM CE_PROJECTS p +WITH INSERT UPDATE DELETE; + +CREATE OR REPLACE PROPERTY GRAPH CONSTRUCTION_ENGINEERING_GRAPH + VERTEX TABLES ( + "CE_PROJECTS" KEY ("PROJECT_ID") PROPERTIES ("PROJECT_NAME", "LOCATION", "PROJECT_TYPE", "PROJECT_PHASE", "EVALUATION_STATUS"), + "CE_PROJECT_REQUIREMENTS" KEY ("REQUIREMENT_ID") PROPERTIES ("PROJECT_ID", "TRADE_CATEGORY", "MATERIAL_NEED", "REQUIRED_CERTIFICATION", "PROCUREMENT_URGENCY", "RISK_LEVEL"), + "CE_SUPPLIERS" KEY ("SUPPLIER_ID") PROPERTIES ("SUPPLIER_NAME", "CATEGORY", "REGION", "ACTIVE", "CAPACITY_STATUS"), + "CE_SUPPLIER_RECOMMENDATION" KEY ("RECOMMEND_ID") PROPERTIES ("PROJECT_ID", "SUPPLIER_ID", "RECOMMENDATION", "FIT_SCORE", "RISK_LEVEL"), + "CE_SUPPLIER_EVALUATION" KEY ("EVALUATION_ID") PROPERTIES ("PROJECT_ID", "RECOMMEND_ID", "EVALUATION_STATUS", "FINAL_DECISION"), + "CE_SUPPLIER_DEPENDENCIES" KEY ("DEPENDENCY_ID") PROPERTIES ("SUPPLIER_ID", "RELATED_SUPPLIER_ID", "DEPENDENCY_TYPE", "RISK_NOTE") + ) + EDGE TABLES ( + "CE_PROJECT_REQUIREMENTS" AS project_has_requirement + SOURCE KEY ("PROJECT_ID") REFERENCES "CE_PROJECTS"("PROJECT_ID") + DESTINATION KEY ("REQUIREMENT_ID") REFERENCES "CE_PROJECT_REQUIREMENTS"("REQUIREMENT_ID") + PROPERTIES ("TRADE_CATEGORY", "PROCUREMENT_URGENCY", "RISK_LEVEL"), + "CE_SUPPLIER_RECOMMENDATION" AS project_recommends_supplier + SOURCE KEY ("PROJECT_ID") REFERENCES "CE_PROJECTS"("PROJECT_ID") + DESTINATION KEY ("SUPPLIER_ID") REFERENCES "CE_SUPPLIERS"("SUPPLIER_ID") + PROPERTIES ("RECOMMEND_ID", "RECOMMENDATION", "FIT_SCORE", "RISK_LEVEL"), + "CE_SUPPLIER_EVALUATION" AS evaluation_for_project + SOURCE KEY ("PROJECT_ID") REFERENCES "CE_PROJECTS"("PROJECT_ID") + DESTINATION KEY ("EVALUATION_ID") REFERENCES "CE_SUPPLIER_EVALUATION"("EVALUATION_ID") + PROPERTIES ("EVALUATION_STATUS", "FINAL_DECISION"), + "CE_SUPPLIER_DEPENDENCIES" AS supplier_dependency + SOURCE KEY ("SUPPLIER_ID") REFERENCES "CE_SUPPLIERS"("SUPPLIER_ID") + DESTINATION KEY ("RELATED_SUPPLIER_ID") REFERENCES "CE_SUPPLIERS"("SUPPLIER_ID") + PROPERTIES ("DEPENDENCY_TYPE", "RISK_NOTE") + ); + +COMMIT; 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 9eea1695a..407526269 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 c841c299a..a43a229b3 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/tables.png b/dev-ai-app-dev-constructioneng-aiexperience/build/images/tables.png index 4654c46ed..95b4d8de9 100644 Binary files a/dev-ai-app-dev-constructioneng-aiexperience/build/images/tables.png and b/dev-ai-app-dev-constructioneng-aiexperience/build/images/tables.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 a1da02284..b0d4e3cc4 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 e83375f48..e8793c948 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 e782fc591..a0f06744d 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 e41997718..30be44fa5 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 d713566ce..240d8e761 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 db286ae04..3d00ac944 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/user-story/files/starter-file.sql b/dev-ai-app-dev-constructioneng-aiexperience/user-story/files/starter-file.sql index b29250621..52397f1ae 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,66 +1,302 @@ -/* 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) +-- Construction Engineering supplier evaluation model +DROP TABLE IF EXISTS CE_SUPPLIER_DEPENDENCIES CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_PROJECT_CHUNKS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_DECISION CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPORTING_DOCS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_EVALUATION CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_RECOMMENDATION CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_PERFORMANCE CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIER_CERTIFICATIONS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_SUPPLIERS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_PROJECT_REQUIREMENTS CASCADE CONSTRAINTS PURGE; +DROP TABLE IF EXISTS CE_PROJECTS CASCADE CONSTRAINTS PURGE; +DROP VIEW IF EXISTS CONSTRUCTION_PROJECTS_DV; +DROP PROPERTY GRAPH IF EXISTS CONSTRUCTION_ENGINEERING_GRAPH; + +CREATE TABLE IF NOT EXISTS CE_PROJECTS ( + PROJECT_ID NUMBER PRIMARY KEY, + PROJECT_NAME VARCHAR2(200) NOT NULL, + LOCATION VARCHAR2(200), + PROJECT_TYPE VARCHAR2(100), + PROJECT_PHASE VARCHAR2(100), + PROJECT_SUMMARY CLOB, + START_DATE DATE, + TARGET_DELIVERY_DATE DATE, + EVALUATION_STATUS VARCHAR2(50), + CREATED_BY VARCHAR2(100) +); + +CREATE TABLE IF NOT EXISTS CE_PROJECT_REQUIREMENTS ( + REQUIREMENT_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + TRADE_CATEGORY VARCHAR2(100), + MATERIAL_NEED VARCHAR2(200), + TECHNICAL_SPEC CLOB, + REQUIRED_CERTIFICATION VARCHAR2(200), + DELIVERY_WINDOW VARCHAR2(100), + PROCUREMENT_URGENCY VARCHAR2(50), + BUDGET_RANGE VARCHAR2(100), + RISK_LEVEL VARCHAR2(50) +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIERS ( + SUPPLIER_ID NUMBER PRIMARY KEY, + SUPPLIER_NAME VARCHAR2(200) NOT NULL, + CATEGORY VARCHAR2(100), + REGION VARCHAR2(100), + EMAIL VARCHAR2(100), + PHONE_NUMBER VARCHAR2(20), + ACTIVE CHAR(1), + CAPACITY_STATUS VARCHAR2(50), + CAPABILITY_SUMMARY CLOB +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_CERTIFICATIONS ( + CERT_ID NUMBER PRIMARY KEY, + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + CERTIFICATION_NAME VARCHAR2(200), + ISSUED_BY VARCHAR2(200), + EXPIRES_ON DATE, + STATUS VARCHAR2(50) +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_PERFORMANCE ( + PERFORMANCE_ID NUMBER PRIMARY KEY, + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + PROJECT_TYPE VARCHAR2(100), + SIMILAR_PROJECT_COUNT NUMBER, + ON_TIME_DELIVERY_RATE NUMBER(5,2), + COST_VARIANCE_PCT NUMBER(5,2), + UNRESOLVED_NCR_COUNT NUMBER, + SAFETY_SCORE NUMBER(5,2), + LAST_EVALUATED DATE +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_RECOMMENDATION ( + RECOMMEND_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + RECOMMENDATION VARCHAR2(50), + FIT_SCORE NUMBER(5,2), + RISK_LEVEL VARCHAR2(50), + EXPLANATION CLOB, + STRENGTHS CLOB, + MISSING_INFORMATION CLOB, + GENERATED_DATE DATE DEFAULT SYSDATE +); + +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_EVALUATION ( + EVALUATION_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + RECOMMEND_ID NUMBER REFERENCES CE_SUPPLIER_RECOMMENDATION(RECOMMEND_ID), + REQUEST_DATE DATE, + EVALUATION_STATUS VARCHAR2(50), + FINAL_DECISION VARCHAR2(50), + DECISION_DATE DATE +); + +CREATE TABLE IF NOT EXISTS CE_SUPPORTING_DOCS ( + DOC_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + DOC_TYPE VARCHAR2(100), + FILE_NAME VARCHAR2(255), + DOC_TEXT CLOB, + UPLOAD_TIME DATE DEFAULT SYSDATE +); + +CREATE TABLE IF NOT EXISTS CE_DECISION ( + DEC_ID NUMBER PRIMARY KEY, + EVALUATION_ID NUMBER REFERENCES CE_SUPPLIER_EVALUATION(EVALUATION_ID), + DECISION_TYPE VARCHAR2(50), + LETTER_TEXT CLOB, + GENERATED_ON DATE DEFAULT SYSDATE ); -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 CE_PROJECT_CHUNKS ( + CHUNK_ID NUMBER PRIMARY KEY, + PROJECT_ID NUMBER REFERENCES CE_PROJECTS(PROJECT_ID), + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + SOURCE_TYPE VARCHAR2(50), + CHUNK_TEXT CLOB, + CHUNK_VECTOR VECTOR(384,*,DENSE) ); -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) +CREATE TABLE IF NOT EXISTS CE_SUPPLIER_DEPENDENCIES ( + DEPENDENCY_ID NUMBER PRIMARY KEY, + SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + RELATED_SUPPLIER_ID NUMBER REFERENCES CE_SUPPLIERS(SUPPLIER_ID), + DEPENDENCY_TYPE VARCHAR2(100), + RISK_NOTE VARCHAR2(1000) ); -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 - }; +INSERT INTO CE_PROJECTS VALUES (1001, 'Downtown Mixed-Use Tower', 'San Jose, California', 'Mixed-use commercial building', 'Procurement', 'Mid-rise mixed-use project requiring structural steel framing, fire-rated assemblies, shop drawing support, inspection documentation, and regional delivery within a compressed schedule. Atlas Structural Fabrication has complete documentation and low supplier risk, so this project is ready for approval.', DATE '2026-06-01', DATE '2026-08-15', 'Pending Review', 'Maya Chen'); +INSERT INTO CE_PROJECTS VALUES (1002, 'Bayfront Utility Upgrade', 'Oakland, California', 'Infrastructure', 'Preconstruction', 'Public works utility upgrade requiring concrete vaults, electrical gear, traffic controls, and suppliers with public-sector documentation history.', DATE '2026-07-10', DATE '2026-10-01', 'In Progress', 'Jordan Patel'); +INSERT INTO CE_PROJECTS VALUES (1003, 'Harbor Seismic Retrofit', 'Long Beach, California', 'Public works retrofit', 'Procurement', 'Seismic retrofit project requiring specialty steel bracing, strict public works documentation, DBE participation, and suppliers with clean nonconformance history. Existing supplier pool does not meet core compliance requirements, so the recommended action is to deny current suppliers and issue a new RFP.', DATE '2026-07-15', DATE '2026-09-30', 'Pending Review', 'Elena Ruiz'); +INSERT INTO CE_PROJECTS VALUES (1004, 'North Campus Lab Expansion', 'Palo Alto, California', 'Laboratory expansion', 'Procurement', 'Laboratory expansion requiring HVAC equipment, cleanroom-compatible ductwork, seismic anchorage documentation, and manufacturer startup support. The evaluation is waiting for an uploaded technical addendum before AI re-analysis.', DATE '2026-08-01', DATE '2026-11-15', 'Pending Review', 'Priya Raman'); + +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2001, 1001, 'Structural Steel', 'Fabricated beams, columns, and connection assemblies', 'AISC-compliant structural steel package for a mid-rise commercial frame, including mill certificates, weld procedures, shop drawings, and inspection documentation.', 'AISC Certification; AWS Certified Welders', 'Six weeks', 'High', '$2.4M - $2.9M', 'Low'); +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2002, 1002, 'Electrical Systems', 'Switchgear and underground utility components', 'Utility-grade electrical equipment with public works submittals, delivery traceability, and site coordination documentation.', 'UL Listed Components; OSHA Safety Program', 'Ten weeks', 'Medium', '$900K - $1.3M', 'Medium'); +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2003, 1003, 'Seismic Steel Bracing', 'Buckling-restrained braces, embeds, and retrofit connection plates', 'Public works seismic retrofit package requiring documented AISC fabrication, DBE participation, certified welding procedures, unresolved NCR count of zero, and verified delivery access for night work.', 'AISC Certification; AWS Certified Welders; DBE Participation', 'Four weeks', 'Critical', '$1.8M - $2.2M', 'High'); +INSERT INTO CE_PROJECT_REQUIREMENTS VALUES (2004, 1004, 'Mechanical Systems', 'Cleanroom HVAC units, ductwork, controls, and startup support', 'Laboratory HVAC package requiring cleanroom-compatible ductwork, seismic anchorage calculations, TAB plan, manufacturer startup support, and submittal-ready technical documentation.', 'OSHPD/Seismic Anchorage Documentation; Factory Startup Authorization', 'Eight weeks', 'Medium', '$1.1M - $1.6M', 'Medium'); + +INSERT INTO CE_SUPPLIERS VALUES (3001, 'Atlas Structural Fabrication', 'Structural Steel', 'Northern California', 'estimating@atlasstructural.example', '408-555-0140', 'Y', 'Constrained', 'Certified structural steel fabricator with mid-rise commercial experience, shop drawing support, weld procedure documentation, and strong regional delivery history.'); +INSERT INTO CE_SUPPLIERS VALUES (3002, 'WestBridge Steel Supply', 'Structural Steel', 'Bay Area', 'bids@westbridgesteel.example', '510-555-0188', 'Y', 'Available', 'Regional steel supplier with competitive cost history and broad material availability; updated inspection package is still pending.'); +INSERT INTO CE_SUPPLIERS VALUES (3003, 'Northline Industrial Metals', 'Structural Steel', 'Central California', 'rfq@northlinemetals.example', '559-555-0199', 'Y', 'Available', 'Industrial metals supplier with strong fabrication capabilities and prior commercial work, but recent schedule confirmations are required due to historical delivery delays.'); +INSERT INTO CE_SUPPLIERS VALUES (3004, 'Coastal Retrofit Metals', 'Seismic Steel', 'Southern California', 'bids@coastalretrofit.example', '562-555-0111', 'Y', 'Overloaded', 'Retrofit steel supplier with partial seismic brace experience but missing DBE documentation and open nonconformance items.'); +INSERT INTO CE_SUPPLIERS VALUES (3005, 'Pacific Brace Works', 'Seismic Steel', 'California', 'estimating@pacificbrace.example', '714-555-0122', 'Y', 'Available', 'Specialty bracing supplier with competitive pricing but expired AISC certification and limited public works documentation.'); +INSERT INTO CE_SUPPLIERS VALUES (3006, 'Civic Steel Partners', 'Seismic Steel', 'Western US', 'rfp@civicsteel.example', '916-555-0177', 'Y', 'Available', 'Regional steel supplier with public-sector references but unresolved weld NCRs and no verified night-work delivery plan.'); +INSERT INTO CE_SUPPLIERS VALUES (3007, 'Precision Air Systems', 'Mechanical Systems', 'Northern California', 'labprojects@precisionair.example', '650-555-0133', 'Y', 'Available', 'Mechanical systems supplier with cleanroom HVAC experience, seismic anchorage partners, and factory startup authorization after updated technical package is received.'); +INSERT INTO CE_SUPPLIERS VALUES (3008, 'Valley Mechanical Supply', 'Mechanical Systems', 'Bay Area', 'quotes@valleymechanical.example', '408-555-0166', 'Y', 'Constrained', 'Mechanical supplier with competitive cost history but missing cleanroom TAB documentation and limited startup support availability.'); + +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4001, 3001, 'AISC Certified Fabricator', 'AISC', DATE '2027-05-31', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4002, 3001, 'AWS Certified Welding Program', 'AWS', DATE '2027-03-15', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4003, 3002, 'AISC Certified Fabricator', 'AISC', DATE '2026-12-31', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4004, 3003, 'AWS Certified Welding Program', 'AWS', DATE '2027-01-20', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4005, 3004, 'DBE Participation Letter', 'Agency Self-Report', DATE '2026-08-01', 'Missing'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4006, 3005, 'AISC Certified Fabricator', 'AISC', DATE '2025-12-31', 'Expired'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4007, 3006, 'AWS Certified Welding Program', 'AWS', DATE '2027-02-28', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4008, 3007, 'Factory Startup Authorization', 'HVAC Manufacturer', DATE '2027-06-30', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4009, 3007, 'Seismic Anchorage Partner Letter', 'Structural Engineer', DATE '2027-04-30', 'Current'); +INSERT INTO CE_SUPPLIER_CERTIFICATIONS VALUES (4010, 3008, 'Cleanroom TAB Documentation', 'Independent TAB Agency', DATE '2026-09-01', 'Missing'); + +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5001, 3001, 'Mid-rise commercial', 3, 94.00, 2.10, 0, 96.00, DATE '2026-05-20'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5002, 3002, 'Commercial steel framing', 2, 89.00, -1.80, 1, 91.00, DATE '2026-05-18'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5003, 3003, 'Industrial and commercial', 4, 82.00, 4.70, 2, 88.00, DATE '2026-05-12'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5004, 3004, 'Seismic retrofit', 1, 61.00, 9.40, 3, 74.00, DATE '2026-05-25'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5005, 3005, 'Public works retrofit', 1, 68.00, 6.10, 1, 79.00, DATE '2026-05-28'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5006, 3006, 'Civic infrastructure', 2, 72.00, 8.90, 2, 81.00, DATE '2026-05-29'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5007, 3007, 'Laboratory HVAC', 4, 93.00, 1.80, 0, 95.00, DATE '2026-06-02'); +INSERT INTO CE_SUPPLIER_PERFORMANCE VALUES (5008, 3008, 'Healthcare and lab mechanical', 3, 84.00, 3.90, 1, 88.00, DATE '2026-06-03'); + +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6001, 1001, 3001, 'Approved', 97.00, 'Low', 'Atlas Structural Fabrication is approved because it has completed three similar mid-rise steel frame projects, maintains current AISC and AWS documentation, has a 96 percent on-time delivery rate, has no unresolved inspection failures in the past 24 months, and has confirmed capacity for the six-week delivery window.', 'AISC certification, certified weld procedures, commercial steel framing experience, complete mill certificates, clean inspection history, confirmed delivery capacity, low supplier risk.', 'No blocking information is missing. Proceed with supplier confirmation and purchase package preparation.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6002, 1001, 3002, 'Request Info', 86.00, 'Medium', 'WestBridge Steel Supply has competitive cost history and good regional availability, but the evaluation is incomplete because current inspection documentation has not been provided.', 'Competitive cost performance, regional availability, current AISC certification.', 'Updated inspection logs, mill certificates, and nonconformance closeout evidence.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6003, 1001, 3003, 'Request Info', 78.00, 'High', 'Northline Industrial Metals has fabrication capability and similar project experience, but prior delivery delays and unresolved nonconformance count require schedule and quality confirmation before selection.', 'Strong fabrication capabilities and similar project references.', 'Delivery schedule confirmation, corrective action evidence, and updated inspection records.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6004, 1003, 3004, 'Denied', 38.00, 'High', 'Coastal Retrofit Metals should be denied because DBE participation documentation is missing, capacity is overloaded, and three unresolved nonconformance reports conflict with the public works retrofit requirements.', 'Some seismic retrofit experience.', 'DBE letter, NCR closeout evidence, and capacity plan are missing. Submit an RFP for new qualified seismic steel suppliers.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6005, 1003, 3005, 'Denied', 34.00, 'High', 'Pacific Brace Works should be denied because AISC certification is expired and public works documentation is incomplete for the required seismic retrofit scope.', 'Competitive pricing.', 'Current AISC certification and public works documentation are missing. Submit an RFP for new qualified seismic steel suppliers.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6006, 1003, 3006, 'Denied', 31.00, 'Very High', 'Civic Steel Partners should be denied because unresolved weld nonconformance reports and no verified night-work logistics plan create unacceptable schedule and quality risk.', 'Public-sector references.', 'NCR closeout evidence and night-work delivery plan are missing. Submit an RFP for new qualified seismic steel suppliers.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6007, 1004, 3007, 'Request Info', 82.00, 'Medium', 'Precision Air Systems is the leading candidate for the lab expansion, but the evaluation is pending the updated technical addendum with cleanroom TAB plan, seismic anchorage package, and factory startup letter. Re-analyze after PDF upload.', 'Laboratory HVAC experience, clean startup support, current factory authorization.', 'Upload technical addendum with TAB plan, seismic anchorage package, startup letter, and updated delivery confirmation.', SYSDATE); +INSERT INTO CE_SUPPLIER_RECOMMENDATION VALUES (6008, 1004, 3008, 'Request Info', 68.00, 'Medium', 'Valley Mechanical Supply has cost advantages but lacks cleanroom TAB documentation and has constrained startup support availability.', 'Competitive cost history and regional availability.', 'Cleanroom TAB documentation and startup support confirmation are missing.', SYSDATE); + +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7001, 1001, 6001, SYSDATE, 'Pending Review', NULL, NULL); +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7002, 1002, NULL, SYSDATE, 'In Progress', NULL, NULL); +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7003, 1003, 6004, SYSDATE, 'Pending Review', NULL, NULL); +INSERT INTO CE_SUPPLIER_EVALUATION VALUES (7004, 1004, 6007, SYSDATE, 'Pending Review', NULL, NULL); + +INSERT INTO CE_SUPPORTING_DOCS VALUES (8001, 1001, 3001, 'Inspection Log', 'atlas_inspection_log_2026.pdf', 'Inspection log shows no unresolved weld inspection failures for comparable mid-rise commercial projects in the last 24 months.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8002, 1001, 3001, 'Material Certificate', 'atlas_mill_certificates.pdf', 'Mill certificate package covers wide flange beams, columns, and connection assemblies required for the Downtown Mixed-Use Tower.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8003, 1001, 3002, 'Qualification File', 'westbridge_supplier_qualification.pdf', 'Supplier qualification file confirms AISC certification and regional availability but omits the most recent inspection log.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8004, 1003, 3004, 'Supplier Qualification', 'coastal_retrofit_qualification.pdf', 'Supplier package has missing DBE participation letter, overloaded shop capacity, and unresolved NCR history. Existing suppliers should be denied and new RFP should be submitted.', SYSDATE); +INSERT INTO CE_SUPPORTING_DOCS VALUES (8005, 1004, 3007, 'Pending Technical Addendum', 'Construction_Supplier_Evaluation.pdf', 'Upload PDF contains the lab HVAC technical addendum needed for AI re-analysis, including TAB plan, seismic anchorage package, startup letter, and updated delivery confirmation.', SYSDATE); +INSERT INTO CE_DECISION VALUES (9001, 7001, 'Approve Recommended', 'Atlas Structural Fabrication has complete certification, inspection, capacity, and delivery evidence. Recommended path is to approve and confirm the supplier.', SYSDATE); +INSERT INTO CE_DECISION VALUES (9002, 7003, 'RFP Recommended', 'Current seismic steel suppliers do not meet DBE, AISC, nonconformance, and logistics requirements. Deny current suppliers and submit a new RFP.', SYSDATE); +INSERT INTO CE_DECISION VALUES (9003, 7004, 'Request Info', 'Upload the lab HVAC technical addendum and re-run AI analysis before confirming supplier selection.', SYSDATE); + +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10001, 1001, 3001, 'Project Requirement', 'Downtown Mixed-Use Tower requires structural steel framing, fabricated beams and columns, connection assemblies, AISC certification, AWS certified welders, mill certificates, shop drawings, inspection records, and delivery within six weeks. Required evidence is complete.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10002, 1001, 3001, 'Supplier Profile', 'Atlas Structural Fabrication has completed three similar mid-rise steel frame projects, maintains current AISC certification, has certified weld procedure documentation, confirmed delivery capacity, no unresolved inspection failures, and low supplier risk.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10003, 1001, 3002, 'Supplier Profile', 'WestBridge Steel Supply has competitive cost history and good regional availability, but updated inspection documentation and nonconformance closeout records are missing.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10004, 1003, 3004, 'RFP Trigger', 'Harbor Seismic Retrofit has no acceptable supplier in the current pool. Coastal Retrofit Metals lacks DBE documentation, Pacific Brace Works has expired AISC certification, and Civic Steel Partners has unresolved weld NCRs. Deny suppliers and submit an RFP.'); +INSERT INTO CE_PROJECT_CHUNKS (CHUNK_ID, PROJECT_ID, SUPPLIER_ID, SOURCE_TYPE, CHUNK_TEXT) VALUES (10005, 1004, 3007, 'PDF Upload Scenario', 'North Campus Lab Expansion is awaiting a technical addendum PDF. Upload should add cleanroom TAB plan, seismic anchorage package, factory startup authorization, and updated delivery confirmation for AI re-analysis.'); +INSERT INTO CE_SUPPLIER_DEPENDENCIES VALUES (11001, 3001, 3002, 'Shared coating subcontractor', 'Both suppliers may use the same coating subcontractor, which could create schedule pressure if both are selected for concurrent projects.'); +INSERT INTO CE_SUPPLIER_DEPENDENCIES VALUES (11002, 3004, 3006, 'Shared inspection consultant', 'Both seismic retrofit suppliers rely on the same inspection consultant, creating a hidden review bottleneck for public works closeout.'); + +CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW construction_projects_dv AS +SELECT JSON { + '_id': p.PROJECT_ID, + 'projectName': p.PROJECT_NAME, + 'location': p.LOCATION, + 'projectType': p.PROJECT_TYPE, + 'projectPhase': p.PROJECT_PHASE, + 'projectSummary': p.PROJECT_SUMMARY, + 'startDate': p.START_DATE, + 'targetDeliveryDate': p.TARGET_DELIVERY_DATE, + 'evaluationStatus': p.EVALUATION_STATUS, + 'createdBy': p.CREATED_BY, + 'requirements': [ + SELECT JSON { + 'requirementId': r.REQUIREMENT_ID, + 'tradeCategory': r.TRADE_CATEGORY, + 'materialNeed': r.MATERIAL_NEED, + 'technicalSpec': r.TECHNICAL_SPEC, + 'requiredCertification': r.REQUIRED_CERTIFICATION, + 'deliveryWindow': r.DELIVERY_WINDOW, + 'procurementUrgency': r.PROCUREMENT_URGENCY, + 'budgetRange': r.BUDGET_RANGE, + 'riskLevel': r.RISK_LEVEL + } + FROM CE_PROJECT_REQUIREMENTS r WITH INSERT UPDATE DELETE + WHERE r.PROJECT_ID = p.PROJECT_ID + ], + 'supplierEvaluations': [ + SELECT JSON { + 'evaluationId': e.EVALUATION_ID, + 'requestDate': e.REQUEST_DATE, + 'evaluationStatus': e.EVALUATION_STATUS, + 'finalDecision': e.FINAL_DECISION, + 'decisionDate': e.DECISION_DATE, + 'recommendation': ( + SELECT JSON { + 'recommendId': rec.RECOMMEND_ID, + 'recommendation': rec.RECOMMENDATION, + 'fitScore': rec.FIT_SCORE, + 'riskLevel': rec.RISK_LEVEL, + 'explanation': rec.EXPLANATION, + 'strengths': rec.STRENGTHS, + 'missingInformation': rec.MISSING_INFORMATION, + 'generatedDate': rec.GENERATED_DATE, + 'supplier': ( + SELECT JSON { + 'supplierId': s.SUPPLIER_ID, + 'supplierName': s.SUPPLIER_NAME, + 'category': s.CATEGORY, + 'region': s.REGION, + 'email': s.EMAIL, + 'phone': s.PHONE_NUMBER, + 'active': s.ACTIVE, + 'capacityStatus': s.CAPACITY_STATUS, + 'capabilitySummary': s.CAPABILITY_SUMMARY + } + FROM CE_SUPPLIERS s + WHERE s.SUPPLIER_ID = rec.SUPPLIER_ID + ) + } + FROM CE_SUPPLIER_RECOMMENDATION rec WITH UPDATE + WHERE rec.RECOMMEND_ID = e.RECOMMEND_ID + ) + } + FROM CE_SUPPLIER_EVALUATION e WITH INSERT UPDATE DELETE + WHERE e.PROJECT_ID = p.PROJECT_ID + ] +} +FROM CE_PROJECTS p +WITH INSERT UPDATE DELETE; + +CREATE OR REPLACE PROPERTY GRAPH CONSTRUCTION_ENGINEERING_GRAPH + VERTEX TABLES ( + "CE_PROJECTS" KEY ("PROJECT_ID") PROPERTIES ("PROJECT_NAME", "LOCATION", "PROJECT_TYPE", "PROJECT_PHASE", "EVALUATION_STATUS"), + "CE_PROJECT_REQUIREMENTS" KEY ("REQUIREMENT_ID") PROPERTIES ("PROJECT_ID", "TRADE_CATEGORY", "MATERIAL_NEED", "REQUIRED_CERTIFICATION", "PROCUREMENT_URGENCY", "RISK_LEVEL"), + "CE_SUPPLIERS" KEY ("SUPPLIER_ID") PROPERTIES ("SUPPLIER_NAME", "CATEGORY", "REGION", "ACTIVE", "CAPACITY_STATUS"), + "CE_SUPPLIER_RECOMMENDATION" KEY ("RECOMMEND_ID") PROPERTIES ("PROJECT_ID", "SUPPLIER_ID", "RECOMMENDATION", "FIT_SCORE", "RISK_LEVEL"), + "CE_SUPPLIER_EVALUATION" KEY ("EVALUATION_ID") PROPERTIES ("PROJECT_ID", "RECOMMEND_ID", "EVALUATION_STATUS", "FINAL_DECISION"), + "CE_SUPPLIER_DEPENDENCIES" KEY ("DEPENDENCY_ID") PROPERTIES ("SUPPLIER_ID", "RELATED_SUPPLIER_ID", "DEPENDENCY_TYPE", "RISK_NOTE") + ) + EDGE TABLES ( + "CE_PROJECT_REQUIREMENTS" AS project_has_requirement + SOURCE KEY ("PROJECT_ID") REFERENCES "CE_PROJECTS"("PROJECT_ID") + DESTINATION KEY ("REQUIREMENT_ID") REFERENCES "CE_PROJECT_REQUIREMENTS"("REQUIREMENT_ID") + PROPERTIES ("TRADE_CATEGORY", "PROCUREMENT_URGENCY", "RISK_LEVEL"), + "CE_SUPPLIER_RECOMMENDATION" AS project_recommends_supplier + SOURCE KEY ("PROJECT_ID") REFERENCES "CE_PROJECTS"("PROJECT_ID") + DESTINATION KEY ("SUPPLIER_ID") REFERENCES "CE_SUPPLIERS"("SUPPLIER_ID") + PROPERTIES ("RECOMMEND_ID", "RECOMMENDATION", "FIT_SCORE", "RISK_LEVEL"), + "CE_SUPPLIER_EVALUATION" AS evaluation_for_project + SOURCE KEY ("PROJECT_ID") REFERENCES "CE_PROJECTS"("PROJECT_ID") + DESTINATION KEY ("EVALUATION_ID") REFERENCES "CE_SUPPLIER_EVALUATION"("EVALUATION_ID") + PROPERTIES ("EVALUATION_STATUS", "FINAL_DECISION"), + "CE_SUPPLIER_DEPENDENCIES" AS supplier_dependency + SOURCE KEY ("SUPPLIER_ID") REFERENCES "CE_SUPPLIERS"("SUPPLIER_ID") + DESTINATION KEY ("RELATED_SUPPLIER_ID") REFERENCES "CE_SUPPLIERS"("SUPPLIER_ID") + PROPERTIES ("DEPENDENCY_TYPE", "RISK_NOTE") + ); + +COMMIT;