modelfusion 0.38.0 → 0.39.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.
Files changed (30) hide show
  1. package/README.md +3 -4
  2. package/core/structure/JsonSchemaProducer.cjs +2 -0
  3. package/core/structure/JsonSchemaProducer.d.ts +9 -0
  4. package/core/structure/JsonSchemaProducer.js +1 -0
  5. package/core/structure/Schema.d.ts +1 -5
  6. package/core/structure/StructureDefinition.d.ts +2 -1
  7. package/core/structure/{UncheckedJsonSchemaSchema.cjs → UncheckedSchema.cjs} +3 -3
  8. package/core/structure/{UncheckedJsonSchemaSchema.d.ts → UncheckedSchema.d.ts} +3 -3
  9. package/core/structure/{UncheckedJsonSchemaSchema.js → UncheckedSchema.js} +1 -1
  10. package/core/structure/{UncheckedJsonSchemaStructureDefinition.cjs → UncheckedStructureDefinition.cjs} +5 -5
  11. package/core/structure/{UncheckedJsonSchemaStructureDefinition.d.ts → UncheckedStructureDefinition.d.ts} +3 -3
  12. package/core/structure/{UncheckedJsonSchemaStructureDefinition.js → UncheckedStructureDefinition.js} +3 -3
  13. package/core/structure/ZodStructureDefinition.d.ts +2 -2
  14. package/core/structure/index.cjs +3 -2
  15. package/core/structure/index.d.ts +3 -2
  16. package/core/structure/index.js +3 -2
  17. package/event-source/index.cjs +1 -0
  18. package/event-source/index.d.ts +1 -0
  19. package/event-source/index.js +1 -0
  20. package/event-source/readEventSource.cjs +27 -0
  21. package/event-source/readEventSource.d.ts +7 -0
  22. package/event-source/readEventSource.js +20 -0
  23. package/event-source/readEventSourceStream.cjs +6 -1
  24. package/event-source/readEventSourceStream.d.ts +2 -1
  25. package/event-source/readEventSourceStream.js +6 -1
  26. package/package.json +1 -1
  27. package/tool/Tool.d.ts +3 -2
  28. package/vector-index/memory/MemoryVectorIndex.cjs +15 -8
  29. package/vector-index/memory/MemoryVectorIndex.d.ts +2 -2
  30. package/vector-index/memory/MemoryVectorIndex.js +15 -8
package/README.md CHANGED
@@ -17,10 +17,9 @@
17
17
 
18
18
  ModelFusion is a library for building AI apps, chatbots, and agents. It provides abstractions for AI models, vector indices, and tools.
19
19
 
