diff --git a/src/llmUtil.jl b/src/llmUtil.jl index f2c603b..888f7ae 100644 --- a/src/llmUtil.jl +++ b/src/llmUtil.jl @@ -767,6 +767,54 @@ julia> conn = "host=localhost port=5432 dbname=winedb user=admin password=secret julia> fruits = GeneralUtils.harvest_entity_catalog(conn, "products", "fruit_name") ["Apple", "Banana", "Orange", "Mango"] ``` + +# Integration Guide: Finding Closest Entity Match in Database +When users type queries, they often make typos or use abbreviations. This function finds +the closest matching entity from a database column, handling common input errors. + +**Example:** +```julia +# Database contains: ["Hand Old Bar & Grill", "Hand Old", "Wine Cellar"] +# User types: "HandOld" (compressed words, missing space) + +catalog = GeneralUtils.harvest_entity_catalog(pg_conn_str, "venues", "name") +closest = GeneralUtils.resolve_entity("HandOld", catalog; threshold=0.9) +# Returns: "Hand Old Bar & Grill" (closest match) +``` + +**Step 1: Extract all valid values from a column** +```julia +# Get all wine names from the database +wine_names = GeneralUtils.harvest_entity_catalog(pg_conn_str, "wine", "wine_name") +# Returns: ["Château Margaux", "Château Lafite", "Domaine Leroy", ...] +``` + +**Step 2: Find closest match for user input** +```julia +# User types a wine name with a typo +catalog = GeneralUtils.harvest_entity_catalog(pg_conn_str, "wine", "wine_name") +closest_wine = GeneralUtils.resolve_entity("Chateu Margaux", catalog; threshold=0.9) +# Returns: "Château Margaux" (closest match) +``` + +**Step 3: Resolve all fields in a response** +```julia +# Agent produces a response with potentially misspelled values +responsedict = Dict("wine_name" => "Chateu Margaux", "region" => "Bord") + +# For each field, find the closest match in the database +for (k, v) in responsedict + catalog = GeneralUtils.harvest_entity_catalog(pg_conn_str, "wine", k) + resolved = GeneralUtils.resolve_entity(v, catalog; threshold=0.9) + responsedict[k] = resolved # Replace messy input with database entity +end +``` + +**Threshold guidance:** +- `threshold=0.5` - Lenient, may return false positives +- `threshold=0.7` - Moderate balance +- `threshold=0.9` - Strict, only high-confidence matches +- Returns `""` when no match meets threshold """ function harvest_entity_catalog(pg_conn_str::String, table::String, column::String)::Vector{String} conn = LibPQ.Connection(pg_conn_str) @@ -832,6 +880,54 @@ julia> GeneralUtils.resolve_entity("Wine Cellar", catalog; threshold=0.5) julia> GeneralUtils.resolve_entity("Unknown Place", catalog; threshold=0.5) "" ``` + +# Integration Guide: Finding Closest Entity Match in Database +When users type queries, they often make typos or use abbreviations. This function finds +the closest matching entity from a database column, handling common input errors. + +**Example:** +```julia +# Database contains: ["Hand Old Bar & Grill", "Hand Old", "Wine Cellar"] +# User types: "HandOld" (compressed words, missing space) + +catalog = GeneralUtils.harvest_entity_catalog(pg_conn_str, "venues", "name") +closest = GeneralUtils.resolve_entity("HandOld", catalog; threshold=0.9) +# Returns: "Hand Old Bar & Grill" (closest match) +``` + +**Step 1: Extract all valid values from a column** +```julia +# Get all wine names from the database +wine_names = GeneralUtils.harvest_entity_catalog(pg_conn_str, "wine", "wine_name") +# Returns: ["Château Margaux", "Château Lafite", "Domaine Leroy", ...] +``` + +**Step 2: Find closest match for user input** +```julia +# User types a wine name with a typo +catalog = GeneralUtils.harvest_entity_catalog(pg_conn_str, "wine", "wine_name") +closest_wine = GeneralUtils.resolve_entity("Chateu Margaux", catalog; threshold=0.9) +# Returns: "Château Margaux" (closest match) +``` + +**Step 3: Resolve all fields in a response** +```julia +# Agent produces a response with potentially misspelled values +responsedict = Dict("wine_name" => "Chateu Margaux", "region" => "Bord") + +# For each field, find the closest match in the database +for (k, v) in responsedict + catalog = GeneralUtils.harvest_entity_catalog(pg_conn_str, "wine", k) + resolved = GeneralUtils.resolve_entity(v, catalog; threshold=0.9) + responsedict[k] = resolved # Replace messy input with database entity +end +``` + +**Threshold guidance:** +- `threshold=0.5` - Lenient, may return false positives +- `threshold=0.7` - Moderate balance +- `threshold=0.9` - Strict, only high-confidence matches +- Returns `""` when no match meets threshold """ function resolve_entity(messy_input::String, catalog::Vector{String}; threshold=0.5)::String best_match = ""