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;