θΏ™ζ˜―indexlocζδΎ›ηš„ζœεŠ‘οΌŒδΈθ¦θΎ“ε…₯任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 75 additions & 32 deletions frontend/src/components/EmbeddingSelection/CohereOptions/index.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { useState, useEffect } from "react";
import System from "@/models/system";

export default function CohereEmbeddingOptions({ settings }) {
const [inputValue, setInputValue] = useState(settings?.CohereApiKey);
const [cohereApiKey, setCohereApiKey] = useState(settings?.CohereApiKey);

return (
<div className="w-full flex flex-col gap-y-4">
<div className="w-full flex items-center gap-[36px] mt-1.5">
Expand All @@ -15,41 +21,78 @@ export default function CohereEmbeddingOptions({ settings }) {
required={true}
autoComplete="off"
spellCheck={false}
onChange={(e) => setInputValue(e.target.value)}
onBlur={() => setCohereApiKey(inputValue)}
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
Model Preference
</label>
<select
name="EmbeddingModelPref"
required={true}
className="border-none bg-theme-settings-input-bg border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
>
<optgroup label="Available embedding models">
{[
"embed-english-v3.0",
"embed-multilingual-v3.0",
"embed-english-light-v3.0",
"embed-multilingual-light-v3.0",
"embed-english-v2.0",
"embed-english-light-v2.0",
"embed-multilingual-v2.0",
].map((model) => {
return (
<option
key={model}
value={model}
selected={settings?.EmbeddingModelPref === model}
>
{model}
</option>
);
})}
</optgroup>
</select>
</div>
<CohereModelSelection settings={settings} apiKey={cohereApiKey} />
</div>
</div>
);
}

function CohereModelSelection({ apiKey, settings }) {
const [models, setModels] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
async function findCustomModels() {
if (!apiKey) {
setModels([]);
setLoading(true);
return;
}

setLoading(true);
const { models } = await System.customModels(
"cohere-embedder",
typeof apiKey === "boolean" ? null : apiKey
);
setModels(models || []);
setLoading(false);
}
findCustomModels();
}, [apiKey]);

if (loading) {
return (
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
Model Preference
</label>
<select
name="EmbeddingModelPref"
disabled={true}
className="border-none bg-theme-settings-input-bg border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
>
<option disabled={true} selected={true}>
-- loading available models --
</option>
</select>
</div>
);
}

return (
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
Model Preference
</label>
<select
name="EmbeddingModelPref"
required={true}
className="border-none bg-theme-settings-input-bg border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
>
{models.map((model) => (
<option
key={model.id}
value={model.id}
selected={settings?.EmbeddingModelPref === model.id}
>
{model.name}
</option>
))}
</select>
</div>
);
}
103 changes: 77 additions & 26 deletions frontend/src/components/LLMSelection/CohereAiOptions/index.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { useState, useEffect } from "react";
import System from "@/models/system";

export default function CohereAiOptions({ settings }) {
const [inputValue, setInputValue] = useState(settings?.CohereApiKey);
const [cohereApiKey, setCohereApiKey] = useState(settings?.CohereApiKey);

return (
<div className="w-full flex flex-col">
<div className="w-full flex items-center gap-[36px] mt-1.5">
Expand All @@ -15,35 +21,80 @@ export default function CohereAiOptions({ settings }) {
required={true}
autoComplete="off"
spellCheck={false}
onChange={(e) => setInputValue(e.target.value)}
onBlur={() => setCohereApiKey(inputValue)}
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
Chat Model Selection
</label>
<select
name="CohereModelPref"
defaultValue={settings?.CohereModelPref || "command-r"}
required={true}
className="border-none bg-theme-settings-input-bg border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
>
{[
"command-r",
"command-r-plus",
"command",
"command-light",
"command-nightly",
"command-light-nightly",
].map((model) => {
return (
<option key={model} value={model}>
{model}
</option>
);
})}
</select>
</div>
{!settings?.credentialsOnly && (
<CohereModelSelection settings={settings} apiKey={cohereApiKey} />
)}
</div>
</div>
);
}

function CohereModelSelection({ apiKey, settings }) {
const [models, setModels] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
async function findCustomModels() {
if (!apiKey) {
setModels([]);
setLoading(true);
return;
}

setLoading(true);
const { models } = await System.customModels(
"cohere",
typeof apiKey === "boolean" ? null : apiKey
);
setModels(models || []);
setLoading(false);
}
findCustomModels();
}, [apiKey]);

if (loading) {
return (
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
Chat Model Selection
</label>
<select
name="CohereModelPref"
disabled={true}
className="border-none bg-theme-settings-input-bg border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
>
<option disabled={true} selected={true}>
-- loading available models --
</option>
</select>
</div>
);
}

