npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

modelfusion

v0.137.0

Published

The TypeScript library for building AI applications.

Downloads

8,459

Readme

ModelFusion

The TypeScript library for building AI applications.

NPM Version MIT License Docs Discord Created by Lars Grammel Follow @modelfusionjs

Introduction | Quick Install | Usage | Documentation | Examples | Contributing | modelfusion.dev

Introduction

ModelFusion is an abstraction layer for integrating AI models into JavaScript and TypeScript applications, unifying the API for common operations such as text streaming, object generation, and tool usage. It provides features to support production environments, including observability hooks, logging, and automatic retries. You can use ModelFusion to build AI applications, chatbots, and agents.

  • Vendor-neutral: ModelFusion is a non-commercial open source project that is community-driven. You can use it with any supported provider.
  • Multi-modal: ModelFusion supports a wide range of models including text generation, image generation, vision, text-to-speech, speech-to-text, and embedding models.
  • Type inference and validation: ModelFusion infers TypeScript types wherever possible and validates model responses.
  • Observability and logging: ModelFusion provides an observer framework and logging support.
  • Resilience and robustness: ModelFusion ensures seamless operation through automatic retries, throttling, and error handling mechanisms.
  • Built for production: ModelFusion is fully tree-shakeable, can be used in serverless environments, and only uses a minimal set of dependencies.

[!NOTE] ModelFusion is getting closer to a stable v1, which is expected in Q2/2024. The main API is now mostly stable, but until version 1.0 there may be breaking changes. Feedback and suggestions are welcome.

Quick Install

npm install modelfusion

Or use a starter template:

Usage Examples

[!TIP] The basic examples are a great way to get started and to explore in parallel with the documentation. You can find them in the examples/basic folder.

You can provide API keys for the different integrations using environment variables (e.g., OPENAI_API_KEY) or pass them into the model constructors as options.

Generate Text

Generate text using a language model and a prompt. You can stream the text if it is supported by the model. You can use images for multi-modal prompting if the model supports it (e.g. with llama.cpp). You can use prompt styles to use text, instruction, or chat prompts.

generateText

import { generateText, openai } from "modelfusion";

const text = await generateText({
  model: openai.CompletionTextGenerator({ model: "gpt-3.5-turbo-instruct" }),
  prompt: "Write a short story about a robot learning to love:\n\n",
});

Providers: OpenAI, OpenAI compatible, Llama.cpp, Ollama, Mistral, Hugging Face, Cohere

streamText

import { streamText, openai } from "modelfusion";

const textStream = await streamText({
  model: openai.CompletionTextGenerator({ model: "gpt-3.5-turbo-instruct" }),
  prompt: "Write a short story about a robot learning to love:\n\n",
});

for await (const textPart of textStream) {
  process.stdout.write(textPart);
}

Providers: OpenAI, OpenAI compatible, Llama.cpp, Ollama, Mistral, Cohere

streamText with multi-modal prompt

Multi-modal vision models such as GPT 4 Vision can process images as part of the prompt.

import { streamText, openai } from "modelfusion";
import { readFileSync } from "fs";

const image = readFileSync("./image.png");

const textStream = await streamText({
  model: openai
    .ChatTextGenerator({ model: "gpt-4-vision-preview" })
    .withInstructionPrompt(),

  prompt: {
    instruction: [
      { type: "text", text: "Describe the image in detail." },
      { type: "image", image, mimeType: "image/png" },
    ],
  },
});

for await (const textPart of textStream) {
  process.stdout.write(textPart);
}

Providers: OpenAI, OpenAI compatible, Llama.cpp, Ollama

Generate Object

Generate typed objects using a language model and a schema.

generateObject

Generate an object that matches a schema.

import {
  ollama,
  zodSchema,
  generateObject,
  jsonObjectPrompt,
} from "modelfusion";

const sentiment = await generateObject({
  model: ollama
    .ChatTextGenerator({
      model: "openhermes2.5-mistral",
      maxGenerationTokens: 1024,
      temperature: 0,
    })
    .asObjectGenerationModel(jsonObjectPrompt.instruction()),

  schema: zodSchema(
    z.object({
      sentiment: z
        .enum(["positive", "neutral", "negative"])
        .describe("Sentiment."),
    })
  ),

  prompt: {
    system:
      "You are a sentiment evaluator. " +
      "Analyze the sentiment of the following product review:",
    instruction:
      "After I opened the package, I was met by a very unpleasant smell " +
      "that did not disappear even after washing. Never again!",
  },
});

