diff --git a/src/lib/apis/dmr/index.ts b/src/lib/apis/dmr/index.ts
new file mode 100644
index 000000000..24dc81736
--- /dev/null
+++ b/src/lib/apis/dmr/index.ts
@@ -0,0 +1,455 @@
+import { DMR_API_BASE_URL } from '$lib/constants';
+
+export const verifyDMRConnection = async (token: string = '', connection: object = {}) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/verify`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ Authorization: `Bearer ${token}`,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ ...connection
+ })
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ error = `DMR: ${err?.error?.message ?? 'Network Problem'}`;
+ return [];
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const getDMRConfig = async (token: string = '') => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/config`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ }
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+type DMRConfig = {
+ ENABLE_DMR_API: boolean;
+ DMR_BASE_URL: string;
+ DMR_API_CONFIG: object;
+};
+
+export const updateDMRConfig = async (token: string = '', config: DMRConfig) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/config/update`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify({
+ ...config
+ })
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const getDMRUrl = async (token: string = '') => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/url`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ }
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res.DMR_BASE_URL;
+};
+
+export const updateDMRUrl = async (token: string = '', url: string) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/url/update`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify({
+ url: url
+ })
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res.DMR_BASE_URL;
+};
+
+export const getDMRVersion = async (token: string) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/api/version`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ }
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res?.version ?? '';
+};
+
+export const getDMRModels = async (token: string = '') => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/api/tags`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ }
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res?.models ?? [];
+};
+
+export const getDMRModelInfo = async (token: string, name: string) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/api/show`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify({
+ name: name
+ })
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const generateTextCompletion = async (token: string = '', model: string, text: string) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/api/generate`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify({
+ model: model,
+ prompt: text,
+ stream: false
+ })
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ error = err;
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const generateChatCompletion = async (token: string = '', body: object) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/api/chat`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify(body)
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ error = err;
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const generateEmbeddings = async (token: string = '', model: string, text: string) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/api/embeddings`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify({
+ model: model,
+ prompt: text
+ })
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ error = err;
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+// OpenAI-compatible endpoints
+export const generateOpenAIChatCompletion = async (token: string = '', body: object) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/v1/chat/completions`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify(body)
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ error = err;
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const generateOpenAICompletion = async (token: string = '', body: object) => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/v1/completions`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ },
+ body: JSON.stringify(body)
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ error = err;
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const getOpenAIModels = async (token: string = '') => {
+ let error = null;
+
+ const res = await fetch(`${DMR_API_BASE_URL}/v1/models`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ ...(token && { authorization: `Bearer ${token}` })
+ }
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .catch((err) => {
+ console.error(err);
+ if ('detail' in err) {
+ error = err.detail;
+ } else {
+ error = 'Server connection failed';
+ }
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
\ No newline at end of file
diff --git a/src/lib/components/AddConnectionModal.svelte b/src/lib/components/AddConnectionModal.svelte
index 2104d8f93..095417783 100644
--- a/src/lib/components/AddConnectionModal.svelte
+++ b/src/lib/components/AddConnectionModal.svelte
@@ -6,6 +6,7 @@
import { models } from '$lib/stores';
import { verifyOpenAIConnection } from '$lib/apis/openai';
import { verifyOllamaConnection } from '$lib/apis/ollama';
+ import { verifyDMRConnection } from '$lib/apis/dmr';
import Modal from '$lib/components/common/Modal.svelte';
import Plus from '$lib/components/icons/Plus.svelte';
@@ -23,6 +24,7 @@
export let edit = false;
export let ollama = false;
+ export let dmr = false;
export let direct = false;
export let connection = null;
@@ -64,6 +66,22 @@
}
};
+ const verifyDMRHandler = async () => {
+ // remove trailing slash from url
+ url = url.replace(/\/$/, '');
+
+ const res = await verifyDMRConnection(localStorage.token, {
+ url,
+ key
+ }).catch((error) => {
+ toast.error(`${error}`);
+ });
+
+ if (res) {
+ toast.success($i18n.t('Server connection verified'));
+ }
+ };
+
const verifyOpenAIHandler = async () => {
// remove trailing slash from url
url = url.replace(/\/$/, '');
@@ -91,6 +109,8 @@
const verifyHandler = () => {
if (ollama) {
verifyOllamaHandler();
+ } else if (dmr) {
+ verifyDMRHandler();
} else {
verifyOpenAIHandler();
}
@@ -172,7 +192,7 @@
prefixId = connection.config?.prefix_id ?? '';
modelIds = connection.config?.model_ids ?? [];
- if (ollama) {
+ if (ollama || dmr) {
connectionType = connection.config?.connection_type ?? 'local';
} else {
connectionType = connection.config?.connection_type ?? 'external';
diff --git a/src/lib/components/admin/Settings/Connections.svelte b/src/lib/components/admin/Settings/Connections.svelte
index ac0566f22..cde6ed09f 100644
--- a/src/lib/components/admin/Settings/Connections.svelte
+++ b/src/lib/components/admin/Settings/Connections.svelte
@@ -6,6 +6,7 @@
import { getOllamaConfig, updateOllamaConfig } from '$lib/apis/ollama';
import { getOpenAIConfig, updateOpenAIConfig, getOpenAIModels } from '$lib/apis/openai';
+ import { getDMRConfig, updateDMRConfig } from '$lib/apis/dmr';
import { getModels as _getModels } from '$lib/apis';
import { getDirectConnectionsConfig, setDirectConnectionsConfig } from '$lib/apis/configs';
@@ -19,6 +20,7 @@
import OpenAIConnection from './Connections/OpenAIConnection.svelte';
import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
import OllamaConnection from './Connections/OllamaConnection.svelte';
+ import DMRConnection from './Connections/DMRConnection.svelte';
const i18n = getContext('i18n');
@@ -38,14 +40,19 @@
let OPENAI_API_BASE_URLS = [''];
let OPENAI_API_CONFIGS = {};
+ let DMR_BASE_URL = '';
+ let DMR_API_CONFIG = {};
+
let ENABLE_OPENAI_API: null | boolean = null;
let ENABLE_OLLAMA_API: null | boolean = null;
+ let ENABLE_DMR_API: null | boolean = null;
let directConnectionsConfig = null;
let pipelineUrls = {};
let showAddOpenAIConnectionModal = false;
let showAddOllamaConnectionModal = false;
+ let showAddDMRConnectionModal = false;
const updateOpenAIHandler = async () => {
if (ENABLE_OPENAI_API !== null) {
@@ -104,6 +111,26 @@
}
};
+ const updateDMRHandler = async () => {
+ if (ENABLE_DMR_API !== null) {
+ // Remove trailing slash
+ DMR_BASE_URL = DMR_BASE_URL.replace(/\/$/, '');
+
+ const res = await updateDMRConfig(localStorage.token, {
+ ENABLE_DMR_API: ENABLE_DMR_API,
+ DMR_BASE_URL: DMR_BASE_URL,
+ DMR_API_CONFIG: DMR_API_CONFIG
+ }).catch((error) => {
+ toast.error(`${error}`);
+ });
+
+ if (res) {
+ toast.success($i18n.t('DMR API settings updated'));
+ await models.set(await getModels());
+ }
+ }
+ };
+
const updateDirectConnectionsHandler = async () => {
const res = await setDirectConnectionsConfig(localStorage.token, directConnectionsConfig).catch(
(error) => {
@@ -135,10 +162,21 @@
await updateOllamaHandler();
};
+ const addDMRConnectionHandler = async (connection) => {
+ DMR_BASE_URL = connection.url;
+ DMR_API_CONFIG = {
+ ...connection.config,
+ key: connection.key
+ };
+
+ await updateDMRHandler();
+ };
+
onMount(async () => {
if ($user?.role === 'admin') {
let ollamaConfig = {};
let openaiConfig = {};
+ let dmrConfig = {};
await Promise.all([
(async () => {
@@ -147,6 +185,9 @@
(async () => {
openaiConfig = await getOpenAIConfig(localStorage.token);
})(),
+ (async () => {
+ dmrConfig = await getDMRConfig(localStorage.token);
+ })(),
(async () => {
directConnectionsConfig = await getDirectConnectionsConfig(localStorage.token);
})()
@@ -154,6 +195,7 @@
ENABLE_OPENAI_API = openaiConfig.ENABLE_OPENAI_API;
ENABLE_OLLAMA_API = ollamaConfig.ENABLE_OLLAMA_API;
+ ENABLE_DMR_API = dmrConfig.ENABLE_DMR_API;
OPENAI_API_BASE_URLS = openaiConfig.OPENAI_API_BASE_URLS;
OPENAI_API_KEYS = openaiConfig.OPENAI_API_KEYS;
@@ -162,6 +204,9 @@
OLLAMA_BASE_URLS = ollamaConfig.OLLAMA_BASE_URLS;
OLLAMA_API_CONFIGS = ollamaConfig.OLLAMA_API_CONFIGS;
+ DMR_BASE_URL = dmrConfig.DMR_BASE_URL;
+ DMR_API_CONFIG = dmrConfig.DMR_API_CONFIG;
+
if (ENABLE_OPENAI_API) {
// get url and idx
for (const [idx, url] of OPENAI_API_BASE_URLS.entries()) {
@@ -196,6 +241,7 @@
const submitHandler = async () => {
updateOpenAIHandler();
updateOllamaHandler();
+ updateDMRHandler();
updateDirectConnectionsHandler();
dispatch('save');
@@ -213,9 +259,15 @@
onSubmit={addOllamaConnectionHandler}
/>
+