20
- - **Type inference and validation**: ModelFusion uses TypeScript and [Zod](https://github.com/colinhacks/zod) to infer types wherever possible and to validate model responses.
21
- - **Flexibility and control**: AI application development can be complex and unique to each project. With ModelFusion, you have complete control over the prompts and model settings, and you can access the raw responses from the models quickly to build what you need.
22
- - **No chains and predefined prompts**: Use the concepts provided by JavaScript (variables, functions, etc.) and explicit prompts to build applications you can easily understand and control. Not hidden prompts and logic.
23
20
  - **Multimodal Support**: Beyond just LLMs, ModelFusion encompasses a diverse array of models including text generation, text-to-speech, speech-to-text, and image generation, allowing you to build multifaceted AI applications with ease.
21
+ - **Flexibility and control**: AI application development can be complex and unique to each project. With ModelFusion, you have complete control over the prompts and model settings, and you can access the raw responses from the models quickly to build what you need.
22
+ - **Type inference and validation**: ModelFusion uses TypeScript and [Zod](https://github.com/colinhacks/zod) to infer types wherever possible and to validate model responses.
24
23
  - **Integrated support features**: Essential features like logging, retries, throttling, tracing, and error handling are built-in, helping you focus more on building your application.
25
24
 
26
25
  ## Quick Install
@@ -358,7 +357,7 @@ const text = await describeImage(
358
357
  new HuggingFaceImageDescriptionModel({
359
358
  model: "nlpconnect/vit-gpt2-image-captioning",
360
359
  }),
361
- data: buffer
360
+ data // buffer with image data
362
361
  );
363
362
  ```
364
363
 
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Schema defines a structure for a JSON object.
3
+ */
4
+ export interface JsonSchemaProducer {
5
+ /**
6
+ * Returns the JSON schema for this schema. The schema has to be a valid JSON schema in object form.
7
+ */
8
+ getJsonSchema(): unknown;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Schema defines a structure for a JSON object.
2
+ * Validates that the structure of `value` matches the structure of this schema.
3
3
  */
4
4
  export interface Schema<STRUCTURE> {
5
5
  /**
@@ -13,10 +13,6 @@ export interface Schema<STRUCTURE> {
13
13
  success: false;
14
14
  error: unknown;
15
15
  };
16
- /**
17
- * Returns the JSON schema for this schema. The schema has to be a valid JSON schema in object form.
18
- */
19
- getJsonSchema(): unknown;
20
16
  /**
21
17
  * Only used for type inference.
22
18
  */
@@ -1,6 +1,7 @@
1
+ import { JsonSchemaProducer } from "./JsonSchemaProducer.js";
1
2
  import { Schema } from "./Schema.js";
2
3
  export interface StructureDefinition<NAME extends string, STRUCTURE> {
3
4
  name: NAME;
4
5
  description?: string;
5
- schema: Schema<STRUCTURE>;
6
+ schema: Schema<STRUCTURE> & JsonSchemaProducer;
6
7
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UncheckedJsonSchemaSchema = void 0;
4
- class UncheckedJsonSchemaSchema {
3
+ exports.UncheckedSchema = void 0;
4
+ class UncheckedSchema {
5
5
  constructor(jsonSchema) {
6
6
  Object.defineProperty(this, "jsonSchema", {
7
7
  enumerable: true,
@@ -23,4 +23,4 @@ class UncheckedJsonSchemaSchema {
23
23
  return this.jsonSchema;
24
24
  }
25
25
  }
26
- exports.UncheckedJsonSchemaSchema = UncheckedJsonSchemaSchema;
26
+ exports.UncheckedSchema = UncheckedSchema;
@@ -1,7 +1,7 @@
1
1
  import { Schema } from "./Schema.js";
2
- export declare class UncheckedJsonSchemaSchema<STRUCTURE> implements Schema<STRUCTURE> {
3
- private readonly jsonSchema;
4
- constructor(jsonSchema: unknown);
2
+ export declare class UncheckedSchema<STRUCTURE> implements Schema<STRUCTURE> {
3
+ private readonly jsonSchema?;
4
+ constructor(jsonSchema?: unknown);
5
5
  validate(value: unknown): {
6
6
  success: true;
7
7
  value: STRUCTURE;
@@ -1,4 +1,4 @@
1
- export class UncheckedJsonSchemaSchema {
1
+ export class UncheckedSchema {
2
2
  constructor(jsonSchema) {
3
3
  Object.defineProperty(this, "jsonSchema", {
4
4
  enumerable: true,
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UncheckedJsonSchemaStructureDefinition = void 0;
4
- const UncheckedJsonSchemaSchema_js_1 = require("./UncheckedJsonSchemaSchema.cjs");
5
- class UncheckedJsonSchemaStructureDefinition {
3
+ exports.UncheckedStructureDefinition = void 0;
4
+ const UncheckedSchema_js_1 = require("./UncheckedSchema.cjs");
5
+ class UncheckedStructureDefinition {
6
6
  constructor({ name, description, jsonSchema, }) {
7
7
  Object.defineProperty(this, "name", {
8
8
  enumerable: true,
@@ -24,7 +24,7 @@ class UncheckedJsonSchemaStructureDefinition {
24
24
  });
25
25
  this.name = name;
26
26
  this.description = description;
27
- this.schema = new UncheckedJsonSchemaSchema_js_1.UncheckedJsonSchemaSchema(jsonSchema);
27
+ this.schema = new UncheckedSchema_js_1.UncheckedSchema(jsonSchema);
28
28
  }
29
29
  }
30
- exports.UncheckedJsonSchemaStructureDefinition = UncheckedJsonSchemaStructureDefinition;
30
+ exports.UncheckedStructureDefinition = UncheckedStructureDefinition;
@@ -1,9 +1,9 @@
1
- import { Schema } from "./Schema.js";
2
1
  import { StructureDefinition } from "./StructureDefinition.js";
3
- export declare class UncheckedJsonSchemaStructureDefinition<NAME extends string, STRUCTURE> implements StructureDefinition<NAME, STRUCTURE> {
2
+ import { UncheckedSchema } from "./UncheckedSchema.js";
3
+ export declare class UncheckedStructureDefinition<NAME extends string, STRUCTURE> implements StructureDefinition<NAME, STRUCTURE> {
4
4
  name: NAME;
5
5
  description?: string;
6
- schema: Schema<STRUCTURE>;
6
+ schema: UncheckedSchema<STRUCTURE>;
7
7
  constructor({ name, description, jsonSchema, }: {
8
8
  name: NAME;
9
9
  description?: string;
@@ -1,5 +1,5 @@
1
- import { UncheckedJsonSchemaSchema } from "./UncheckedJsonSchemaSchema.js";
2
- export class UncheckedJsonSchemaStructureDefinition {
1
+ import { UncheckedSchema } from "./UncheckedSchema.js";
2
+ export class UncheckedStructureDefinition {
3
3
  constructor({ name, description, jsonSchema, }) {
4
4
  Object.defineProperty(this, "name", {
5
5
  enumerable: true,
@@ -21,6 +21,6 @@ export class UncheckedJsonSchemaStructureDefinition {
21
21
  });
22
22
  this.name = name;
23
23
  this.description = description;
24
- this.schema = new UncheckedJsonSchemaSchema(jsonSchema);
24
+ this.schema = new UncheckedSchema(jsonSchema);
25
25
  }
26
26
  }
@@ -1,10 +1,10 @@
1
1
  import { z } from "zod";
2
- import { Schema } from "./Schema.js";
3
2
  import { StructureDefinition } from "./StructureDefinition.js";
3
+ import { ZodSchema } from "./ZodSchema.js";
4
4
  export declare class ZodStructureDefinition<NAME extends string, STRUCTURE> implements StructureDefinition<NAME, STRUCTURE> {
5
5
  name: NAME;
6
6
  description?: string;
7
- schema: Schema<STRUCTURE>;
7
+ schema: ZodSchema<STRUCTURE>;
8
8
  constructor({ name, description, schema, }: {
9
9
  name: NAME;
10
10
  description?: string;
@@ -14,9 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./JsonSchemaProducer.cjs"), exports);
17
18
  __exportStar(require("./Schema.cjs"), exports);
18
19
  __exportStar(require("./StructureDefinition.cjs"), exports);
19
- __exportStar(require("./UncheckedJsonSchemaSchema.cjs"), exports);
20
- __exportStar(require("./UncheckedJsonSchemaStructureDefinition.cjs"), exports);
20
+ __exportStar(require("./UncheckedSchema.cjs"), exports);
21
+ __exportStar(require("./UncheckedStructureDefinition.cjs"), exports);
21
22
  __exportStar(require("./ZodSchema.cjs"), exports);
22
23
  __exportStar(require("./ZodStructureDefinition.cjs"), exports);
@@ -1,6 +1,7 @@
1
+ export * from "./JsonSchemaProducer.js";
1
2
  export * from "./Schema.js";
2
3
  export * from "./StructureDefinition.js";
3
- export * from "./UncheckedJsonSchemaSchema.js";
4
- export * from "./UncheckedJsonSchemaStructureDefinition.js";
4
+ export * from "./UncheckedSchema.js";
5
+ export * from "./UncheckedStructureDefinition.js";
5
6
  export * from "./ZodSchema.js";
6
7
  export * from "./ZodStructureDefinition.js";
@@ -1,6 +1,7 @@
1
+ export * from "./JsonSchemaProducer.js";
1
2
  export * from "./Schema.js";
2
3
  export * from "./StructureDefinition.js";
3
- export * from "./UncheckedJsonSchemaSchema.js";
4
- export * from "./UncheckedJsonSchemaStructureDefinition.js";
4
+ export * from "./UncheckedSchema.js";
5
+ export * from "./UncheckedStructureDefinition.js";
5
6
  export * from "./ZodSchema.js";
6
7
  export * from "./ZodStructureDefinition.js";
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./AsyncQueue.cjs"), exports);
18
18
  __exportStar(require("./createEventSourceStream.cjs"), exports);
19
+ __exportStar(require("./readEventSource.cjs"), exports);
19
20
  __exportStar(require("./readEventSourceStream.cjs"), exports);
@@ -1,3 +1,4 @@
1
1
  export * from "./AsyncQueue.js";
2
2
  export * from "./createEventSourceStream.js";
3
+ export * from "./readEventSource.js";
3
4
  export * from "./readEventSourceStream.js";
@@ -1,3 +1,4 @@
1
1
  export * from "./AsyncQueue.js";
2
2
  export * from "./createEventSourceStream.js";
3
+ export * from "./readEventSource.js";
3
4
  export * from "./readEventSourceStream.js";
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readEventSource = void 0;
7
+ const secure_json_parse_1 = __importDefault(require("secure-json-parse"));
8
+ function readEventSource({ url, schema, onEvent, onError = console.error, }) {
9
+ const eventSource = new EventSource(url);
10
+ eventSource.onmessage = (e) => {
11
+ try {
12
+ const validationResult = schema.validate(secure_json_parse_1.default.parse(e.data));
13
+ if (!validationResult.success) {
14
+ onError(validationResult.error, eventSource);
15
+ return;
16
+ }
17
+ onEvent(validationResult.value, eventSource);
18
+ }
19
+ catch (error) {
20
+ onError(error, eventSource);
21
+ }
22
+ };
23
+ eventSource.onerror = (e) => {
24
+ onError(e, eventSource);
25
+ };
26
+ }
27
+ exports.readEventSource = readEventSource;
@@ -0,0 +1,7 @@
1
+ import { Schema } from "../core/structure/Schema";
2
+ export declare function readEventSource<T>({ url, schema, onEvent, onError, }: {
3
+ url: string;
4
+ schema: Schema<T>;
5
+ onEvent: (event: T, eventSource: EventSource) => void;
6
+ onError?: (error: unknown, eventSource: EventSource) => void;
7
+ }): void;
@@ -0,0 +1,20 @@
1
+ import SecureJSON from "secure-json-parse";
2
+ export function readEventSource({ url, schema, onEvent, onError = console.error, }) {
3
+ const eventSource = new EventSource(url);
4
+ eventSource.onmessage = (e) => {
5
+ try {
6
+ const validationResult = schema.validate(SecureJSON.parse(e.data));
7
+ if (!validationResult.success) {
8
+ onError(validationResult.error, eventSource);
9
+ return;
10
+ }
11
+ onEvent(validationResult.value, eventSource);
12
+ }
13
+ catch (error) {
14
+ onError(error, eventSource);
15
+ }
16
+ };
17
+ eventSource.onerror = (e) => {
18
+ onError(e, eventSource);
19
+ };
20
+ }
@@ -14,7 +14,12 @@ function readEventSourceStream({ stream, schema, errorHandler, }) {
14
14
  .then(async (events) => {
15
15
  try {
16
16
  for await (const event of events) {
17
- queue.push(schema.parse(secure_json_parse_1.default.parse(event.data)));
17
+ const validationResult = schema.validate(secure_json_parse_1.default.parse(event.data));
18
+ if (!validationResult.success) {
19
+ errorHandler?.(validationResult.error);
20
+ continue;
21
+ }
22
+ queue.push(validationResult.value);
18
23
  }
19
24
  }
20
25
  catch (error) {
@@ -1,6 +1,7 @@
1
+ import { Schema } from "../core/structure/Schema.js";
1
2
  import { ErrorHandler } from "../util/ErrorHandler.js";
2
3
  export declare function readEventSourceStream<T>({ stream, schema, errorHandler, }: {
3
4
  stream: ReadableStream<Uint8Array>;
4
- schema: Zod.Schema<T>;
5
+ schema: Schema<T>;
5
6
  errorHandler?: ErrorHandler;
6
7
  }): AsyncIterable<T>;
@@ -8,7 +8,12 @@ export function readEventSourceStream({ stream, schema, errorHandler, }) {
8
8
  .then(async (events) => {
9
9
  try {
10
10
  for await (const event of events) {
11
- queue.push(schema.parse(SecureJSON.parse(event.data)));
11
+ const validationResult = schema.validate(SecureJSON.parse(event.data));
12
+ if (!validationResult.success) {
13
+ errorHandler?.(validationResult.error);
14
+ continue;
15
+ }
16
+ queue.push(validationResult.value);
12
17
  }
13
18
  }
14
19
  catch (error) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modelfusion",
3
3
  "description": "Build multimodal applications, chatbots, and agents with JavaScript and TypeScript.",
4
- "version": "0.38.0",
4
+ "version": "0.39.0",
5
5
  "author": "Lars Grammel",
6
6
  "license": "MIT",
7
7
  "keywords": [
package/tool/Tool.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { FunctionOptions } from "../core/FunctionOptions.js";
2
+ import { JsonSchemaProducer } from "../core/structure/JsonSchemaProducer.js";
2
3
  import { Schema } from "../core/structure/Schema.js";
3
4
  import { StructureDefinition } from "../core/structure/StructureDefinition.js";
4
5
  /**
@@ -20,7 +21,7 @@ export declare class Tool<NAME extends string, INPUT, OUTPUT> {
20
21
  * The schema of the input that the tool expects. The language model will use this to generate the input.
21
22
  * Use descriptions to make the input understandable for the language model.
22
23
  */
23
- readonly inputSchema: Schema<INPUT>;
24
+ readonly inputSchema: Schema<INPUT> & JsonSchemaProducer;
24
25
  /**
25
26
  * An optional schema of the output that the tool produces. This will be used to validate the output.
26
27
  */
@@ -32,7 +33,7 @@ export declare class Tool<NAME extends string, INPUT, OUTPUT> {
32
33
  constructor({ name, description, inputSchema, outputSchema, execute, }: {
33
34
  name: NAME;
34
35
  description: string;
35
- inputSchema: Schema<INPUT>;
36
+ inputSchema: Schema<INPUT> & JsonSchemaProducer;
36
37
  outputSchema?: Schema<OUTPUT>;
37
38
  execute(input: INPUT, options?: FunctionOptions): PromiseLike<OUTPUT>;
38
39
  });
@@ -4,8 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.MemoryVectorIndex = void 0;
7
+ const secure_json_parse_1 = __importDefault(require("secure-json-parse"));
7
8
  const zod_1 = __importDefault(require("zod"));
8
9
  const cosineSimilarity_js_1 = require("../../util/cosineSimilarity.cjs");
10
+ const jsonDataSchema = zod_1.default.array(zod_1.default.object({
11
+ id: zod_1.default.string(),
12
+ vector: zod_1.default.array(zod_1.default.number()),
13
+ data: zod_1.default.unknown(),
14
+ }));
9
15
  /**
10
16
  * A very simple vector index that stores all entries in memory. Useful when you only have
11
17
  * a small number of entries and don't want to set up a real database, e.g. for conversational memory
@@ -21,15 +27,16 @@ class MemoryVectorIndex {
21
27
  });
22
28
  }
23
29
  static async deserialize({ serializedData, schema, }) {
24
- let json = JSON.parse(serializedData);
30
+ // validate the outer structure:
31
+ const json = jsonDataSchema.parse(secure_json_parse_1.default.parse(serializedData));
25
32
  if (schema != null) {
26
- json = zod_1.default
27
- .array(zod_1.default.object({
28
- id: zod_1.default.string(),
29
- vector: zod_1.default.array(zod_1.default.number()),
30
- data: schema,
31
- }))
32
- .parse(json);
33
+ // when a schema is provided, validate all entries:
34
+ for (const entry of json) {
35
+ const validationResult = schema.validate(entry.data);
36
+ if (!validationResult.success) {
37
+ throw validationResult.error;
38
+ }
39
+ }
33
40
  }
34
41
  const vectorIndex = new MemoryVectorIndex();
35
42
  vectorIndex.upsertMany(json);
@@ -1,5 +1,5 @@
1
- import z from "zod";
2
1
  import { Vector } from "../../core/Vector.js";
2
+ import { Schema } from "../../core/structure/Schema.js";
3
3
  import { VectorIndex } from "../VectorIndex.js";
4
4
  /**
5
5
  * A very simple vector index that stores all entries in memory. Useful when you only have
@@ -9,7 +9,7 @@ import { VectorIndex } from "../VectorIndex.js";
9
9
  export declare class MemoryVectorIndex<DATA> implements VectorIndex<DATA, MemoryVectorIndex<DATA>, (value: DATA) => boolean> {
10
10
  static deserialize<DATA>({ serializedData, schema, }: {
11
11
  serializedData: string;
12
- schema?: z.ZodSchema<DATA>;
12
+ schema?: Schema<DATA>;
13
13
  }): Promise<MemoryVectorIndex<DATA>>;
14
14
  private readonly entries;
15
15
  upsertMany(data: Array<{
@@ -1,5 +1,11 @@
1
+ import SecureJSON from "secure-json-parse";
1
2
  import z from "zod";
2
3
  import { cosineSimilarity } from "../../util/cosineSimilarity.js";
4
+ const jsonDataSchema = z.array(z.object({
5
+ id: z.string(),
6
+ vector: z.array(z.number()),
7
+ data: z.unknown(),
8
+ }));
3
9
  /**
4
10
  * A very simple vector index that stores all entries in memory. Useful when you only have
5
11
  * a small number of entries and don't want to set up a real database, e.g. for conversational memory
@@ -15,15 +21,16 @@ export class MemoryVectorIndex {
15
21
  });
16
22
  }
17
23
  static async deserialize({ serializedData, schema, }) {
18
- let json = JSON.parse(serializedData);
24
+ // validate the outer structure:
25
+ const json = jsonDataSchema.parse(SecureJSON.parse(serializedData));
19
26
  if (schema != null) {
20
- json = z
21
- .array(z.object({
22
- id: z.string(),
23
- vector: z.array(z.number()),
24
- data: schema,
25
- }))
26
- .parse(json);
27
+ // when a schema is provided, validate all entries:
28
+ for (const entry of json) {
29
+ const validationResult = schema.validate(entry.data);
30
+ if (!validationResult.success) {
31
+ throw validationResult.error;
32
+ }
33
+ }
27
34
  }
28
35
  const vectorIndex = new MemoryVectorIndex();
29
36
  vectorIndex.upsertMany(json);