Providers: OpenAI, Ollama, Llama.cpp

streamObject

Stream a object that matches a schema. Partial objects before the final part are untyped JSON.

import { zodSchema, openai, streamObject } from "modelfusion";

const objectStream = await streamObject({
  model: openai
    .ChatTextGenerator(/* ... */)
    .asFunctionCallObjectGenerationModel({
      fnName: "generateCharacter",
      fnDescription: "Generate character descriptions.",
    })
    .withTextPrompt(),

  schema: zodSchema(
    z.object({
      characters: z.array(
        z.object({
          name: z.string(),
          class: z
            .string()
            .describe("Character class, e.g. warrior, mage, or thief."),
          description: z.string(),
        })
      ),
    })
  ),

  prompt: "Generate 3 character descriptions for a fantasy role playing game.",
});

for await (const { partialObject } of objectStream) {
  console.clear();
  console.log(partialObject);
}

Providers: OpenAI, Ollama, Llama.cpp

Generate Image

Generate an image from a prompt.

import { generateImage, openai } from "modelfusion";

const image = await generateImage({
  model: openai.ImageGenerator({ model: "dall-e-3", size: "1024x1024" }),
  prompt:
    "the wicked witch of the west in the style of early 19th century painting",
});

Providers: OpenAI (Dall·E), Stability AI, Automatic1111

Generate Speech

Synthesize speech (audio) from text. Also called TTS (text-to-speech).

generateSpeech

generateSpeech synthesizes speech from text.

import { generateSpeech, lmnt } from "modelfusion";

// `speech` is a Uint8Array with MP3 audio data
const speech = await generateSpeech({
  model: lmnt.SpeechGenerator({
    voice: "034b632b-df71-46c8-b440-86a42ffc3cf3", // Henry
  }),
  text:
    "Good evening, ladies and gentlemen! Exciting news on the airwaves tonight " +
    "as The Rolling Stones unveil 'Hackney Diamonds,' their first collection of " +
    "fresh tunes in nearly twenty years, featuring the illustrious Lady Gaga, the " +
    "magical Stevie Wonder, and the final beats from the late Charlie Watts.",
});

Providers: Eleven Labs, LMNT, OpenAI

streamSpeech

generateSpeech generates a stream of speech chunks from text or from a text stream. Depending on the model, this can be fully duplex.

import { streamSpeech, elevenlabs } from "modelfusion";

const textStream: AsyncIterable<string>;

const speechStream = await streamSpeech({
  model: elevenlabs.SpeechGenerator({
    model: "eleven_turbo_v2",
    voice: "pNInz6obpgDQGcFmaJgB", // Adam
    optimizeStreamingLatency: 1,
    voiceSettings: { stability: 1, similarityBoost: 0.35 },
    generationConfig: {
      chunkLengthSchedule: [50, 90, 120, 150, 200],
    },
  }),
  text: textStream,
});

for await (const part of speechStream) {
  // each part is a Uint8Array with MP3 audio data
}

Providers: Eleven Labs

Generate Transcription

Transcribe speech (audio) data into text. Also called speech-to-text (STT).

import { generateTranscription, openai } from "modelfusion";
import fs from "node:fs";

const transcription = await generateTranscription({
  model: openai.Transcriber({ model: "whisper-1" }),
  mimeType: "audio/mp3",
  audioData: await fs.promises.readFile("data/test.mp3"),
});

Providers: OpenAI (Whisper), Whisper.cpp

Embed Value

Create embeddings for text and other values. Embeddings are vectors that represent the essence of the values in the context of the model.

import { embed, embedMany, openai } from "modelfusion";

// embed single value:
const embedding = await embed({
  model: openai.TextEmbedder({ model: "text-embedding-ada-002" }),
  value: "At first, Nox didn't know what to do with the pup.",
});

// embed many values:
const embeddings = await embedMany({
  model: openai.TextEmbedder({ model: "text-embedding-ada-002" }),
  values: [
    "At first, Nox didn't know what to do with the pup.",
    "He keenly observed and absorbed everything around him, from the birds in the sky to the trees in the forest.",
  ],
});

Providers: OpenAI, OpenAI compatible, Llama.cpp, Ollama, Mistral, Hugging Face, Cohere

Classify Value

Classifies a value into a category.

