π OllamaApiFacadeJS - For Express.js with LangChainJS
OllamaApiFacadeJS is an open-source Node.js library designed to seamlessly integrate an Express.js backend with the Ollama API using LangChainJS. This allows clients expecting an Ollama-compatible backend - such as Open WebUI - to interact with your Express.js API effortlessly.
It serves as a Node.js counterpart to the .NET-based OllamaApiFacade, providing a similar level of integration but optimized for the JavaScript/TypeScript ecosystem.

β¨ Features
β
Ollama-Compatible API for Express.js β Easily expose your Express backend as an Ollama API.
β
Supports Local AI Models (e.g., LM Studio) β Works with local inference engines like LM Studio.
β
Seamless Integration with LangChainJS β Enables natural language processing with LangChainJS.
β
Automatic Function Calling Support β New: Automatically executes tools (function calling) with ToolCallService
.
β
Streaming Support β Stream AI-generated responses directly to clients.
β
Custom Model Names β Configure custom model names for full flexibility.
β
Optimized for TypeScript β Includes full TypeScript support (.d.ts
files) for better IntelliSense.
π¦ Installation
You can install OllamaApiFacadeJS via NPM or PNPM:
pnpm add ollama-api-facade-js
or
npm install ollama-api-facade-js
π Getting Started
1οΈβ£ Prerequisites
- Node.js 18+
- Express.js
- LangChainJS
- LM Studio or another local LLM provider (optional)
2οΈβ£ Basic Express.js Example
Hereβs how to integrate OllamaApiFacadeJS into an Express.js application:
import express from 'express';
import { ChatOpenAI } from '@langchain/openai';
import { createOllamaApiFacade, createLMStudioConfig } from 'ollama-api-facade-js';
const chatOpenAI = new ChatOpenAI(createLMStudioConfig());
const app = express();
const ollamaApi = createOllamaApiFacade(app, chatOpenAI);
ollamaApi.postApiChat(async (chatRequest, chatModel, chatResponse) => {
chatRequest.addSystemMessage(
`You are a fun, slightly drunk coding buddy.
You joke around but still give correct and helpful programming advice.
Your tone is informal, chaotic, and enthusiasticβlike a tipsy friend debugging at 2 AM. Cheers!`
);
const result = await chatModel.invoke(chatRequest.messages);
chatResponse.asStream(result);
});
ollamaApi.listen();
π What does this setup do?
- Creates an Express.js server.
- Initializes the Ollama API facade using LangChainJS.
- Handles AI chat requests with streaming responses.
- Starts the server on
http://localhost:11434
(default Ollama port).
π Automatic Function Calling with ToolCallService
Normally, when using LangChainJS Function Calling, you need to:
- Bind tools manually (
bindTools([...])
).
- Check the response for
tool_calls
.
- Execute the appropriate tool(s).
- Re-send the updated message history to the model.
OllamaApiFacadeJS simplifies this with ToolCallService
, handling everything for you!
π Example with ToolCallService
import express from 'express';
import { ChatOpenAI } from '@langchain/openai';
import { createOllamaApiFacade, createLMStudioConfig } from 'ollama-api-facade-js';
import { dateTimeTool } from './tools/dateTimeTool';
const chatOpenAI = new ChatOpenAI(createLMStudioConfig());
const tools = [dateTimeTool];
const app = express();
const ollamaApi = createOllamaApiFacade(app, chatOpenAI);
ollamaApi.postApiChat(async (chatRequest, chatModel, chatResponse, toolCallService) => {
chatRequest.addSystemMessage(`You are a helpful Devbot.
You have a dateTimeTool registered, execute it when asked about the time / date / day.
`);
const response = await toolCallService.with(tools).invoke(chatRequest.messages);
chatResponse.asStream(response);
});
ollamaApi.listen();
π What happens under the hood?
ToolCallService
automatically binds the tools.
- If the model requests a tool, it gets executed immediately.
- The response is updated and re-sent to the model if needed.
- You donβt need to manually handle
tool_calls
anymore!
π‘ Running Open WebUI with Docker
After setting up your Express.js backend, you can integrate it with Open WebUI by running:
docker run -d -p 8181:8080 --add-host=host.docker.internal:host-gateway --name open-webui ghcr.io/open-webui/open-webui:main
β‘ Open WebUI will now be accessible at:
http://localhost:8181
For advanced configurations (e.g., GPU support), refer to the official Open WebUI GitHub repo.
π·οΈ Customizing Model Names
By default, the API uses the model name "nodeapi"
. To specify a custom model name, pass it as an argument:
const ollamaApi = createOllamaApiFacade(app, chatOpenAI, 'my-custom-model');
π‘ Streaming AI Responses
OllamaApiFacadeJS supports streaming responses to improve response times and user experience:
ollamaApi.postApiChat(async (chatRequest, chatModel, chatResponse) => {
const result = await chatModel.stream(chatRequest.messages);
chatResponse.asStream(result); // Handles both streams & single responses
});
π‘ Automatically detects whether streaming is supported and adapts accordingly.
Debugging HTTP Communication with https-proxy-agent
π
To analyze the HTTP communication between LangChainJS and language model APIs, you can use a proxy tool like Burp Suite Community Edition or OWASP ZAP. This allows you to inspect the exchanged data in detail.
π§ Setup
-
Install https-proxy-agent
in your project:
npm install https-proxy-agent
-
Configure HttpsProxyAgent
in your code:
import { ChatOpenAI } from '@langchain/openai';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { createLMStudioConfig } from 'ollama-api-facade-js';
const chatOpenAI = new ChatOpenAI(
createLMStudioConfig({
httpAgent: new HttpsProxyAgent('http://localhost:8080'),
})
);
Or for cloud API usage:
import { ChatOpenAI } from '@langchain/openai';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { createLMStudioConfig } from 'ollama-api-facade-js';
// Disable certificate verification
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const chatOpenAI = new ChatOpenAI({
model: 'gpt-4o-mini',
configuration: {
apiKey: openAiApiKey,
httpAgent: new HttpsProxyAgent('http://localhost:8080'),
},
});
-
Start Burp Suite Community Edition or OWASP ZAP and ensure the proxy is listening on http://localhost:8080
.
β οΈ Important Notes
-
If another service is already using port 8080, update the proxy port accordingly and adjust the HttpsProxyAgent
URL in the code, e.g.:
httpAgent: new HttpsProxyAgent('http://127.0.0.1:8888');
-
This method is for development and debugging purposes only. It should not be used in a production environment as it bypasses SSL validation.
With this setup, you can monitor all HTTP requests and responses exchanged between LangChainJS and the API endpoints, making it easier to debug and analyze the communication.
π€ Contributing
We welcome contributions from the community!
To contribute:
- Fork the repo.
- Create a branch (
feature/new-feature
).
- Commit your changes & push the branch.
- Submit a pull request for review.
π License
This project is licensed under the MIT License.
π‘ Created by Gregor Biswanger β Microsoft MVP for Azure AI & Web App Development.
π Acknowledgments
π Ready to build your AI-powered Express.js backend? Get started today!
If you have questions, feel free to open an issue on GitHub.
π₯ Summary
β
This README follows best practices
β
Clear structure with installation, usage, and advanced setup
β
Code snippets are formatted & easy to follow
β
Includes streaming, debugging, and customization options
β
Encourages contributions & community engagement
Let me know if you need any refinements! ππ₯