-
Notifications
You must be signed in to change notification settings - Fork 82
Expand file tree
/
Copy pathsemanticSearchPostgresDocs.ts
More file actions
100 lines (93 loc) · 2.61 KB
/
semanticSearchPostgresDocs.ts
File metadata and controls
100 lines (93 loc) · 2.61 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
import { z } from 'zod';
import { openai } from '@ai-sdk/openai';
import { embed } from 'ai';
import { ApiFactory } from '../shared/boilerplate/src/types.js';
import { ServerContext } from '../types.js';
const inputSchema = {
version: z.coerce
.number()
.int()
.nullable()
.describe('The PostgreSQL version to use for the query. Defaults to 17.'),
limit: z.coerce
.number()
.min(1)
.nullable()
.describe('The maximum number of matches to return. Defaults to 10.'),
prompt: z
.string()
.min(1)
.describe(
'The natural language query used to search the PostgreSQL documentation for relevant information.',
),
} as const;
const zEmbeddedDoc = z.object({
id: z
.number()
.int()
.describe('The unique identifier of the documentation entry.'),
headerPath: z
.array(z.string())
.describe('The path to the header of the documentation entry.'),
sourceUrl: z
.string()
.nullable()
.describe('The URL of the documentation entry.'),
content: z.string().describe('The content of the documentation entry.'),
tokenCount: z
.number()
.int()
.describe('The number of tokens in the documentation entry.'),
distance: z
.number()
.describe(
'The distance score indicating the relevance of the entry to the prompt. Lower values indicate higher relevance.',
),
});
type EmbeddedDoc = z.infer<typeof zEmbeddedDoc>;
const outputSchema = {
results: z.array(zEmbeddedDoc),
} as const;
export const semanticSearchPostgresDocsFactory: ApiFactory<
ServerContext,
typeof inputSchema,
typeof outputSchema,
z.infer<(typeof outputSchema)['results']>
> = ({ pgPool }) => ({
name: 'semanticSearchPostgresDocs',
method: 'get',
route: '/semantic-search/postgres-docs',
config: {
title: 'Semantic Search of PostgreSQL Documentation Embeddings',
description:
'This retrieves relevant PostgreSQL documentation entries based on a natural language query.',
inputSchema,
outputSchema,
},
fn: async ({ prompt, version, limit }) => {
const { embedding } = await embed({
model: openai.embedding('text-embedding-3-small'),
value: prompt,
});
const result = await pgPool.query<EmbeddedDoc>(
/* sql */ `
SELECT
id::int,
header_path AS "headerPath",
source_url AS "sourceUrl",
content,
token_count::int AS "tokenCount",
embedding <=> $1::vector(1536) AS distance
FROM docs.postgres
WHERE version = $2
ORDER BY distance
LIMIT $3
`,
[JSON.stringify(embedding), version || 17, limit || 10],
);
return {
results: result.rows,
};
},
pickResult: (r) => r.results,
});