import { classify, EmbeddingSimilarityClassifier, openai } from "modelfusion";

const classifier = new EmbeddingSimilarityClassifier({
  embeddingModel: openai.TextEmbedder({ model: "text-embedding-ada-002" }),
  similarityThreshold: 0.82,
  clusters: [
    {
      name: "politics" as const,
      values: [
        "they will save the country!",
        // ...
      ],
    },
    {
      name: "chitchat" as const,
      values: [
        "how's the weather today?",
        // ...
      ],
    },
  ],
});

// strongly typed result:
const result = await classify({
  model: classifier,
  value: "don't you love politics?",
});

Classifiers: EmbeddingSimilarityClassifier

Tokenize Text

Split text into tokens and reconstruct the text from tokens.

const tokenizer = openai.Tokenizer({ model: "gpt-4" });

const text = "At first, Nox didn't know what to do with the pup.";

const tokenCount = await countTokens(tokenizer, text);

const tokens = await tokenizer.tokenize(text);
const tokensAndTokenTexts = await tokenizer.tokenizeWithTexts(text);
const reconstructedText = await tokenizer.detokenize(tokens);

Providers: OpenAI, Llama.cpp, Cohere

Tools

Tools are functions (and associated metadata) that can be executed by an AI model. They are useful for building chatbots and agents.

ModelFusion offers several tools out-of-the-box: Math.js, MediaWiki Search, SerpAPI, Google Custom Search. You can also create custom tools.

runTool

With runTool, you can ask a tool-compatible language model (e.g. OpenAI chat) to invoke a single tool. runTool first generates a tool call and then executes the tool with the arguments.

const { tool, toolCall, args, ok, result } = await runTool({
  model: openai.ChatTextGenerator({ model: "gpt-3.5-turbo" }),
  too: calculator,
  prompt: [openai.ChatMessage.user("What's fourteen times twelve?")],
});

console.log(`Tool call:`, toolCall);
console.log(`Tool:`, tool);
console.log(`Arguments:`, args);
console.log(`Ok:`, ok);
console.log(`Result or Error:`, result);

runTools

With runTools, you can ask a language model to generate several tool calls as well as text. The model will choose which tools (if any) should be called with which arguments. Both the text and the tool calls are optional. This function executes the tools.

const { text, toolResults } = await runTools({
  model: openai.ChatTextGenerator({ model: "gpt-3.5-turbo" }),
  tools: [calculator /* ... */],
  prompt: [openai.ChatMessage.user("What's fourteen times twelve?")],
});

Agent Loop

You can use runTools to implement an agent loop that responds to user messages and executes tools. Learn more.

Vector Indices

const texts = [
  "A rainbow is an optical phenomenon that can occur under certain meteorological conditions.",
  "It is caused by refraction, internal reflection and dispersion of light in water droplets resulting in a continuous spectrum of light appearing in the sky.",
  // ...
];

const vectorIndex = new MemoryVectorIndex<string>();
const embeddingModel = openai.TextEmbedder({
  model: "text-embedding-ada-002",
});

// update an index - usually done as part of an ingestion process:
await upsertIntoVectorIndex({
  vectorIndex,
  embeddingModel,
  objects: texts,
  getValueToEmbed: (text) => text,
});

// retrieve text chunks from the vector index - usually done at query time:
const retrievedTexts = await retrieve(
  new VectorIndexRetriever({
    vectorIndex,
    embeddingModel,
    maxResults: 3,
    similarityThreshold: 0.8,
  }),
  "rainbow and water droplets"
);

Available Vector Stores: Memory, SQLite VSS, Pinecone

Text Generation Prompt Styles

You can use different prompt styles (such as text, instruction or chat prompts) with ModelFusion text generation models. These prompt styles can be accessed through the methods .withTextPrompt(), .withChatPrompt() and .withInstructionPrompt():

Text Prompt Style

const text = await generateText({
  model: openai
    .ChatTextGenerator({
      // ...
    })
    .withTextPrompt(),

  prompt: "Write a short story about a robot learning to love",
});

Instruction Prompt Style

const text = await generateText({
  model: llamacpp
    .CompletionTextGenerator({
      // run https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF with llama.cpp
      promptTemplate: llamacpp.prompt.Llama2, // Set prompt template
      contextWindowSize: 4096, // Llama 2 context window size
      maxGenerationTokens: 512,
    })
    .withInstructionPrompt(),

  prompt: {
    system: "You are a story writer.",
    instruction: "Write a short story about a robot learning to love.",
  },
});

