A social RSS reader built on the AT Protocol. glean.at
glean atproto atmosphere rss feed social app
14
fork

Configure Feed

Select the types of activity you want to include in your feed.

Handle vector table schema mismatches (happens when changing embedding model)

+34 -10
+5 -5
.env.example
··· 11 11 # Leave empty for localhost OAuth (development) 12 12 # GLEAN_OAUTH_CLIENT_ID=https://glean.at/oauth/client-metadata 13 13 # GLEAN_OAUTH_REDIRECT_URL=https://glean.at/auth/callback 14 - # Embeddings (recommended — powers content-based feed/article recommendations) 14 + # Embeddings (recommended as it powers content-based feed/article recommendations) 15 15 # Point to any OpenAI-compatible /v1/embeddings endpoint (OpenAI, Ollama, etc.) 16 16 # Without embeddings, recommendations rely only on subscription overlap and social graph. 17 - GLEAN_EMBED_BASE_URL=https://api.openai.com/v1 18 - GLEAN_EMBED_API_KEY=sk-... 19 - GLEAN_EMBED_MODEL=text-embedding-3-small 20 - GLEAN_EMBED_DIMENSION=1536 17 + GLEAN_EMBED_BASE_URL=https://llms.example.com/v1 18 + GLEAN_EMBED_API_KEY=API-KEY-001 19 + GLEAN_EMBED_MODEL=qwen-embedding-4b 20 + GLEAN_EMBED_DIMENSION=2560
+29 -5
internal/db/db.go
··· 131 131 if dimension <= 0 { 132 132 return nil 133 133 } 134 - for _, stmt := range []string{ 135 - fmt.Sprintf(`CREATE VIRTUAL TABLE IF NOT EXISTS recs.feed_embeddings USING vec0(feed_url TEXT PRIMARY KEY, embedding float[%d])`, dimension), 136 - fmt.Sprintf(`CREATE VIRTUAL TABLE IF NOT EXISTS recs.article_embeddings USING vec0(article_id INTEGER PRIMARY KEY, embedding float[%d])`, dimension), 134 + 135 + for _, tbl := range []struct { 136 + name string 137 + col string 138 + create string 139 + }{ 140 + { 141 + name: "recs.feed_embeddings", 142 + col: "feed_url", 143 + create: fmt.Sprintf(`CREATE VIRTUAL TABLE recs.feed_embeddings USING vec0(feed_url TEXT PRIMARY KEY, embedding float[%d])`, dimension), 144 + }, 145 + { 146 + name: "recs.article_embeddings", 147 + col: "article_id", 148 + create: fmt.Sprintf(`CREATE VIRTUAL TABLE recs.article_embeddings USING vec0(article_id INTEGER PRIMARY KEY, embedding float[%d])`, dimension), 149 + }, 137 150 } { 138 - if _, err := s.db.ExecContext(context.Background(), stmt); err != nil { 139 - return fmt.Errorf("create vec0 table: %w", err) 151 + var schema string 152 + _ = s.db.QueryRow("SELECT sql FROM recs.sqlite_master WHERE type='table' AND name=?", strings.TrimPrefix(tbl.name, "recs.")).Scan(&schema) 153 + expected := fmt.Sprintf("float[%d]", dimension) 154 + if strings.Contains(schema, expected) { 155 + continue 156 + } 157 + 158 + if schema != "" { 159 + s.db.Exec(fmt.Sprintf("DROP TABLE %s", tbl.name)) 160 + } 161 + 162 + if _, err := s.db.ExecContext(context.Background(), tbl.create); err != nil { 163 + return fmt.Errorf("create vec0 table %s: %w", tbl.name, err) 140 164 } 141 165 } 142 166 return nil