SambaNova Integration (#4943)

* SambaNova Integration

* lint
This commit is contained in:
Timothy Carambat
2026-01-29 18:48:22 -08:00
committed by GitHub
parent 392bf33770
commit 0032c4da22
26 changed files with 623 additions and 25 deletions

View File

@@ -87,7 +87,7 @@ AnythingLLM divides your documents into objects called `workspaces`. A Workspace
- [LM Studio (all models)](https://lmstudio.ai)
- [LocalAI (all models)](https://localai.io/)
- [Together AI (chat models)](https://www.together.ai/)
- [Fireworks AI (chat models)](https://fireworks.ai/)
- [Fireworks AI (chat models)](https://fireworks.ai/)
- [Perplexity (chat models)](https://www.perplexity.ai/)
- [OpenRouter (chat models)](https://openrouter.ai/)
- [DeepSeek (chat models)](https://deepseek.com/)
@@ -107,6 +107,8 @@ AnythingLLM divides your documents into objects called `workspaces`. A Workspace
- [Microsoft Foundry Local](https://github.com/microsoft/Foundry-Local)
- [CometAPI (chat models)](https://api.cometapi.com/)
- [Docker Model Runner](https://docs.docker.com/ai/model-runner/)
- [PrivateModeAI (chat models)](https://privatemode.ai/)
- [SambaNova Cloud (chat models)](https://cloud.sambanova.ai/)
**Embedder models:**
@@ -165,8 +167,8 @@ Mintplex Labs & the community maintain a number of deployment methods, scripts,
|----------------------------------------|----|-----|---------------|------------|
| [![Deploy on Docker][docker-btn]][docker-deploy] | [![Deploy on AWS][aws-btn]][aws-deploy] | [![Deploy on GCP][gcp-btn]][gcp-deploy] | [![Deploy on DigitalOcean][do-btn]][do-deploy] | [![Deploy on Render.com][render-btn]][render-deploy] |
| Railway | RepoCloud | Elestio | Northflank |
| --- | --- | --- | --- |
| Railway | RepoCloud | Elestio | Northflank |
| --------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------ |
| [![Deploy on Railway][railway-btn]][railway-deploy] | [![Deploy on RepoCloud][repocloud-btn]][repocloud-deploy] | [![Deploy on Elestio][elestio-btn]][elestio-deploy] | [![Deploy on Northflank][northflank-btn]][northflank-deploy] |
[or set up a production AnythingLLM instance without Docker →](./BARE_METAL.md)
@@ -224,7 +226,7 @@ You can verify these claims by finding all locations `Telemetry.sendTelemetry` i
We take privacy very seriously, and we hope you understand that we want to learn how our tool is used, without using annoying popup surveys, so we can build something worth using. The anonymous data is _never_ shared with third parties, ever.
[View all telemetry events in source code](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry\(&type=code)
[View all telemetry events in source code](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry(&type=code)
</details>

View File

@@ -171,6 +171,10 @@ GID='1000'
# PRIVATEMODE_LLM_BASE_PATH='http://127.0.0.1:8080'
# PRIVATEMODE_LLM_MODEL_PREF='gemma-3-27b'
# LLM_PROVIDER='sambanova'
# SAMBANOVA_LLM_API_KEY='xxx-xxx-xxx'
# SAMBANOVA_LLM_MODEL_PREF='gpt-oss-120b'
###########################################
######## Embedding API SElECTION ##########
###########################################

View File

@@ -0,0 +1,103 @@
import System from "@/models/system";
import { useState, useEffect } from "react";
export default function SambaNovaOptions({ settings }) {
const [inputValue, setInputValue] = useState(settings?.SambaNovaLLMApiKey);
const [apiKey, setApiKey] = useState(settings?.SambaNovaLLMApiKey);
return (
<div className="flex gap-[36px] mt-1.5">
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
SambaNova API Key
</label>
<input
type="password"
name="SambaNovaLLMApiKey"
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="SambaNova AI API Key"
defaultValue={settings?.SambaNovaLLMApiKey ? "*".repeat(20) : ""}
required={true}
autoComplete="off"
spellCheck={false}
onChange={(e) => setInputValue(e.target.value)}
onBlur={() => setApiKey(inputValue)}
/>
</div>
{!settings?.credentialsOnly && (
<SambaNovaModelSelection settings={settings} apiKey={apiKey} />
)}
</div>
);
}
function SambaNovaModelSelection({ settings, apiKey }) {
const [groupedModels, setGroupedModels] = useState({});
const [loading, setLoading] = useState(true);
useEffect(() => {
async function findCustomModels() {
setLoading(true);
const { models } = await System.customModels("sambanova");
if (models?.length > 0) {
const modelsByOrganization = models.reduce((acc, model) => {
acc[model.organization] = acc[model.organization] || [];
acc[model.organization].push(model);
return acc;
}, {});
setGroupedModels(modelsByOrganization);
}
setLoading(false);
}
findCustomModels();
}, []);
if (loading || Object.keys(groupedModels).length === 0) {
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="SambaNovaLLMModelPref"
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="SambaNovaLLMModelPref"
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"
>
{Object.keys(groupedModels)
.sort()
.map((organization) => (
<optgroup key={organization} label={organization}>
{groupedModels[organization].map((model) => (
<option
key={model.id}
value={model.id}
selected={settings?.SambaNovaLLMModelPref === model.id}
>
{model.name}
</option>
))}
</optgroup>
))}
</select>
</div>
);
}

View File

@@ -43,6 +43,7 @@ import FoundryLogo from "@/media/llmprovider/foundry-local.png";
import GiteeAILogo from "@/media/llmprovider/giteeai.png";
import DockerModelRunnerLogo from "@/media/llmprovider/docker-model-runner.png";
import PrivateModeLogo from "@/media/llmprovider/privatemode.png";
import SambaNovaLogo from "@/media/llmprovider/sambanova.png";
const LLM_PROVIDER_PRIVACY_MAP = {
openai: {
@@ -238,6 +239,11 @@ const LLM_PROVIDER_PRIVACY_MAP = {
policyUrl: "https://docs.privatemode.ai/getting-started/faq#q2",
logo: PrivateModeLogo,
},
sambanova: {
name: "SambaNova",
policyUrl: "https://sambanova.ai/privacy-policy",
logo: SambaNovaLogo,
},
};
const VECTOR_DB_PROVIDER_PRIVACY_MAP = {

View File

@@ -53,6 +53,7 @@ const groupedProviders = [
"openrouter",
"ppio",
"docker-model-runner",
"sambanova",
];
export default function useGetProviderModels(provider = null) {
const [defaultModels, setDefaultModels] = useState([]);

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -39,6 +39,7 @@ import FoundryLogo from "@/media/llmprovider/foundry-local.png";
import GiteeAILogo from "@/media/llmprovider/giteeai.png";
import DockerModelRunnerLogo from "@/media/llmprovider/docker-model-runner.png";
import PrivateModeLogo from "@/media/llmprovider/privatemode.png";
import SambaNovaLogo from "@/media/llmprovider/sambanova.png";
import PreLoader from "@/components/Preloader";
import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions";
@@ -75,6 +76,7 @@ import FoundryOptions from "@/components/LLMSelection/FoundryOptions";
import GiteeAIOptions from "@/components/LLMSelection/GiteeAIOptions/index.jsx";
import DockerModelRunnerOptions from "@/components/LLMSelection/DockerModelRunnerOptions";
import PrivateModeOptions from "@/components/LLMSelection/PrivateModeOptions";
import SambaNovaOptions from "@/components/LLMSelection/SambaNovaOptions";
import LLMItem from "@/components/LLMSelection/LLMItem";
import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react";
@@ -177,6 +179,14 @@ export const AVAILABLE_LLM_PROVIDERS = [
"DockerModelRunnerModelTokenLimit",
],
},
{
name: "SambaNova",
value: "sambanova",
logo: SambaNovaLogo,
options: (settings) => <SambaNovaOptions settings={settings} />,
description: "Run open source models from SambaNova.",
requiredConfig: ["SambaNovaLLMApiKey"],
},
{
name: "Local AI",
value: "localai",
@@ -193,6 +203,7 @@ export const AVAILABLE_LLM_PROVIDERS = [
description: "Run open source models from Together AI.",
requiredConfig: ["TogetherAiApiKey"],
},
{
name: "Fireworks AI",
value: "fireworksai",

View File

@@ -33,6 +33,7 @@ import CometApiLogo from "@/media/llmprovider/cometapi.png";
import GiteeAILogo from "@/media/llmprovider/giteeai.png";
import DockerModelRunnerLogo from "@/media/llmprovider/docker-model-runner.png";
import PrivateModeLogo from "@/media/llmprovider/privatemode.png";
import SambaNovaLogo from "@/media/llmprovider/sambanova.png";
import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions";
import GenericOpenAiOptions from "@/components/LLMSelection/GenericOpenAiOptions";
@@ -67,6 +68,7 @@ import CometApiLLMOptions from "@/components/LLMSelection/CometApiLLMOptions";
import GiteeAiOptions from "@/components/LLMSelection/GiteeAIOptions";
import DockerModelRunnerOptions from "@/components/LLMSelection/DockerModelRunnerOptions";
import PrivateModeOptions from "@/components/LLMSelection/PrivateModeOptions";
import SambaNovaOptions from "@/components/LLMSelection/SambaNovaOptions";
import LLMItem from "@/components/LLMSelection/LLMItem";
import System from "@/models/system";
@@ -157,6 +159,13 @@ const LLMS = [
options: (settings) => <LocalAiOptions settings={settings} />,
description: "Run LLMs locally on your own machine.",
},
{
name: "SambaNova",
value: "sambanova",
logo: SambaNovaLogo,
options: (settings) => <SambaNovaOptions settings={settings} />,
description: "Run open source models from SambaNova.",
},
{
name: "Novita AI",
value: "novita",

View File

@@ -39,6 +39,7 @@ const ENABLED_PROVIDERS = [
"cohere",
"docker-model-runner",
"privatemode",
"sambanova",
// TODO: More agent support.
// "huggingface" // Can be done but already has issues with no-chat templated. Needs to be tested.
];

View File

@@ -55,6 +55,7 @@
AnythingLLM یک اپلیکیشن کامل است که در آن می‌توانید از LLMهای تجاری آماده یا LLMهای متن‌باز محبوب و راه‌حل‌های vectorDB برای ساخت یک ChatGPT خصوصی بدون محدودیت استفاده کنید که می‌توانید آن را به صورت محلی اجرا کنید یا از راه دور میزبانی کنید و با هر سندی که به آن ارائه می‌دهید، هوشمندانه گفتگو کنید.
AnythingLLM اسناد شما را به اشیایی به نام `workspaces` تقسیم می‌کند. یک Workspace مانند یک رشته عمل می‌کند، اما با اضافه شدن کانتینرسازی اسناد شما. Workspaceها می‌توانند اسناد را به اشتراک بگذارند، اما با یکدیگر ارتباط برقرار نمی‌کنند تا بتوانید زمینه هر workspace را تمیز نگه دارید.
</div>
<div dir="rtl">
@@ -90,7 +91,7 @@ AnythingLLM اسناد شما را به اشیایی به نام `workspaces` ت
- [LM Studio (all models)](https://lmstudio.ai)
- [LocalAi (all models)](https://localai.io/)
- [Together AI (chat models)](https://www.together.ai/)
- [Fireworks AI (chat models)](https://fireworks.ai/)
- [Fireworks AI (chat models)](https://fireworks.ai/)
- [Perplexity (chat models)](https://www.perplexity.ai/)
- [OpenRouter (chat models)](https://openrouter.ai/)
- [DeepSeek (chat models)](https://deepseek.com/)
@@ -106,6 +107,8 @@ AnythingLLM اسناد شما را به اشیایی به نام `workspaces` ت
- [Novita AI (chat models)](https://novita.ai/model-api/product/llm-api?utm_source=github_anything-llm&utm_medium=github_readme&utm_campaign=link)
- [PPIO](https://ppinfra.com?utm_source=github_anything-llm)
- [Docker Model Runner](https://docs.docker.com/ai/model-runner/)
- [PrivateModeAI (chat models)](https://privatemode.ai/)
- [SambaNova Cloud (chat models)](https://cloud.sambanova.ai/)
<div dir="rtl">
@@ -166,14 +169,15 @@ AnythingLLM اسناد شما را به اشیایی به نام `workspaces` ت
<div dir="rtl">
Mintplex Labs و جامعه کاربران، روش‌ها، اسکریپت‌ها و قالب‌های متعددی را برای اجرای AnythingLLM به صورت محلی نگهداری می‌کنند. برای مطالعه نحوه استقرار در محیط مورد نظر خود یا استقرار خودکار، به جدول زیر مراجعه کنید.
</div>
| Docker | AWS | GCP | Digital Ocean | Render.com |
|----------------------------------------|----|-----|---------------|------------|
| Docker | AWS | GCP | Digital Ocean | Render.com |
| ------------------------------------------------ | --------------------------------------- | --------------------------------------- | ---------------------------------------------- | ---------------------------------------------------- |
| [![Deploy on Docker][docker-btn]][docker-deploy] | [![Deploy on AWS][aws-btn]][aws-deploy] | [![Deploy on GCP][gcp-btn]][gcp-deploy] | [![Deploy on DigitalOcean][do-btn]][do-deploy] | [![Deploy on Render.com][render-btn]][render-deploy] |
| Railway | RepoCloud | Elestio |
| --- | --- | --- |
| Railway | RepoCloud | Elestio |
| --------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------- |
| [![Deploy on Railway][railway-btn]][railway-deploy] | [![Deploy on RepoCloud][repocloud-btn]][repocloud-deploy] | [![Deploy on Elestio][elestio-btn]][elestio-deploy] |
<div dir="rtl">
@@ -224,7 +228,8 @@ AnythingLLM توسط Mintplex Labs Inc دارای ویژگی تله‌متری
می‌توانید این ادعاها را با پیدا کردن تمام مکان‌هایی که `Telemetry.sendTelemetry` فراخوانی می‌شود، تأیید کنید. ارائه‌دهنده تله‌متری [PostHog](https://posthog.com/) است.
[مشاهده همه رویدادهای تله‌متری در کد منبع](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry\(&type=code)
[مشاهده همه رویدادهای تله‌متری در کد منبع](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry(&type=code)
</div>
</details>
@@ -259,10 +264,12 @@ AnythingLLM توسط Mintplex Labs Inc دارای ویژگی تله‌متری
</div>
---
<div dir="ltr" align="left">
Copyright © 2025 [Mintplex Labs][profile-link]. <br />
This project is [MIT](../LICENSE) licensed.
</div>
<!-- LINK GROUP -->

View File

@@ -95,6 +95,8 @@ AnythingLLMは、ドキュメントを`ワークスペース`と呼ばれるオ
- [PPIO](https://ppinfra.com?utm_source=github_anything-llm)
- [CometAPI (チャットモデル)](https://api.cometapi.com/)
- [Docker Model Runner](https://docs.docker.com/ai/model-runner/)
- [PrivateModeAI (chat models)](https://privatemode.ai/)
- [SambaNova Cloud (chat models)](https://cloud.sambanova.ai/)
**埋め込みモデル:**
@@ -150,8 +152,8 @@ Mintplex Labsおよびコミュニティは、AnythingLLMをローカルで実
|----------------------------------------|----|-----|---------------|------------|
| [![Docker上でデプロイ][docker-btn]][docker-deploy] | [![AWS上でデプロイ][aws-btn]][aws-deploy] | [![GCP上でデプロイ][gcp-btn]][gcp-deploy] | [![DigitalOcean上でデプロイ][do-btn]][do-deploy] | [![Render.com上でデプロイ][render-btn]][render-deploy] |
| Railway |
| --------------------------------------------------- |
| Railway |
| ----------------------------------------------------- |
| [![Railway上でデプロイ][railway-btn]][railway-deploy] |
[Dockerを使用せずに本番環境のAnythingLLMインスタンスを設定する →](../BARE_METAL.md)
@@ -201,7 +203,7 @@ Mintplex Labs Inc.によって開発されたAnythingLLMには、匿名の使用
これらの主張を検証するには、`Telemetry.sendTelemetry`が呼び出されるすべての場所を見つけてください。また、これらのイベントは出力ログに書き込まれるため、送信された具体的なデータも確認できます。IPアドレスやその他の識別情報は収集されません。テレメトリープロバイダーは[PostHog](https://posthog.com/)です。
[ソースコード内のすべてのテレメトリーイベントを表示](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry\(&type=code)
[ソースコード内のすべてのテレメトリーイベントを表示](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry(&type=code)
</details>

View File

@@ -32,7 +32,6 @@ Belgelerinizle sohbet edin, yapay zeka ajanlarını kullanın, son derece özell
<b>English</b> · <a href='./locales/README.zh-CN.md'>简体中文</a> · <a href='./locales/README.ja-JP.md'>日本語</a> · <a href='./locales/README.tr-TR.md'>Turkish</a>
</p>
<p align="center">
👉 Masaüstü için AnythingLLM (Mac, Windows ve Linux)! <a href="https://anythingllm.com/download" target="_blank"> Şimdi İndir</a>
</p>
@@ -87,7 +86,7 @@ AnythingLLM, belgelerinizi **"çalışma alanları" (workspaces)** adı verilen
- [LM Studio (all models)](https://lmstudio.ai)
- [LocalAi (all models)](https://localai.io/)
- [Together AI (chat models)](https://www.together.ai/)
- [Fireworks AI (chat models)](https://fireworks.ai/)
- [Fireworks AI (chat models)](https://fireworks.ai/)
- [Perplexity (chat models)](https://www.perplexity.ai/)
- [OpenRouter (chat models)](https://openrouter.ai/)
- [DeepSeek (chat models)](https://deepseek.com/)
@@ -103,6 +102,8 @@ AnythingLLM, belgelerinizi **"çalışma alanları" (workspaces)** adı verilen
- [Novita AI (chat models)](https://novita.ai/model-api/product/llm-api?utm_source=github_anything-llm&utm_medium=github_readme&utm_campaign=link)
- [PPIO](https://ppinfra.com?utm_source=github_anything-llm)
- [Docker Model Runner](https://docs.docker.com/ai/model-runner/)
- [PrivateModeAI (chat models)](https://privatemode.ai/)
- [SambaNova Cloud (chat models)](https://cloud.sambanova.ai/)
**Embedder modelleri:**
@@ -161,8 +162,8 @@ Mintplex Labs ve topluluk, AnythingLLM'i yerel olarak çalıştırmak için çe
|----------------------------------------|----|-----|---------------|------------|
| [![Deploy on Docker][docker-btn]][docker-deploy] | [![Deploy on AWS][aws-btn]][aws-deploy] | [![Deploy on GCP][gcp-btn]][gcp-deploy] | [![Deploy on DigitalOcean][do-btn]][do-deploy] | [![Deploy on Render.com][render-btn]][render-deploy] |
| Railway | RepoCloud | Elestio |
| --- | --- | --- |
| Railway | RepoCloud | Elestio |
| --------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------- |
| [![Deploy on Railway][railway-btn]][railway-deploy] | [![Deploy on RepoCloud][repocloud-btn]][repocloud-deploy] | [![Deploy on Elestio][elestio-btn]][elestio-deploy] |
[veya Docker kullanmadan üretim ortamında AnythingLLM kurun →](../BARE_METAL.md)
@@ -214,11 +215,10 @@ Yalnızca ürün ve yol haritası kararlarını almamıza yardımcı olacak kull
Bu verileri doğrulamak için kod içinde **`Telemetry.sendTelemetry` çağrılarını** inceleyebilirsiniz. Ayrıca, bu olaylar günlük kaydına yazıldığı için hangi verilerin gönderildiğini görebilirsiniz (eğer etkinleştirilmişse). **IP adresi veya diğer tanımlayıcı bilgiler toplanmaz.** Telemetri sağlayıcısı, açık kaynaklı bir telemetri toplama hizmeti olan [PostHog](https://posthog.com/)dur.
[Kaynak kodda tüm telemetri olaylarını görüntüle](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry\(&type=code)
[Kaynak kodda tüm telemetri olaylarını görüntüle](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry(&type=code)
</details>
## 👋 Katkıda Bulunma
- Bir **issue** oluşturun.

View File

@@ -54,6 +54,7 @@ AnythingLLM是一个全栈应用程序您可以使用现成的商业大语言
AnythingLLM将您的文档划分为称为`workspaces` (工作区)的对象。工作区的功能类似于线程,同时增加了文档的容器化。工作区可以共享文档,但工作区之间的内容不会互相干扰或污染,因此您可以保持每个工作区的上下文清晰。
## AnythingLLM的一些酷炫特性
- 🆕 [**完全兼容 MCP**](https://docs.anythingllm.com/mcp-compatibility/overview)
- 🆕 [**无代码AI代理构建器**](https://docs.anythingllm.com/agent-flows/overview)
- 🖼️ **多用户实例支持和权限管理支持封闭源和开源LLM**
@@ -103,6 +104,8 @@ AnythingLLM将您的文档划分为称为`workspaces` (工作区)的对象。工
- [PPIO (聊天模型)](https://ppinfra.com?utm_source=github_anything-llm)
- [CometAPI (聊天模型)](https://api.cometapi.com/)
- [Docker Model Runner](https://docs.docker.com/ai/model-runner/)
- [PrivateModeAI (chat models)](https://privatemode.ai/)
- [SambaNova Cloud (chat models)](https://cloud.sambanova.ai/)
**支持的嵌入模型:**
@@ -161,8 +164,8 @@ Mintplex Labs和社区维护了许多部署方法、脚本和模板您可以
|----------------------------------------|----|-----|---------------|------------|
| [![在 Docker 上部署][docker-btn]][docker-deploy] | [![在 AWS 上部署][aws-btn]][aws-deploy] | [![在 GCP 上部署][gcp-btn]][gcp-deploy] | [![在DigitalOcean上部署][do-btn]][do-deploy] | [![在 Render.com 上部署][render-btn]][render-deploy] |
| Railway | RepoCloud | Elestio |
| --- | --- | --- |
| Railway | RepoCloud | Elestio |
| --------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------- |
| [![在 Railway 上部署][railway-btn]][railway-deploy] | [![在 RepoCloud 上部署][repocloud-btn]][repocloud-deploy] | [![在 Elestio 上部署][elestio-btn]][elestio-deploy] |
[其他方案不使用Docker配置AnythingLLM实例 →](../BARE_METAL.md)
@@ -194,9 +197,6 @@ _以下是一些与 AnythingLLM 兼容的应用程序,但并非由 Mintplex La
<details>
<summary><kbd>有关 AnythingLLM 的远程信息收集与隐私保护更多信息</kbd></summary>
### 为什么收集信息?
我们使用这些信息来帮助我们理解 AnythingLLM 的使用情况,帮助我们确定新功能和错误修复的优先级,并帮助我们提高 AnythingLLM 的性能和稳定性。
@@ -219,7 +219,7 @@ _以下是一些与 AnythingLLM 兼容的应用程序,但并非由 Mintplex La
我们非常重视隐私,且不用烦人的弹窗问卷来获取反馈,希望你能理解为什么我们想要知道该工具的使用情况,这样我们才能打造真正值得使用的产品。所有匿名数据 _绝不会_ 与任何第三方共享。
[在源代码中查看所有信息收集活动](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry\(&type=code)
[在源代码中查看所有信息收集活动](https://github.com/search?q=repo%3AMintplex-Labs%2Fanything-llm%20.sendTelemetry(&type=code)
</details>

View File

@@ -170,6 +170,10 @@ SIG_SALT='salt' # Please generate random string at least 32 chars long.
# PRIVATEMODE_LLM_BASE_PATH='http://127.0.0.1:8080'
# PRIVATEMODE_LLM_MODEL_PREF='gemma-3-27b'
# LLM_PROVIDER='sambanova'
# SAMBANOVA_LLM_API_KEY='xxx-xxx-xxx'
# SAMBANOVA_LLM_MODEL_PREF='gpt-oss-120b'
###########################################
######## Embedding API SElECTION ##########
###########################################

View File

@@ -165,6 +165,9 @@ function getModelTag() {
case "privatemode":
model = process.env.PRIVATEMODE_LLM_MODEL_PREF;
break;
case "sambanova":
model = process.env.SAMBANOVA_LLM_MODEL_PREF;
break;
default:
model = "--";
break;

View File

@@ -681,6 +681,10 @@ const SystemSettings = {
// Privatemode Keys
PrivateModeBasePath: process.env.PRIVATEMODE_LLM_BASE_PATH,
PrivateModeModelPref: process.env.PRIVATEMODE_LLM_MODEL_PREF,
// SambaNova Keys
SambaNovaLLMApiKey: !!process.env.SAMBANOVA_LLM_API_KEY,
SambaNovaLLMModelPref: process.env.SAMBANOVA_LLM_MODEL_PREF,
};
},

View File

@@ -20,6 +20,7 @@ class ContextWindowFinder {
deepseek: "deepseek",
moonshot: "moonshot",
zai: "vercel_ai_gateway", // Vercel has correct context windows for Z.AI models
sambanova: "sambanova",
};
static expiryMs = 1000 * 60 * 60 * 24 * 3; // 3 days
static remoteUrl =

View File

@@ -0,0 +1,268 @@
const { NativeEmbedder } = require("../../EmbeddingEngines/native");
const {
LLMPerformanceMonitor,
} = require("../../helpers/chat/LLMPerformanceMonitor");
const { v4: uuidv4 } = require("uuid");
const { writeResponseChunk } = require("../../helpers/chat/responses");
const { MODEL_MAP } = require("../modelMap");
class SambaNovaLLM {
constructor(embedder = null, modelPreference = null) {
if (!process.env.SAMBANOVA_LLM_API_KEY)
throw new Error("No SambaNova API key was set.");
this.className = "SambaNovaLLM";
const { OpenAI: OpenAIApi } = require("openai");
this.openai = new OpenAIApi({
baseURL: "https://api.sambanova.ai/v1",
apiKey: process.env.SAMBANOVA_LLM_API_KEY,
});
this.model = modelPreference || process.env.SAMBANOVA_LLM_MODEL_PREF;
this.limits = {
history: this.promptWindowLimit() * 0.15,
system: this.promptWindowLimit() * 0.15,
user: this.promptWindowLimit() * 0.7,
};
this.embedder = embedder ?? new NativeEmbedder();
this.defaultTemp = 0.7;
this.log(
`Initialized ${this.model} with context window ${this.promptWindowLimit()}`
);
}
log(text, ...args) {
console.log(`\x1b[36m[${this.className}]\x1b[0m ${text}`, ...args);
}
#appendContext(contextTexts = []) {
if (!contextTexts || !contextTexts.length) return "";
return (
"\nContext:\n" +
contextTexts
.map((text, i) => {
return `[CONTEXT ${i}]:\n${text}\n[END CONTEXT ${i}]\n\n`;
})
.join("")
);
}
streamingEnabled() {
return "streamGetChatCompletion" in this;
}
static promptWindowLimit(modelName) {
return MODEL_MAP.get("sambanova", modelName) ?? 131072;
}
promptWindowLimit() {
return MODEL_MAP.get("sambanova", this.model) ?? 131072;
}
async isValidChatCompletionModel(modelName = "") {
return !!modelName; // name just needs to exist
}
/**
* Generates appropriate content array for a message + attachments.
* @param {{userPrompt:string, attachments: import("../../helpers").Attachment[]}}
* @returns {string|object[]}
*/
#generateContent({ userPrompt, attachments = [] }) {
if (!attachments.length) return userPrompt;
const content = [{ type: "text", text: userPrompt }];
for (let attachment of attachments) {
content.push({
type: "image_url",
image_url: {
url: attachment.contentString,
},
});
}
return content.flat();
}
/**
* Construct the user prompt for this model.
* @param {{attachments: import("../../helpers").Attachment[]}} param0
* @returns
*/
constructPrompt({
systemPrompt = "",
contextTexts = [],
chatHistory = [],
userPrompt = "",
attachments = [],
}) {
const prompt = {
role: "system",
content: `${systemPrompt}${this.#appendContext(contextTexts)}`,
};
return [
prompt,
...chatHistory,
{
role: "user",
content: this.#generateContent({ userPrompt, attachments }),
},
];
}
async getChatCompletion(messages = null, { temperature = 0.7 }) {
const result = await LLMPerformanceMonitor.measureAsyncFunction(
this.openai.chat.completions
.create({
model: this.model,
messages,
temperature,
})
.catch((e) => {
throw new Error(e.message);
})
);
if (
!result.output.hasOwnProperty("choices") ||
result.output.choices.length === 0
)
return null;
return {
textResponse: result.output.choices[0].message.content,
metrics: {
prompt_tokens: result.output.usage?.prompt_tokens || 0,
completion_tokens: result.output.usage?.completion_tokens || 0,
total_tokens: result.output.usage?.total_tokens || 0,
outputTps: result.output.usage?.total_tokens_per_sec || 0,
duration: result.duration,
model: this.model,
timestamp: new Date(),
},
};
}
async streamGetChatCompletion(messages = null, { temperature = 0.7 }) {
const measuredStreamRequest = await LLMPerformanceMonitor.measureStream({
func: this.openai.chat.completions.create({
model: this.model,
stream: true,
messages,
temperature,
stream_options: {
include_usage: true,
},
}),
messages,
runPromptTokenCalculation: false,
modelTag: this.model,
});
return measuredStreamRequest;
}
handleStream(response, stream, responseProps) {
const { uuid = uuidv4(), sources = [] } = responseProps;
let hasUsageMetrics = false;
let usage = {
prompt_tokens: 0,
total_tokens: 0,
outputTps: 0,
completion_tokens: 0,
};
return new Promise(async (resolve) => {
let fullText = "";
const handleAbort = () => {
stream?.endMeasurement(usage);
clientAbortedHandler(resolve, fullText);
};
response.on("close", handleAbort);
try {
for await (const chunk of stream) {
const message = chunk?.choices?.[0];
const token = message?.delta?.content;
if (
chunk.hasOwnProperty("usage") && // exists
!!chunk.usage &&
Object.values(chunk.usage).length > 0
) {
if (chunk.usage.hasOwnProperty("prompt_tokens"))
usage.prompt_tokens = Number(chunk.usage.prompt_tokens);
if (chunk.usage.hasOwnProperty("completion_tokens"))
usage.completion_tokens = Number(chunk.usage.completion_tokens);
if (chunk.usage.hasOwnProperty("total_tokens"))
usage.total_tokens = Number(chunk.usage.total_tokens);
if (chunk.usage.hasOwnProperty("total_tokens_per_sec"))
usage.outputTps = Number(chunk.usage.total_tokens_per_sec);
hasUsageMetrics = true;
}
if (token) {
fullText += token;
if (!hasUsageMetrics) usage.completion_tokens++;
writeResponseChunk(response, {
uuid,
sources: [],
type: "textResponseChunk",
textResponse: token,
close: false,
error: false,
});
}
if (
message?.hasOwnProperty("finish_reason") &&
message.finish_reason !== "" &&
message.finish_reason !== null
) {
writeResponseChunk(response, {
uuid,
sources,
type: "textResponseChunk",
textResponse: "",
close: true,
error: false,
});
}
}
response.removeListener("close", handleAbort);
stream?.endMeasurement(usage);
resolve(fullText);
} catch (e) {
this.log(`\x1b[43m\x1b[34m[STREAMING ERROR]\x1b[0m ${e.message}`);
writeResponseChunk(response, {
uuid,
type: "abort",
textResponse: null,
sources: [],
close: true,
error: e.message,
});
stream?.endMeasurement(usage);
resolve(fullText);
}
});
}
// Simple wrapper for dynamic embedder & normalize interface for all LLM implementations
async embedTextInput(textInput) {
return await this.embedder.embedTextInput(textInput);
}
async embedChunks(textChunks = []) {
return await this.embedder.embedChunks(textChunks);
}
async compressMessages(promptArgs = {}, rawHistory = []) {
const { messageArrayCompressor } = require("../../helpers/chat");
const messageArray = this.constructPrompt(promptArgs);
return await messageArrayCompressor(this, messageArray, rawHistory);
}
}
module.exports = {
SambaNovaLLM,
};

View File

@@ -996,6 +996,8 @@ ${this.getHistory({ to: route.to })
return new Providers.DockerModelRunnerProvider({ model: config.model });
case "privatemode":
return new Providers.PrivatemodeProvider({ model: config.model });
case "sambanova":
return new Providers.SambaNovaProvider({ model: config.model });
default:
throw new Error(
`Unknown provider: ${config.provider}. Please use a valid provider.`

View File

@@ -257,6 +257,14 @@ class Provider {
apiKey: null,
...config,
});
case "sambanova":
return new ChatOpenAI({
configuration: {
baseURL: "https://api.sambanova.ai/v1",
},
apiKey: process.env.SAMBANOVA_LLM_API_KEY ?? null,
...config,
});
// OSS Model Runners
// case "anythingllm_ollama":
// return new ChatOllama({

View File

@@ -31,6 +31,7 @@ const GiteeAIProvider = require("./giteeai.js");
const CohereProvider = require("./cohere.js");
const DockerModelRunnerProvider = require("./dockerModelRunner.js");
const PrivatemodeProvider = require("./privatemode.js");
const SambaNovaProvider = require("./sambanova.js");
module.exports = {
OpenAIProvider,
@@ -66,4 +67,5 @@ module.exports = {
CohereProvider,
DockerModelRunnerProvider,
PrivatemodeProvider,
SambaNovaProvider,
};

View File

@@ -0,0 +1,85 @@
const OpenAI = require("openai");
const Provider = require("./ai-provider.js");
const InheritMultiple = require("./helpers/classes.js");
const UnTooled = require("./helpers/untooled.js");
class SambaNovaProvider extends InheritMultiple([Provider, UnTooled]) {
model;
constructor(config = {}) {
const { model = "Meta-Llama-3.1-8B-Instruct" } = config;
super();
const client = new OpenAI({
baseURL: "https://api.sambanova.ai/v1",
apiKey: process.env.SAMBANOVA_LLM_API_KEY,
maxRetries: 3,
});
this._client = client;
this.model = model;
this.verbose = true;
}
/**
* Create a completion based on the received messages.
*
* @param messages A list of messages to send to the API.
* @param functions
* @returns The completion.
*/
get client() {
return this._client;
}
get supportsAgentStreaming() {
return true;
}
async #handleFunctionCallChat({ messages = [] }) {
return await this.client.chat.completions
.create({
model: this.model,
messages,
})
.then((result) => {
if (!result.hasOwnProperty("choices"))
throw new Error("SambaNova chat: No results!");
if (result.choices.length === 0)
throw new Error("SambaNova chat: No results length!");
return result.choices[0].message.content;
});
}
async #handleFunctionCallStream({ messages = [] }) {
return await this.client.chat.completions.create({
model: this.model,
stream: true,
messages,
});
}
async stream(messages, functions = [], eventHandler = null) {
return await UnTooled.prototype.stream.call(
this,
messages,
functions,
this.#handleFunctionCallStream.bind(this),
eventHandler
);
}
async complete(messages, functions = []) {
return await UnTooled.prototype.complete.call(
this,
messages,
functions,
this.#handleFunctionCallChat.bind(this)
);
}
getCost(_usage) {
return 0;
}
}
module.exports = SambaNovaProvider;

View File

@@ -229,6 +229,10 @@ class AgentHandler {
"Privatemode base path must be provided to use agents."
);
break;
case "sambanova":
if (!process.env.SAMBANOVA_LLM_API_KEY)
throw new Error("SambaNova API key must be provided to use agents.");
break;
default:
throw new Error(
"No workspace agent provider set. Please set your agent provider in the workspace's settings"
@@ -313,6 +317,8 @@ class AgentHandler {
return process.env.DOCKER_MODEL_RUNNER_LLM_MODEL_PREF ?? null;
case "privatemode":
return process.env.PRIVATEMODE_LLM_MODEL_PREF ?? null;
case "sambanova":
return process.env.SAMBANOVA_LLM_MODEL_PREF ?? null;
default:
return null;
}

View File

@@ -46,6 +46,7 @@ const SUPPORT_CUSTOM_MODELS = [
"giteeai",
"docker-model-runner",
"privatemode",
"sambanova",
// Embedding Engines
"native-embedder",
"cohere-embedder",
@@ -123,6 +124,8 @@ async function getCustomModels(provider = "", apiKey = null, basePath = null) {
return await getDockerModelRunnerModels(basePath);
case "privatemode":
return await getPrivatemodeModels(basePath, "generate");
case "sambanova":
return await getSambaNovaModels(apiKey);
default:
return { models: [], error: "Invalid provider for custom models" };
}
@@ -932,6 +935,53 @@ async function getPrivatemodeModels(basePath = null, task = "any") {
}
}
/**
* Get SambaNova models
* @param {string} _apiKey - The API key to use
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
*/
async function getSambaNovaModels(_apiKey = null) {
try {
const apiKey =
_apiKey === true
? process.env.SAMBANOVA_LLM_API_KEY
: _apiKey || process.env.SAMBANOVA_LLM_API_KEY || null;
const { OpenAI: OpenAIApi } = require("openai");
const openai = new OpenAIApi({
baseURL: "https://api.sambanova.ai/v1",
apiKey,
});
const models = await openai.models
.list()
.then((results) => results.data)
.then((models) =>
models.filter((model) => !model.id.toLowerCase().startsWith("whisper"))
)
.then((models) =>
models.map((model) => {
const organization =
model.hasOwnProperty("owned_by") &&
model.owned_by !== "no-reply@sambanova.ai"
? model.owned_by
: "SambaNova";
return {
id: model.id,
organization,
name: model.id,
};
})
)
.catch((e) => {
console.error(`SambaNova:listModels`, e.message);
return [];
});
return { models, error: null };
} catch (e) {
console.error(`SambaNova:getSambaNovaModels`, e.message);
return { models: [], error: "Could not fetch SambaNova Models" };
}
}
module.exports = {
getCustomModels,
SUPPORT_CUSTOM_MODELS,

View File

@@ -237,6 +237,9 @@ function getLLMProvider({ provider = null, model = null } = {}) {
case "privatemode":
const { PrivatemodeLLM } = require("../AiProviders/privatemode");
return new PrivatemodeLLM(embedder, model);
case "sambanova":
const { SambaNovaLLM } = require("../AiProviders/sambanova");
return new SambaNovaLLM(embedder, model);
default:
throw new Error(
`ENV: No valid LLM_PROVIDER value found in environment! Using ${process.env.LLM_PROVIDER}`
@@ -410,6 +413,9 @@ function getLLMProviderClass({ provider = null } = {}) {
case "privatemode":
const { PrivateModeLLM } = require("../AiProviders/privatemode");
return PrivateModeLLM;
case "sambanova":
const { SambaNovaLLM } = require("../AiProviders/sambanova");
return SambaNovaLLM;
default:
return null;
}
@@ -490,6 +496,8 @@ function getBaseLLMProviderModel({ provider = null } = {}) {
return process.env.DOCKER_MODEL_RUNNER_LLM_MODEL_PREF;
case "privatemode":
return process.env.PRIVATEMODE_LLM_MODEL_PREF;
case "sambanova":
return process.env.SAMBANOVA_LLM_MODEL_PREF;
default:
return null;
}

View File

@@ -809,6 +809,16 @@ const KEY_MAPPING = {
envKey: "PRIVATEMODE_LLM_MODEL_PREF",
checks: [isNotEmpty],
},
// SambaNova Options
SambaNovaLLMApiKey: {
envKey: "SAMBANOVA_LLM_API_KEY",
checks: [isNotEmpty],
},
SambaNovaLLMModelPref: {
envKey: "SAMBANOVA_LLM_MODEL_PREF",
checks: [isNotEmpty],
},
};
function isNotEmpty(input = "") {
@@ -924,6 +934,7 @@ function supportedLLM(input = "") {
"giteeai",
"docker-model-runner",
"privatemode",
"sambanova",
].includes(input);
return validSelection ? null : `${input} is not a valid LLM provider.`;
}