Ragfish Logo
Get In Touch
Ragfish Logo

Book a Demo

Interfaces

Interfaces define the contracts between components in the Ragfish Framework.

They allow the core framework to work with different implementations without becoming tightly coupled to a specific AI provider, vector database, or connector.

This is an important part of Ragfish's modular architecture.

For example, @ragfish/core can define how an LLM or retriever should behave, while packages such as @ragfish/openai and @ragfish/qdrant provide concrete implementations.

Why Interfaces?

Consider a Ragfish application that uses OpenAI and Qdrant.

@ragfish/core
      │
      ├── LLM Contract
      ├── Embedding Contract
      ├── Retriever Contract
      └── Vector Store Contract
             │
       ┌─────┴─────┐
       ▼           ▼
@ragfish/openai  @ragfish/qdrant
       │           │
       ▼           ▼
 OpenAILLM    QdrantRetriever
 OpenAI       QdrantVectorStore
 Embedding


The core framework does not need to know the internal implementation details of each provider.

It only needs the component to satisfy the expected interface.

Interface vs Implementation

An interface defines what a component must provide.

An implementation defines how that component works.

Conceptually:

Interface
   │
   │ defines contract
   ▼
Implementation
   │
   │ provides behavior
   ▼
Runtime


For example:

LLM Interface
     │
     ├── OpenAILLM
     ├── AnthropicLLM
     ├── GeminiLLM
     └── OllamaLLM


The same principle can be applied to other framework components.

Interfaces in Ragfish

Ragfish's modular architecture can be organized around contracts for components such as:

    1. Language Models

    2. Embedding Models

    3. Retrievers

    4. Vector Stores

    5. Connectors

    6. Documents

    7. Chat responses

The exact interface names and method signatures are defined by the version of the Ragfish core package you are using.

LLM Abstraction

The language model is an important example of interface-based design.

The core framework can work with an LLM abstraction without depending directly on OpenAI.

LLM Interface
       │
       ├───────────────┬───────────────┐
       ▼               ▼               ▼
   OpenAILLM       GeminiLLM       OllamaLLM

The OpenAI implementation belongs to the provider package rather than the core framework.

The current Ragfish architecture demonstrates this separation through:

import { Settings } from "@ragfish/core";
import { OpenAILLM } from "@ragfish/openai";

Settings.llm = new OpenAILLM({
  apiKey: process.env.OPENAI_API_KEY
});

Here, Settings comes from the core package while OpenAILLM comes from the OpenAI provider package.

Embedding Abstraction

The same architecture applies to embedding models.

                          Embedding Interface
                           │
             ┌─────────────┼─────────────┐
             │             │             │
             ▼             ▼             ▼
     OpenAIEmbedding  OtherProvider  CustomEmbedding

The core framework can use the embedding abstraction while the provider package handles the actual implementation.

For example:

Settings.embedModel = new OpenAIEmbedding({
  apiKey: process.env.OPENAI_API_KEY
});

This keeps embedding-provider details outside the core framework.

Retriever Abstraction

A retriever provides the mechanism for finding relevant knowledge.

Conceptually:

                    Retriever Interface
                           │
             ┌─────────────┼─────────────┐
             │             │             │
             ▼             ▼             ▼
     QdrantRetriever  CustomRetriever  OtherRetriever

The Chat component can work with a retriever without needing to know the internal search implementation.

For example:

const chat = new Chat({
  retriever
});

This is what allows the chat layer to remain independent of the vector database being used.

Vector Store Abstraction

A vector store is responsible for storing and searching vector representations.

Conceptually:

                 Vector Store Interface
                           │
             ┌─────────────┼─────────────┐
             ▼             ▼             ▼
     QdrantVectorStore  ChromaStore  CustomStore

The current Ragfish package architecture includes QdrantVectorStore as the Qdrant implementation.

const store = new QdrantVectorStore({
  // configuration
});

The retriever can then use the vector store:

const retriever = new QdrantRetriever({
  vectorStore: store,
  collectionName: "knowledge"
});

This separation allows the retrieval layer to remain independent from the underlying vector database.

Connector Abstraction

Connectors provide another natural extension point.

A connector is responsible for accessing a particular knowledge source.

Conceptually:

                 Connector Interface
                          │
            ┌─────────────┼─────────────┐
            ▼             ▼             ▼
     Spreadsheet       PDF          Database
      Connector      Connector       Connector

The connector-specific implementation can change without changing the rest of the knowledge pipeline.

Connector
    │
    ▼
Ingestion
    │
    ▼
Chunking
    │
    ▼
Embeddings
    │
    ▼
Vector Store


Dependency Direction

A key principle of the architecture is that the core framework should not depend on individual provider implementations.

The preferred dependency direction is:

                         Application
                             │
                             ▼
                       @ragfish/core
                        ▲           ▲
                        │           │
                        │           │
               @ragfish/openai   @ragfish/qdrant


The provider packages extend the framework rather than forcing the core framework to depend on them.

This keeps the architecture modular.

Replacing an Implementation

Because components communicate through interfaces, an implementation can be replaced without redesigning the entire application.

For example:

Current

Chat
 │
 ▼
Retriever
 │
 ▼
QdrantVectorStore

A future application could use:
Chat
 │
 ▼
Retriever
 │
 ▼
AnotherVectorStore


The higher-level application architecture remains the same.

Custom Implementations

The interface-based architecture also allows developers to create their own implementations.

Potential custom components include:

    1. Custom LLM providers

    2. Custom embedding providers

    3. Custom vector stores

    4. Custom retrievers

    5. Custom connectors

A custom implementation should follow the corresponding Ragfish interface defined by the core framework.

This allows the custom component to participate in the same framework pipeline as the built-in integrations.

Interfaces and TypeScript

Interfaces are particularly important in a TypeScript-first framework.

They provide:

    1. Compile-time contracts

    2. Type safety

    3. Better IDE support

    4. Easier testing

    5. Clear extension points

    6. More maintainable integrations

A simplified TypeScript contract might look like:

interface Component {
  // Framework-defined contract
}

The actual interfaces exposed by Ragfish should be used when implementing framework extensions.

Refer to the Types and API Reference sections for the exact interfaces and definitions available in your installed version.

Interface-Based Architecture

The overall design can be summarized as:

                     Ragfish Core
                          │
          ┌───────────────┼───────────────┐
          ▼               ▼               ▼
    LLM Interface   Retriever Interface  Connector Interface
          │               │               │
          ▼               ▼               ▼
     OpenAI /         Qdrant /        Spreadsheet /
     Other LLMs      Other Stores     Other Sources

This approach allows the framework to grow without introducing unnecessary coupling between components.

Best Practices

When working with Ragfish interfaces:

    1. Depend on framework abstractions rather than provider-specific implementations where possible.

    2. Keep custom implementations isolated from application business logic.

    3. Use the interfaces exposed by @ragfish/core.

    4. Avoid modifying core framework contracts for application-specific requirements.

    5. Keep provider-specific functionality inside provider packages.

    6. Follow TypeScript typing conventions when creating extensions.

What's Next?

Interfaces define the contracts between Ragfish components. The next page focuses on the Types used throughout the framework.

Continue to Types to understand the shared TypeScript models, configuration types, data structures, and other type definitions used by Ragfish applications and integrations.