Chat Prompt Style

const textStream = await streamText({
  model: openai
    .ChatTextGenerator({
      model: "gpt-3.5-turbo",
    })
    .withChatPrompt(),

  prompt: {
    system: "You are a celebrated poet.",
    messages: [
      {
        role: "user",
        content: "Suggest a name for a robot.",
      },
      {
        role: "assistant",
        content: "I suggest the name Robbie",
      },
      {
        role: "user",
        content: "Write a short story about Robbie learning to love",
      },
    ],
  },
});

Image Generation Prompt Templates

You an use prompt templates with image models as well, e.g. to use a basic text prompt. It is available as a shorthand method:

const image = await generateImage({
  model: stability
    .ImageGenerator({
      //...
    })
    .withTextPrompt(),

  prompt:
    "the wicked witch of the west in the style of early 19th century painting",
});

| Prompt Template | Text Prompt | | --------------- | ----------- | | Automatic1111 | ✅ | | Stability | ✅ |

Metadata and original responses

ModelFusion model functions return rich responses that include the raw (original) response and metadata when you set the fullResponse argument to true.

// access the raw response (needs to be typed) and the metadata:
const { text, rawResponse, metadata } = await generateText({
  model: openai.CompletionTextGenerator({
    model: "gpt-3.5-turbo-instruct",
    maxGenerationTokens: 1000,
    n: 2, // generate 2 completions
  }),
  prompt: "Write a short story about a robot learning to love:\n\n",
  fullResponse: true,
});

console.log(metadata);

// cast to the raw response type:
for (const choice of (rawResponse as OpenAICompletionResponse).choices) {
  console.log(choice.text);
}

Logging and Observability

ModelFusion provides an observer framework and logging support. You can easily trace runs and call hierarchies, and you can add your own observers.

Enabling Logging on a Function Call

import { generateText, openai } from "modelfusion";

const text = await generateText({
  model: openai.CompletionTextGenerator({ model: "gpt-3.5-turbo-instruct" }),
  prompt: "Write a short story about a robot learning to love:\n\n",
  logging: "detailed-object",
});

Documentation

Guide

Integrations

Examples & Tutorials

Showcase

API Reference

More Examples

Basic Examples

Examples for almost all of the individual functions and objects. Highly recommended to get started.

StoryTeller

multi-modal, object streaming, image generation, text to speech, speech to text, text generation, object generation, embeddings

StoryTeller is an exploratory web application that creates short audio stories for pre-school kids.

Chatbot (Next.JS)

Next.js app, OpenAI GPT-3.5-turbo, streaming, abort handling

A web chat with an AI assistant, implemented as a Next.js app.

Chat with PDF

terminal app, PDF parsing, in memory vector indices, retrieval augmented generation, hypothetical document embedding

Ask questions about a PDF document and get answers from the document.

Next.js / ModelFusion Demos

Next.js app, image generation, transcription, object streaming, OpenAI, Stability AI, Ollama

Examples of using ModelFusion with Next.js 14 (App Router):

  • image generation
  • voice recording & transcription
  • object streaming

Duplex Speech Streaming (using Vite/React & ModelFusion Server/Fastify)

Speech Streaming, OpenAI, Elevenlabs streaming, Vite, Fastify, ModelFusion Server

Given a prompt, the server returns both a text and a speech stream response.

BabyAGI Agent

terminal app, agent, BabyAGI

TypeScript implementation of the BabyAGI classic and BabyBeeAGI.

Wikipedia Agent

terminal app, ReAct agent, GPT-4, OpenAI functions, tools

Get answers to questions from Wikipedia, e.g. "Who was born first, Einstein or Picasso?"

Middle school math agent

terminal app, agent, tools, GPT-4

Small agent that solves middle school math problems. It uses a calculator tool to solve the problems.

PDF to Tweet

terminal app, PDF parsing, recursive information extraction, in memory vector index, _style example retrieval, OpenAI GPT-4, cost calculation

Extracts information about a topic from a PDF and writes a tweet in your own style about it.

Cloudflare Workers

Cloudflare, OpenAI

Generate text on a Cloudflare Worker using ModelFusion and OpenAI.

Contributing

Contributing Guide

Read the ModelFusion contributing guide to learn about the development process, how to propose bugfixes and improvements, and how to build and test your changes.