Search
Code168
import { initializeDatabase } from './services/supabase.ts';import chatRoutes from './routes/chat.ts';import embeddingRoutes from './routes/embeddings.ts';const app = new Hono();// API Routesapp.route('/api/chat', chatRoutes);app.route('/api/embeddings', embeddingRoutes);// Health checkimport { Hono } from 'https://esm.sh/hono@3.11.7';import { generateEmbedding, generateEmbeddings } from '../services/embeddings.ts';import { searchSimilarContent } from '../services/supabase.ts';import type { EmbeddingRequest, EmbeddingResponse } from '../../shared/types.ts';const embeddings = new Hono();// Generate embedding for a single textembeddings.post('/generate', async (c) => { try { const body: EmbeddingRequest = await c.req.json();});// Generate embeddings for multiple textsembeddings.post('/batch', async (c) => { try { const body: { texts: string[] } = await c.req.json(); } const embeddings = await generateEmbeddings(texts); return c.json({ embeddings, count: embeddings.length, dimensions: embeddings[0]?.length || 0 }); console.error('Batch embedding generation error:', error); return c.json({ error: 'Failed to generate batch embeddings', details: error.message }, 500);// Search similar content using embeddingembeddings.post('/search', async (c) => { try { const body: { // Health check endpointembeddings.get('/health', (c) => { return c.json({ status: 'healthy', service: 'nelson-gpt-embeddings', timestamp: new Date().toISOString() });});export default embeddings;import { Hono } from 'https://esm.sh/hono@3.11.7';import { streamSSE } from 'https://esm.sh/hono@3.11.7/streaming';import { generateEmbedding } from '../services/embeddings.ts';import { searchSimilarContent } from '../services/supabase.ts';import { generateMistralResponse, streamMistralResponse } from '../services/mistral.ts';}export async function generateEmbeddings(texts: string[]): Promise<number[][]> { try { const embeddings = await Promise.all( texts.map(text => generateEmbedding(text)) ); return embeddings; } catch (error) { console.error('Error generating batch embeddings:', error); throw error; }}// Utility function to normalize embeddings (optional, for better similarity search)export function normalizeEmbedding(embedding: number[]): number[] { const magnitude = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));}// Calculate cosine similarity between two embeddingsexport function cosineSimilarity(a: number[], b: number[]): number { if (a.length !== b.length) { throw new Error('Embeddings must have the same length'); } - **Database**: Supabase with PGVector for vector search- **AI**: Mistral API for LLM responses- **Embeddings**: Hugging Face sentence-transformers- **Animations**: Lottie- **PWA**: Service Worker + IndexedDB│ ├── routes/│ │ ├── chat.ts # Chat API endpoints│ │ └── embeddings.ts # Embedding generation│ └── services/│ ├── supabase.ts # Supabase client│ ├── mistral.ts # Mistral API client│ └── embeddings.ts # HuggingFace embeddings├── frontend/│ ├── index.html # Main HTML template- `VITE_SUPABASE_ANON_KEY`: Supabase anonymous key- `VITE_SUPABASE_SERVICE_ROLE_KEY`: Supabase service role key- `VITE_HUGGINFACE_API_KEY`: Hugging Face API key for embeddings## Getting Startedconst app = new Hono();// Hugging Face API for embeddingsconst HF_API_URL = "https://api-inference.huggingface.co/pipeline/feature-extraction/sentence-transformers/all-MiniLM-L6-v2";}// Generate embeddings endpointapp.post("/generate", async (c) => { try { console.error("Batch embedding error:", error); return c.json({ error: "Failed to generate batch embeddings", details: error.message }, 500); return c.json({ status: "healthy", service: "embeddings", model: "sentence-transformers/all-MiniLM-L6-v2", dimensions: testEmbedding?.length || 0, return c.json({ status: "unhealthy", service: "embeddings", error: error.message }, 500); getUserConversations} from "../database/queries.ts";import { generateEmbedding } from "./embeddings.ts";const app = new Hono();}// Fallback text search when embeddings are not availableexport async function textSearchMedicalContent( query: string, await sqlite.execute(` INSERT OR REPLACE INTO ${TABLES.EMBEDDINGS_CACHE} (query_hash, query_text, embedding_vector, last_accessed, access_count) VALUES (?, ?, ?, CURRENT_TIMESTAMP, COALESCE((SELECT access_count FROM ${TABLES.EMBEDDINGS_CACHE} WHERE query_hash = ?), 0) + 1) `, [queryHash, queryText, JSON.stringify(embedding), queryHash]); } catch (error) { const results = await sqlite.execute( `SELECT embedding_vector FROM ${TABLES.EMBEDDINGS_CACHE} WHERE query_hash = ?`, [queryHash] ); // Update access count await sqlite.execute( `UPDATE ${TABLES.EMBEDDINGS_CACHE} SET access_count = access_count + 1, last_accessed = CURRENT_TIMESTAMP WHERE query_hash = ?`, CONVERSATIONS: 'nelson_conversations_v1', USER_PREFERENCES: 'nelson_user_preferences_v1', EMBEDDINGS_CACHE: 'nelson_embeddings_cache_v1'}; `); // Embeddings cache for performance await sqlite.execute(` CREATE TABLE IF NOT EXISTS ${TABLES.EMBEDDINGS_CACHE} ( query_hash TEXT PRIMARY KEY, query_text TEXT NOT NULL, await sqlite.execute(` CREATE INDEX IF NOT EXISTS idx_embeddings_cache_access ON ${TABLES.EMBEDDINGS_CACHE}(last_accessed DESC) `);import { readFile, serveFile } from "https://esm.town/v/std/utils@85-main/index.ts";import { chatRoutes } from "./routes/chat.ts";import { embeddingRoutes } from "./routes/embeddings.ts";import { runMigrations } from "./database/migrations.ts";// API Routesapp.route("/api/chat", chatRoutes);app.route("/api/embeddings", embeddingRoutes);// Health check endpointUsers
No users found
No docs found