vibe-match 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,296 @@
1
+ # vibe-match
2
+
3
+ Semantic test matchers powered by LLMs. Test your AI outputs with fuzzy matching that understands meaning, not just exact text.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -D vibe-match
9
+ ```
10
+
11
+ ```bash
12
+ bun add -D vibe-match
13
+ ```
14
+
15
+ ```bash
16
+ yarn add -D vibe-match
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { vibeMatchers, type VibeMatchConfig } from "vibe-match";
23
+
24
+ const config: VibeMatchConfig = {
25
+ apiKeys: {
26
+ openai: process.env.OPENAI_API_KEY,
27
+ },
28
+ languageModel: "openai:gpt-4o-mini",
29
+ embeddingModel: "openai:text-embedding-3-small",
30
+ };
31
+
32
+ expect.extend(vibeMatchers(config));
33
+
34
+ // Now you can use semantic matchers!
35
+ expect("Hello there!").toBeSimilarTo("Hi!");
36
+ ```
37
+
38
+ ### Provider Examples
39
+
40
+ **OpenAI:**
41
+
42
+ ```typescript
43
+ const config: VibeMatchConfig = {
44
+ apiKeys: {
45
+ openai: process.env.OPENAI_API_KEY,
46
+ },
47
+ languageModel: "openai:gpt-4o-mini",
48
+ embeddingModel: "openai:text-embedding-3-small",
49
+ };
50
+ ```
51
+
52
+ **Anthropic** (use OpenAI for embeddings since Anthropic doesn't provide them):
53
+
54
+ ```typescript
55
+ const config: VibeMatchConfig = {
56
+ apiKeys: {
57
+ anthropic: process.env.ANTHROPIC_API_KEY,
58
+ openai: process.env.OPENAI_API_KEY, // Required for embeddings
59
+ },
60
+ languageModel: "anthropic:claude-sonnet-4-20250514",
61
+ embeddingModel: "openai:text-embedding-3-small",
62
+ };
63
+ ```
64
+
65
+ **Google (Gemini):**
66
+
67
+ ```typescript
68
+ const config: VibeMatchConfig = {
69
+ apiKeys: {
70
+ google: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
71
+ },
72
+ languageModel: "google:gemini-2.0-flash",
73
+ embeddingModel: "google:text-embedding-004",
74
+ };
75
+ ```
76
+
77
+ **Mistral:**
78
+
79
+ ```typescript
80
+ const config: VibeMatchConfig = {
81
+ apiKeys: {
82
+ mistral: process.env.MISTRAL_API_KEY,
83
+ },
84
+ languageModel: "mistral:mistral-small-latest",
85
+ embeddingModel: "mistral:mistral-embed",
86
+ };
87
+ ```
88
+
89
+ **Grok (xAI)** (use OpenAI for embeddings since xAI doesn't provide them):
90
+
91
+ ```typescript
92
+ const config: VibeMatchConfig = {
93
+ apiKeys: {
94
+ xai: process.env.XAI_API_KEY,
95
+ openai: process.env.OPENAI_API_KEY, // Required for embeddings
96
+ },
97
+ languageModel: "xai:grok-2-1212",
98
+ embeddingModel: "openai:text-embedding-3-small",
99
+ };
100
+ ```
101
+
102
+ ### Custom Models
103
+
104
+ You can also pass custom AI SDK model instances directly. This is useful for:
105
+
106
+ - Using OpenAI-compatible APIs (OpenRouter, Together AI, Fireworks, etc.)
107
+ - Using providers not built into vibe-match
108
+ - Configuring models with custom options
109
+
110
+ **OpenRouter:**
111
+
112
+ ```typescript
113
+ import { createOpenAI } from "@ai-sdk/openai";
114
+
115
+ const openrouter = createOpenAI({
116
+ baseURL: "https://openrouter.ai/api/v1",
117
+ apiKey: process.env.OPENROUTER_API_KEY,
118
+ });
119
+
120
+ const config: VibeMatchConfig = {
121
+ languageModel: openrouter("anthropic/claude-sonnet-4"),
122
+ embeddingModel: openrouter.embedding("openai/text-embedding-3-small"),
123
+ };
124
+ ```
125
+
126
+ **Together AI:**
127
+
128
+ ```typescript
129
+ import { createOpenAI } from "@ai-sdk/openai";
130
+
131
+ const together = createOpenAI({
132
+ baseURL: "https://api.together.xyz/v1",
133
+ apiKey: process.env.TOGETHER_API_KEY,
134
+ });
135
+
136
+ const config: VibeMatchConfig = {
137
+ languageModel: together("meta-llama/Llama-3.3-70B-Instruct-Turbo"),
138
+ embeddingModel: together.embedding(
139
+ "togethercomputer/m2-bert-80M-8k-retrieval",
140
+ ),
141
+ };
142
+ ```
143
+
144
+ **Any AI SDK Provider:**
145
+
146
+ ```typescript
147
+ import { createAzure } from "@ai-sdk/azure";
148
+ import { createOpenAI } from "@ai-sdk/openai";
149
+
150
+ const azure = createAzure({
151
+ resourceName: "my-resource",
152
+ apiKey: process.env.AZURE_API_KEY,
153
+ });
154
+
155
+ const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
156
+
157
+ const config: VibeMatchConfig = {
158
+ languageModel: azure("my-gpt-4-deployment"),
159
+ embeddingModel: openai.embedding("text-embedding-3-small"),
160
+ };
161
+ ```
162
+
163
+ ## Matchers
164
+
165
+ ### `toBeSimilarTo(expected, options?)`
166
+
167
+ Tests if two strings are semantically similar.
168
+
169
+ ```typescript
170
+ expect("I love cheese pizza").toBeSimilarTo("Cheese pizza is my favorite", {
171
+ level: "loose", // "loose" | "normal" | "strict"
172
+ threshold: 0.75, // Percentage of samples that must pass
173
+ samples: 5, // Number of LLM calls to make
174
+ });
175
+ ```
176
+
177
+ ### `toMention(concept, options?)`
178
+
179
+ Tests if a string mentions a concept (directly, by description, or by implication).
180
+
181
+ ```typescript
182
+ expect("The red and yellow clown mascot").toMention("McDonald's", {
183
+ threshold: 0.75,
184
+ samples: 5,
185
+ });
186
+ ```
187
+
188
+ ### `toSatisfyCriteria(criteria, options?)`
189
+
190
+ Tests if text satisfies one or more criteria. Accepts either a single criterion string or an array of criteria.
191
+
192
+ ```typescript
193
+ // Single criterion
194
+ expect("Hi John, here's how to reset your password...").toSatisfyCriteria(
195
+ "Addresses the user by name",
196
+ );
197
+
198
+ // Multiple criteria
199
+ expect("Hi John, here's how to reset your password...").toSatisfyCriteria(
200
+ ["Addresses the user by name", "Provides a specific solution"],
201
+ {
202
+ mode: "all", // "all" | "any" | "threshold"
203
+ threshold: 0.75, // For "threshold" mode: percentage that must pass
204
+ samples: 3, // Number of LLM calls per criterion
205
+ },
206
+ );
207
+ ```
208
+
209
+ ### `toBeVectorSimilarTo(expected, options?)`
210
+
211
+ Tests semantic similarity using embedding vectors and cosine similarity.
212
+
213
+ ```typescript
214
+ expect("A guide to baking bread").toBeVectorSimilarTo("Bread baking tutorial", {
215
+ threshold: 0.85, // Minimum cosine similarity (0-1)
216
+ });
217
+ ```
218
+
219
+ ## Inline Model Overrides
220
+
221
+ You can override the language model or embedding model for individual matcher calls. This is useful when you want to use a different model for specific tests without changing your global configuration.
222
+
223
+ ```typescript
224
+ import {
225
+ vibeMatchers,
226
+ type LanguageModelV1,
227
+ type EmbeddingModel,
228
+ } from "vibe-match";
229
+ import { createOpenAI } from "@ai-sdk/openai";
230
+
231
+ // Configure with default models
232
+ const config: VibeMatchConfig = {
233
+ apiKeys: { openai: process.env.OPENAI_API_KEY },
234
+ languageModel: "openai:gpt-4o-mini",
235
+ embeddingModel: "openai:text-embedding-3-small",
236
+ };
237
+
238
+ expect.extend(vibeMatchers(config));
239
+
240
+ // Create a more powerful model for specific tests
241
+ const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
242
+ const gpt4o = openai("gpt-4o");
243
+
244
+ // Use inline override for this specific assertion
245
+ expect(response).toBeSimilarTo(expected, {
246
+ languageModel: gpt4o, // Use GPT-4o for this test only
247
+ });
248
+ ```
249
+
250
+ ### Language Model Overrides
251
+
252
+ The following matchers support the `languageModel` option:
253
+
254
+ - `toBeSimilarTo` — for semantic similarity checks
255
+ - `toMention` — for concept mention detection
256
+ - `toSatisfyCriteria` — for criteria evaluation
257
+
258
+ ```typescript
259
+ // Use a stronger model for critical tests
260
+ expect(aiResponse).toSatisfyCriteria(
261
+ ["Is factually accurate", "Cites sources"],
262
+ {
263
+ languageModel: gpt4o,
264
+ mode: "all",
265
+ },
266
+ );
267
+
268
+ expect(summary).toMention("quarterly revenue", {
269
+ languageModel: gpt4o,
270
+ });
271
+ ```
272
+
273
+ ### Embedding Model Overrides
274
+
275
+ The `toBeVectorSimilarTo` matcher supports the `embeddingModel` option:
276
+
277
+ ```typescript
278
+ const largeEmbedding = openai.embedding("text-embedding-3-large");
279
+
280
+ expect(document).toBeVectorSimilarTo(reference, {
281
+ embeddingModel: largeEmbedding, // Use larger embedding model
282
+ threshold: 0.9,
283
+ });
284
+ ```
285
+
286
+ ## Supported Providers
287
+
288
+ | Provider | Language Models | Embedding Models |
289
+ | ---------- | --------------- | ---------------- |
290
+ | OpenAI | ✅ | ✅ |
291
+ | Anthropic | ✅ | ❌ |
292
+ | Google | ✅ | ✅ |
293
+ | Mistral | ✅ | ✅ |
294
+ | xAI (Grok) | ✅ | ❌ |
295
+
296
+ You can mix and match providers—use Anthropic for language models and OpenAI for embeddings, for example.
@@ -0,0 +1,12 @@
1
+ export { vibeMatchers } from "./matchers";
2
+ export type { VibeMatchConfig, VibeMatchStringConfig, VibeMatchCustomModelConfig, VibeMatchPrompts, VibeMatchApiKeys, } from "./types";
3
+ export type { LanguageModelString, EmbeddingModelString } from "./providers";
4
+ export type { LanguageModelV1, EmbeddingModel } from "ai";
5
+ export type { ToBeSimilarToOptions } from "./matchers/toBeSimilarTo";
6
+ export type { ToMentionOptions } from "./matchers/toMention";
7
+ export type { ToSatisfyCriteriaOptions } from "./matchers/toSatisfyCriteria";
8
+ export type { VectorSimilarityOptions } from "./matchers/toBeVectorSimilarTo";
9
+ export { DEFAULT_SIMILARITY_PROMPT } from "./matchers/toBeSimilarTo";
10
+ export { DEFAULT_MENTION_PROMPT } from "./matchers/toMention";
11
+ export { DEFAULT_SATISFY_CRITERIA_PROMPT } from "./matchers/toSatisfyCriteria";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAG7E,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,IAAI,CAAC;AAG1D,YAAY,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,YAAY,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAG9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,+BAA+B,EAAE,MAAM,8BAA8B,CAAC"}