yawnxyz-buildclubprojectsearch.web.val.run
June 6, 2024
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
/** @jsx jsx **/
import { renderToString } from "npm:react-dom/server";
import { jsx } from "https://deno.land/x/hono@v3.11.7/middleware.ts";
import { Hono } from "https://deno.land/x/hono@v3.11.7/mod.ts";
import { semanticSearch } from "https://esm.town/v/yawnxyz/semanticSearch";
import Airtable from "npm:airtable";
const app = new Hono();
const Layout = ({ children, title = "Build Club Projects" }) => (
<html lang="en">
<head>
<title>{title}</title>
<script src="https://unpkg.com/htmx.org@1.9.9"></script>
</head>
<body>
{children}
</body>
</html>
);
const SearchBar = () => (
<form hx-get="/search" hx-target="#searchResults">
<input type="text" name="query" placeholder="Search..." />
<button type="submit">Search</button>
</form>
);
const SearchResults = ({ results }) => (
<div id="searchResults">
<table>
<thead>
<tr>
<th>Name</th>
<th>Content</th>
<th>embeddingsContent</th>
</tr>
</thead>
<tbody>
{results.map((result) => (
<tr key={result.id}>
<td>{result.name}</td>
<td>{result.content}</td>
<td>{result.embeddingsContent}</td>
</tr>
))}
</tbody>
</table>
</div>
);
const Home = () => (
<main>
<h1>Build Club Project Search</h1>
<SearchBar />
<SearchResults results={[]} />
</main>
);
const airtableApiKey = Deno.env.get("AIRTABLE_API_KEY");
const defaultBaseId = "app1wLB4irV14mxMU";
const defaultTableName = "ExampleItems";
const defaultNameColumn = "Name";
const defaultContentColumn = "Content";
const defaultEmbeddingColumn = "Embeddings";
async function fetchAirtableData(baseId, tableName, nameColumn, contentColumn, embeddingColumn) {
const base = new Airtable({ apiKey: airtableApiKey }).base(baseId);
const records = await base(tableName).select().all();
const documents = records.map(record => ({
id: record.id,
name: record.get(nameColumn),
content: record.get(contentColumn),
embedding: record.get(embeddingColumn).split(",").map(parseFloat),
embeddingsContent: record.get('EmbeddingsContent'),
}));
return documents;
}
async function searchDocuments(c, query, similarityThreshold) {
const baseId = c.req.query("base_id") || defaultBaseId;
const tableName = c.req.query("table_name") || defaultTableName;
const nameColumn = c.req.query("name_column") || defaultNameColumn;
const contentColumn = c.req.query("content_column") || defaultContentColumn;
const embeddingColumn = c.req.query("embedding_column") || defaultEmbeddingColumn;
try {
const documents = await fetchAirtableData(baseId, tableName, nameColumn, contentColumn, embeddingColumn);
console.log('documents:', documents)
await semanticSearch.addDocuments({documents, fields: 'embeddingsContent'});
const results = await semanticSearch.search({query, similarityThreshold});
if (c.req.headers.get("HX-Request")) {
return c.html(<SearchResults results={results} />);
} else {
return c.json(results);
}
} catch (error) {
console.error("Search error:", error);
throw error;
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
June 6, 2024