-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsemantic-site.sql
More file actions
193 lines (176 loc) · 7.03 KB
/
Copy pathsemantic-site.sql
File metadata and controls
193 lines (176 loc) · 7.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/**********************************************************************************************
** Table authority.site_embeddings
** Note Embeddings side table for Site in schema authority
** Used for semantic search with pgvector
** Generated from template by generate_entity_schema.py
**********************************************************************************************/
drop table if exists authority.site_embeddings cascade;
create table if not exists authority.site_embeddings (
site_id integer primary key references public.tbl_sites(site_id) on delete cascade,
emb vector(768)
);
-- Vector index for fast ANN search (cosine). Tune lists to your row count.
create index if not exists site_embeddings_ivfflat
on authority.site_embeddings
using ivfflat (emb vector_cosine_ops)
with (lists = 100);
/***************************************************************************************************
** Procedure authority.update_site_embeddings
** What Updates embeddings in authority.site_embeddings table
** Usage SELECT authority.update_site_embeddings(); -- Update only missing
** SELECT authority.update_site_embeddings(true); -- Force update all
** Arguments p_force_update: If true, regenerate all embeddings; if false (default), only compute missing ones
** Returns Number of rows updated
****************************************************************************************************/
drop function if exists authority.update_site_embeddings(boolean) cascade;
create or replace function authority.update_site_embeddings(
p_force_update boolean default false
) returns integer
language plpgsql volatile
as $$
declare
rec record;
v_emb vector(768);
v_text text;
v_rows_updated integer := 0;
begin
raise notice 'Updating site embeddings (force_update: %)', p_force_update;
for rec in
select t.site_id,
t.site_name,
t.site_description from public.tbl_sites t
where p_force_update
or not exists (
select 1 from authority.site_embeddings e
where e.site_id = t.site_id
)
loop
-- Construct text for embedding (combine label and description if available)
v_text := rec.site_name; if rec.site_description is not null then
v_text := v_text || ' ' || rec.site_description;
end if;
-- Compute embedding (assumes authority.compute_text_embedding exists)
v_emb := authority.compute_text_embedding(v_text);
-- Upsert into embeddings table
insert into authority.site_embeddings (site_id, emb)
values (rec.site_id, v_emb)
on conflict (site_id) do update
set emb = excluded.emb;
v_rows_updated := v_rows_updated + 1;
-- Progress reporting every 100 rows
if v_rows_updated % 100 = 0 then
raise notice ' → Processed % rows', v_rows_updated;
end if;
end loop;
raise notice 'Completed: % rows updated for site', v_rows_updated;
return v_rows_updated;
end;
$$;
/**********************************************************************************************
** Site - Semantic Search Objects (Vector Embeddings)
** Generated from template by generate_entity_schema.py
**
** Note: This file does NOT modify authority.site view.
** It creates a separate embeddings table that can be joined with the view when needed.
** Semantic search functions perform the join internally.
**********************************************************************************************/
/***************************************************************************************************
** Procedure authority.semantic_site
** What Semantic search function using pgvector embeddings
** Usage SELECT * FROM authority.semantic_site(qemb::vector, 10);
** Note Joins authority.site view with authority.site_embeddings table
****************************************************************************************************/
drop function if exists authority.semantic_site(vector, integer) cascade;
create or replace function authority.semantic_site(
qemb vector,
p_limit integer default 10
) returns table (
site_id integer,
label text,
sem_sim double precision
) language sql stable
as $$
select
v.site_id,
v.label,
1.0 - (e.emb <=> qemb) as sem_sim
from authority.site as v
inner join authority.site_embeddings as e using (site_id)
where e.emb is not null
order by e.emb <=> qemb
limit p_limit;
$$;
/***************************************************************************************************
** Procedure authority.search_site_hybrid
** What Hybrid search combining trigram and semantic search
** Notes See docs/MCP Server/SEAD Reconciliation via MCP — Architecture Doc (Outline).md
** Arguments
** p_text: raw query text
** qemb: query embedding (same dim as stored vectors)
** k_trgm: number of trigram results to return (default 30)
** k_sem: number of semantic results to return (default 30)
** k_final: number of final results to return (default 20)
** alpha: blending factor for trigram vs semantic (default 0.5) ****************************************************************************************************/
drop function if exists authority.search_site_hybrid(text, vector, integer, integer, integer, double precision) cascade;
create or replace function authority.search_site_hybrid(
p_text text,
qemb vector,
k_trgm integer default 30,
k_sem integer default 30,
k_final integer default 20,
alpha double precision default 0.5) returns table (
site_id integer,
label text,
trgm_sim double precision,
sem_sim double precision,
blend double precision
) language sql stable
as $$
with params as (
select authority.immutable_unaccent(lower(p_text))::text as q
) , trgm as (
select
e.site_id,
e.label,
greatest(
case when e.norm_label = pq.q then 1.0
else similarity(e.norm_label, pq.q)
end, 0.0001
) as trgm_sim
from authority.site as e
cross join params pq where e.norm_label % pq.q order by trgm_sim desc, e.label
limit k_trgm
)
, sem as (
select
v.site_id,
v.label,
(1.0 - (emb.emb <=> qemb))::double precision as sem_sim
from authority.site as v
inner join authority.site_embeddings as emb using (site_id) where emb.emb is not null order by emb.emb <=> qemb
limit k_sem
)
, u as (
select site_id, label, trgm_sim, null::double precision as sem_sim from trgm
union
select site_id, label, null::double precision as trgm_sim, sem_sim from sem
)
, agg as (
select
site_id,
max(label) as label,
max(trgm_sim) as trgm_sim,
max(sem_sim) as sem_sim
from u
group by site_id
)
select
site_id,
label,
coalesce(trgm_sim, 0.0) as trgm_sim,
coalesce(sem_sim, 0.0) as sem_sim,
(alpha * coalesce(trgm_sim, 0.0) + (1.0 - alpha) * coalesce(sem_sim, 0.0)) as blend
from agg
order by blend desc, label
limit k_final;
$$;