return (
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
Chat Model Selection
</label>
<select
name="CohereModelPref"
required={true}
className="border-none bg-theme-settings-input-bg border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
>
{models.map((model) => (
<option
key={model.id}
value={model.id}
selected={settings?.CohereModelPref === model.id}
>
{model.name}
</option>
))}
</select>
</div>
);
}
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"check-disk-space": "^3.4.0",
"cheerio": "^1.0.0",
"chromadb": "^2.0.1",
"cohere-ai": "^7.9.5",
"cohere-ai": "^7.19.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"elevenlabs": "^0.5.0",
Expand Down
30 changes: 10 additions & 20 deletions server/utils/AiProviders/cohere/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {

class CohereLLM {
constructor(embedder = null) {
this.className = "CohereLLM";
const { CohereClient } = require("cohere-ai");
if (!process.env.COHERE_API_KEY)
throw new Error("No Cohere API key was set.");
Expand All @@ -25,6 +26,13 @@ class CohereLLM {
};

this.embedder = embedder ?? new NativeEmbedder();
this.#log(
`Initialized with model ${this.model}. ctx: ${this.promptWindowLimit()}`
);
}

#log(text, ...args) {
console.log(`\x1b[32m[${this.className}]\x1b[0m ${text}`, ...args);
}

#appendContext(contextTexts = []) {
Expand Down Expand Up @@ -70,16 +78,8 @@ class CohereLLM {
return MODEL_MAP.get("cohere", this.model) ?? 4_096;
}

async isValidChatCompletionModel(model = "") {
const validModels = [
"command-r",
"command-r-plus",
"command",
"command-light",
"command-nightly",
"command-light-nightly",
];
return validModels.includes(model);
async isValidChatCompletionModel() {
return true;
}

constructPrompt({
Expand All @@ -96,11 +96,6 @@ class CohereLLM {
}

async getChatCompletion(messages = null, { temperature = 0.7 }) {
if (!(await this.isValidChatCompletionModel(this.model)))
throw new Error(
`Cohere chat: ${this.model} is not valid for chat completion!`
);

const message = messages[messages.length - 1].content; // Get the last message
const cohereHistory = this.#convertChatHistoryCohere(messages.slice(0, -1)); // Remove the last message and convert to Cohere

Expand Down Expand Up @@ -134,11 +129,6 @@ class CohereLLM {
}

async streamGetChatCompletion(messages = null, { temperature = 0.7 }) {
if (!(await this.isValidChatCompletionModel(this.model)))
throw new Error(
`Cohere chat: ${this.model} is not valid for chat completion!`
);

const message = messages[messages.length - 1].content; // Get the last message
const cohereHistory = this.#convertChatHistoryCohere(messages.slice(0, -1)); // Remove the last message and convert to Cohere
const measuredStreamRequest = await LLMPerformanceMonitor.measureStream(
Expand Down
12 changes: 12 additions & 0 deletions server/utils/AiProviders/modelMap/legacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ const LEGACY_MODEL_MAP = {
"command-light": 4096,
"command-nightly": 8192,
"command-light-nightly": 8192,
"command-r-plus-08-2024": 132096,
"command-a-03-2025": 288000,
"c4ai-aya-vision-32b": 16384,
"command-a-reasoning-08-2025": 288768,
"command-r-08-2024": 132096,
"c4ai-aya-vision-8b": 16384,
"command-r7b-12-2024": 132000,
"command-r7b-arabic-02-2025": 128000,
"command-a-vision-07-2025": 128000,
"c4ai-aya-expanse-8b": 8192,
"c4ai-aya-expanse-32b": 128000,
"command-a-translate-08-2025": 8992,
},
gemini: {
"gemini-1.5-pro-001": 2000000,
Expand Down
39 changes: 39 additions & 0 deletions server/utils/helpers/customModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ const SUPPORT_CUSTOM_MODELS = [
"dpais",
"moonshotai",
"foundry",
"cohere",
// Embedding Engines
"native-embedder",
"cohere-embedder",
];

async function getCustomModels(provider = "", apiKey = null, basePath = null) {
Expand Down Expand Up @@ -96,8 +98,12 @@ async function getCustomModels(provider = "", apiKey = null, basePath = null) {
return await getMoonshotAiModels(apiKey);
case "foundry":
return await getFoundryModels(basePath);
case "cohere":
return await getCohereModels(apiKey, "chat");
case "native-embedder":
return await getNativeEmbedderModels();
case "cohere-embedder":
return await getCohereModels(apiKey, "embed");
default:
return { models: [], error: "Invalid provider for custom models" };
}
Expand Down Expand Up @@ -759,6 +765,39 @@ async function getFoundryModels(basePath = null) {
}
}

/**
* Get Cohere models
* @param {string} _apiKey - The API key to use
* @param {'chat' | 'embed'} type - The type of model to get
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
*/
async function getCohereModels(_apiKey = null, type = "chat") {
const apiKey =
_apiKey === true
? process.env.COHERE_API_KEY
: _apiKey || process.env.COHERE_API_KEY || null;

const { CohereClient } = require("cohere-ai");
const cohere = new CohereClient({
token: apiKey,
});
const models = await cohere.models
.list({ pageSize: 1000, endpoint: type })
.then((results) => results.models)
.then((models) =>
models.map((model) => ({
id: model.id,
name: model.name,
}))
)
.catch((e) => {
console.error(`Cohere:listModels`, e.message);
return [];
});

return { models, error: null };
}

module.exports = {
getCustomModels,
SUPPORT_CUSTOM_MODELS,
Expand Down
Loading