provider.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. /**
  2. * provider.ts - Embedding provider abstraction
  3. *
  4. * Production embeddings use a commercial OpenAI-compatible API. Historical
  5. * local configuration is parsed only by the factory so it can fail closed.
  6. *
  7. * The factory in `./factory.ts` selects an implementation based on env vars,
  8. * a CLI flag, or `~/.config/qmd/config.json`.
  9. */
  10. /**
  11. * Error thrown when the provider's reported model id does not match the
  12. * model id baked into existing `content_vectors` rows. Forces user to
  13. * re-embed (`qmd embed -f`) or pin the matching model id.
  14. */
  15. export class ModelMismatchError extends Error {
  16. providerModel;
  17. existingModels;
  18. constructor(providerModel, existingModels) {
  19. const list = existingModels.join(", ");
  20. super(`Embedding model mismatch: existing vectors use model(s) [${list}] ` +
  21. `but the configured provider reports "${providerModel}". ` +
  22. `Run \`qmd embed -f\` (or \`--rebuild\`) to re-embed everything with ` +
  23. `the new model, or set QMD_EMBED_MODEL_ID="${existingModels[0] ?? ""}" ` +
  24. `to keep the existing vectors.`);
  25. this.name = "ModelMismatchError";
  26. this.providerModel = providerModel;
  27. this.existingModels = existingModels;
  28. }
  29. }
  30. /**
  31. * Verify that the provider's model id is compatible with the existing
  32. * `content_vectors` entries. Pass-through (no-op) if the table is empty
  33. * (fresh DB) or if the model id appears in the distinct set.
  34. *
  35. * Caller passes `existingModels` (typically result of
  36. * `SELECT DISTINCT model FROM content_vectors`).
  37. */
  38. export function assertModelCompatible(providerModel, existingModels) {
  39. // Empty DB — nothing to compare against, anything goes.
  40. if (existingModels.length === 0)
  41. return;
  42. if (existingModels.includes(providerModel))
  43. return;
  44. throw new ModelMismatchError(providerModel, existingModels);
  45. }