ollama-api-facade-js
Version:
OllamaApiFacadeJS is an open-source library for running an ExpressJS backend as an Ollama API using LangChainJS. It supports local language models services like LmStudio and allows seamless message conversion and streaming between LangChainJS and Ollama c
129 lines • 6.9 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChatResponse = void 0;
/**
* Class representing a chat response that streams LangChain data to the client.
*/
class ChatResponse {
constructor(response) {
this.response = response;
}
/**
* Streams LangChain data to the client as a series of chunks.
* @param {string | AIMessageChunk | IterableReadableStream<AIMessageChunk>} streamSource - The source of the stream data.
*/
asStream(streamSource) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
this.response.setHeader('Content-Type', 'application/json; charset=utf-8');
this.response.setHeader('Transfer-Encoding', 'chunked');
this.response.setHeader('Connection', 'keep-alive');
if (((_a = streamSource === null || streamSource === void 0 ? void 0 : streamSource.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'IterableReadableStream') {
yield this.sendStream(this.transformStream(streamSource));
}
else {
yield this.sendStream(this.splitIntoChunks(streamSource || streamSource));
}
});
}
sendStream(stream) {
return __awaiter(this, void 0, void 0, function* () {
var _a, stream_1, stream_1_1;
var _b, e_1, _c, _d;
let firstChunkSent = false;
try {
for (_a = true, stream_1 = __asyncValues(stream); stream_1_1 = yield stream_1.next(), _b = stream_1_1.done, !_b; _a = true) {
_d = stream_1_1.value;
_a = false;
const chunk = _d;
if (!chunk.content.trim())
continue;
const formattedChunk = {
created_at: new Date().toISOString(),
message: {
role: 'assistant',
content: chunk.content,
},
done: false,
};
this.response.write(`${JSON.stringify(formattedChunk)}\n`);
firstChunkSent = true;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_a && !_b && (_c = stream_1.return)) yield _c.call(stream_1);
}
finally { if (e_1) throw e_1.error; }
}
if (!firstChunkSent) {
this.response.write(`${JSON.stringify({ error: 'No content streamed.' })}\n`);
}
this.response.write(`${JSON.stringify({ done: true })}\n`);
this.response.end();
});
}
transformStream(stream) {
return __asyncGenerator(this, arguments, function* transformStream_1() {
var _a, e_2, _b, _c;
try {
for (var _d = true, stream_2 = __asyncValues(stream), stream_2_1; stream_2_1 = yield __await(stream_2.next()), _a = stream_2_1.done, !_a; _d = true) {
_c = stream_2_1.value;
_d = false;
const chunk = _c;
yield yield __await({ content: chunk.content.toString() });
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (!_d && !_a && (_b = stream_2.return)) yield __await(_b.call(stream_2));
}
finally { if (e_2) throw e_2.error; }
}
});
}
splitIntoChunks(text) {
return __asyncGenerator(this, arguments, function* splitIntoChunks_1() {
let contentString = typeof text === 'string' ? text : text.content.toString();
const words = contentString.match(/\S+\s*/g) || [];
for (const word of words) {
if (!word.trim())
continue;
yield yield __await({ content: word });
}
});
}
}
exports.ChatResponse = ChatResponse;
//# sourceMappingURL=ChatResponse.js.map