mirror of
https://github.com/Mintplex-Labs/anything-llm
synced 2026-04-25 17:15:37 +02:00
Intelligent Skill Selection (#5236)
* Beta Intelligent Tooling todo: Agent Skill banner warning when tool # is high or % of content window? * forgot files * add UI controls and maxToolCallStack setting * update docs link * ISS i18n (#5237) i18n
This commit is contained in:
@@ -433,4 +433,15 @@ GID='1000'
|
||||
# Allow native tool calling for specific providers.
|
||||
# This can VASTLY improve performance and speed of agent calls.
|
||||
# Check code for supported providers who can be enabled here via this flag
|
||||
# PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING="generic-openai,bedrock,localai,groq,litellm,openrouter"
|
||||
# PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING="generic-openai,bedrock,localai,groq,litellm,openrouter"
|
||||
|
||||
# (optional) Maximum number of tools an agent can chain for a single response.
|
||||
# This prevents some lower-end models from infinite recursive tool calls.
|
||||
# AGENT_MAX_TOOL_CALLS=10
|
||||
|
||||
# Enable agent tool reranking to reduce token usage by selecting only the most relevant tools
|
||||
# for each query. Uses the native embedding reranker to score tools against the user's prompt.
|
||||
# Set to "true" to enable. This can reduce token costs by 80% when you have
|
||||
# many tools/MCP servers enabled.
|
||||
# AGENT_SKILL_RERANKER_ENABLED="true"
|
||||
# AGENT_SKILL_RERANKER_TOP_N=15 # (optional) Number of top tools to keep after reranking (default: 15)
|
||||
@@ -342,6 +342,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "وسائط استدعاء الدالة",
|
||||
"tools-enabled": "الأدوات مفعّلة",
|
||||
},
|
||||
settings: {
|
||||
title: "إعدادات مهارات الوكيل",
|
||||
"max-tool-calls": {
|
||||
title: "الحد الأقصى لعدد طلبات الأدوات في الاستجابة.",
|
||||
description:
|
||||
"أقصى عدد من الأدوات التي يمكن للممثل (الوكيل) ربطها لإنشاء استجابة واحدة. وهذا يمنع استدعاءات الأدوات غير المنضبطة والحلقات اللانهائية.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "اختيار المهارات الذكية",
|
||||
"beta-badge": "بيتا",
|
||||
description:
|
||||
"تمكين استخدام أدوات غير محدودة وتقليل استخدام رموز القطع بنسبة تصل إلى 80٪ لكل استعلام - يقوم AnythingLLM تلقائيًا باختيار المهارات المناسبة لكل طلب.",
|
||||
"max-tools": {
|
||||
title: "أدوات ماكس",
|
||||
description:
|
||||
"الحد الأقصى لعدد الأدوات التي يمكن اختيارها لكل استعلام. ونوصي بتعيين هذه القيمة على قيم أعلى بالنسبة للنماذج ذات السياق الأكبر.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "محادثات مساحة العمل",
|
||||
|
||||
@@ -358,6 +358,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumenty pro volání nástroje",
|
||||
"tools-enabled": "nástroje jsou aktivovány",
|
||||
},
|
||||
settings: {
|
||||
title: "Nastavení dovedností agenta",
|
||||
"max-tool-calls": {
|
||||
title: "Maximální počet volání nástrojů na jednu odpověď",
|
||||
description:
|
||||
"Maximální počet nástrojů, které může agent spouštět v řetězci za účelem generování jedné odpovědi. To zabraňuje nekontrolovanému spouštění nástrojů a vytváření nekonečných smyček.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Inteligentní výběr dovedností",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
"Umožněte použití libovolného počtu nástrojů a snížit využití tokenů až o 80 % pro každou dotaz — AnythingLLM automaticky vybírá vhodné dovednosti pro každou žádost.",
|
||||
"max-tools": {
|
||||
title: "Nástroje Max",
|
||||
description:
|
||||
"Maximální počet nástrojů, které lze vybrat pro každou dotaz. Doporučujeme nastavit tuto hodnotu na vyšší, pro modely s větším kontextem.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Chaty pracovních prostorů",
|
||||
|
||||
@@ -346,6 +346,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumenter til værktøjsopkald",
|
||||
"tools-enabled": "værktøjer er aktiveret",
|
||||
},
|
||||
settings: {
|
||||
title: "Indstillinger for agenters færdigheder",
|
||||
"max-tool-calls": {
|
||||
title: "Maksimalt antal anmodninger pr. svar",
|
||||
description:
|
||||
"Det maksimale antal værktøjer, en agent kan kæde sammen for at generere et enkelt svar. Dette forhindrer, at værktøjer kaldes unødvendigt, og undgår uendelige løkker.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Intelligent valg af færdigheder",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
"Aktiver ubegrænsede værktøjer og reducer brugen af cut-tokens med op til 80 % pr. forespørgsel – AnythingLLM vælger automatisk de relevante færdigheder til hver forespørgsel.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Det maksimale antal værktøjer, der kan vælges for hver forespørgsel. Vi anbefaler at indstille dette til højere værdier for større modeller med mere kontekst.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Arbejdsområde-chat",
|
||||
|
||||
@@ -352,6 +352,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumente für die Funktionsaufrufe",
|
||||
"tools-enabled": "Werkzeuge aktiviert",
|
||||
},
|
||||
settings: {
|
||||
title: "Einstellungen für Agenten-Fähigkeiten",
|
||||
"max-tool-calls": {
|
||||
title: "Maximale Anzahl an Tool-Anfragen pro Antwort",
|
||||
description:
|
||||
"Die maximale Anzahl an Werkzeugen, die ein Agent verketten kann, um eine einzelne Antwort zu generieren. Dies verhindert, dass Werkzeuge unkontrolliert aufgerufen werden und zu endlosen Schleifen führen.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Intelligente Auswahl von Fähigkeiten",
|
||||
"beta-badge": "Beta-Version",
|
||||
description:
|
||||
"Ermöglichen Sie die uneingeschränkte Nutzung von Werkzeugen und reduzieren Sie die Token-Nutzung pro Anfrage um bis zu 80 % – AnythingLLM wählt automatisch die passenden Fähigkeiten für jede Anfrage aus.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Die maximale Anzahl der auszuwählenden Werkzeuge für jede Abfrage. Wir empfehlen, diesen Wert für größere Modelle mit größerem Kontext auf einen höheren Wert einzustellen.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Workspace-Chats",
|
||||
|
||||
@@ -357,6 +357,25 @@ const TRANSLATIONS = {
|
||||
"This MCP server is not running - it may be stopped or experiencing an error on startup.",
|
||||
"tool-call-arguments": "Tool call arguments",
|
||||
},
|
||||
settings: {
|
||||
title: "Agent Skill Settings",
|
||||
"max-tool-calls": {
|
||||
title: "Max Tool Calls Per Response",
|
||||
description:
|
||||
"The maximum number of tools an agent can chain to generate a single response. This prevents runaway tool calls and infinite loops.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Intelligent Skill Selection",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
"Enable unlimited tools and cut token usage by up to 80% per query — AnythingLLM automatically selects the right skills for every prompt.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"The maximum number of tools to select for each query. We recommend setting this to higher values for larger context models.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Workspace Chats",
|
||||
|
||||
@@ -356,6 +356,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumentos de llamada de función",
|
||||
"tools-enabled": "herramientas habilitadas",
|
||||
},
|
||||
settings: {
|
||||
title: "Configuración de habilidades del agente",
|
||||
"max-tool-calls": {
|
||||
title: "Número máximo de llamadas a funciones Max Tool por respuesta",
|
||||
description:
|
||||
"El número máximo de herramientas que un agente puede encadenar para generar una única respuesta. Esto evita que se realicen llamadas a herramientas de forma descontrolada y que se produzcan bucles infinitos.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Selección inteligente de habilidades",
|
||||
"beta-badge": "Versión preliminar",
|
||||
description:
|
||||
"Permite el uso ilimitado de herramientas y reduce el consumo de tokens hasta en un 80% por consulta: AnythingLLM selecciona automáticamente las habilidades adecuadas para cada solicitud.",
|
||||
"max-tools": {
|
||||
title: "Herramientas Max",
|
||||
description:
|
||||
"El número máximo de herramientas que se pueden seleccionar para cada consulta. Recomendamos establecer este valor en un número más alto para modelos con un contexto más amplio.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Chats del espacio de trabajo",
|
||||
|
||||
@@ -341,6 +341,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": '"Tooli käivitamise argumentid"',
|
||||
"tools-enabled": "vahendid on lubatud",
|
||||
},
|
||||
settings: {
|
||||
title: "Agenti oskuste seaded",
|
||||
"max-tool-calls": {
|
||||
title: "Maximaalne töö-kõned vastuse kohta",
|
||||
description:
|
||||
"Максимаalne arv, mis agent võib ühendada, et genereerida ühe vastuse. See takistab liigse töö tegevuse ja lõpmatute ringide tekkimist.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Nutikad oskuste valiku meetodid",
|
||||
"beta-badge": "Beeta",
|
||||
description:
|
||||
"Lubage piiramatu hulga tööriistade kasutamist ning vähendage küsimuse kohta kasutatavate tokenide arv kuni 80% – AnythingLLM valib automaatselt iga küsimuse jaoks sobivad oskused.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Maksimaalne arv tööriistu, mida saab valida igale küsimusele. Soovitame seada see väärtus suuremate kontekstmudelite jaoks suuremaks.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Tööruumi vestlused",
|
||||
|
||||
@@ -344,6 +344,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "آرگومانهای فراخوانی ابزار",
|
||||
"tools-enabled": "ابزارهای فعال",
|
||||
},
|
||||
settings: {
|
||||
title: "تنظیمات مهارتهای کارمند",
|
||||
"max-tool-calls": {
|
||||
title: "حداکثر تعداد درخواستهای ابزار در هر پاسخ",
|
||||
description:
|
||||
"حداکثر تعداد ابزارهایی که یک عامل میتواند برای تولید یک پاسخ واحد به آنها متصل کند. این کار از اجرای مکرر و بینهایت ابزارها جلوگیری میکند.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "انتخاب مهارتهای هوشمند",
|
||||
"beta-badge": "بتا",
|
||||
description:
|
||||
"امکان استفاده از ابزارهای نامحدود و کاهش مصرف توکن تا 80 درصد برای هر پرس و جو را فراهم کنید - AnythingLLM به طور خودکار بهترین مهارتها را برای هر پرس و جو انتخاب میکند.",
|
||||
"max-tools": {
|
||||
title: "ابزارهای مکس",
|
||||
description:
|
||||
"حداکثر تعداد ابزارهایی که میتوان برای هر پرس و جو انتخاب کرد. ما توصیه میکنیم که این مقدار را برای مدلهای با زمینه بزرگتر، به مقادیر بالاتر تنظیم کنید.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "گفتگوهای فضای کاری",
|
||||
|
||||
@@ -346,6 +346,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Arguments des appels de fonctions/outils",
|
||||
"tools-enabled": "outils activés",
|
||||
},
|
||||
settings: {
|
||||
title: "Paramètres des compétences des agents",
|
||||
"max-tool-calls": {
|
||||
title: "Nombre maximal de requêtes Max Tool par réponse",
|
||||
description:
|
||||
"Le nombre maximal d'outils qu'un agent peut utiliser en chaîne pour générer une seule réponse. Cela empêche les appels excessifs aux outils et les boucles infinies.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Sélection de compétences basée sur l'intelligence",
|
||||
"beta-badge": "Bêta",
|
||||
description:
|
||||
"Permettez l'utilisation illimitée d'outils et réduisez la consommation de jetons jusqu'à 80 % par requête – AnythingLLM sélectionne automatiquement les compétences appropriées pour chaque requête.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Le nombre maximal d'outils à sélectionner pour chaque requête. Nous recommandons de définir cette valeur sur une valeur plus élevée pour les modèles de contexte plus importants.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Chats de l'espace de travail",
|
||||
|
||||
@@ -343,6 +343,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "ארגומנטים לפונקציות",
|
||||
"tools-enabled": "הכלים פעלו/היו זמינים",
|
||||
},
|
||||
settings: {
|
||||
title: "הגדרות מיומנויות של סוכן",
|
||||
"max-tool-calls": {
|
||||
title: 'מספר קריאות "Max Tool" לכל תגובה',
|
||||
description:
|
||||
"מספר הכלים המקסימלי שאгент יכול לקשור כדי ליצור תגובה אחת. זה מונע קריאות מרובות של כלים ומחזורים אינסופיים.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "בחירת מיומנויות בהתאם ליכולות",
|
||||
"beta-badge": "בטא",
|
||||
description:
|
||||
"אפשרו שימוש בלתי מוגבל בכלים וצמצום השימוש בטוקנים עד 80% לכל שאילתה – ה-AnythingLLM בוחר באופן אוטומטי את הכישורים המתאימים ביותר לכל בקשה.",
|
||||
"max-tools": {
|
||||
title: "כלים של מקס",
|
||||
description:
|
||||
"מספר המינימום של כלי העבודה שניתן לבחור עבור כל שאילתה. אנו ממליצים להגדיר ערך גבוה יותר עבור מודלים עם הקשר רחב יותר.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "צ'אטים של סביבת עבודה",
|
||||
|
||||
@@ -349,6 +349,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argomenti delle chiamate di funzioni",
|
||||
"tools-enabled": "strumenti abilitati",
|
||||
},
|
||||
settings: {
|
||||
title: "Impostazioni delle competenze dell'agente",
|
||||
"max-tool-calls": {
|
||||
title: "Numero massimo di chiamate a funzioni Max Tool per risposta",
|
||||
description:
|
||||
"Il numero massimo di strumenti che un agente può concatenare per generare una singola risposta. Questo previene chiamate eccessive agli strumenti e cicli infiniti.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Selezione intelligente delle competenze",
|
||||
"beta-badge": "Versione beta",
|
||||
description:
|
||||
"Abilita l'uso illimitato degli strumenti e riduci l'utilizzo dei token fino all'80% per ogni query — AnythingLLM seleziona automaticamente le competenze più appropriate per ogni richiesta.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Il numero massimo di strumenti da selezionare per ogni query. Si raccomanda di impostare questo valore su un valore più elevato per i modelli con un contesto più ampio.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Chat dell'area di lavoro",
|
||||
|
||||
@@ -340,6 +340,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "ツール呼び出しの引数",
|
||||
"tools-enabled": "ツールが有効化されました",
|
||||
},
|
||||
settings: {
|
||||
title: "エージェントのスキル設定",
|
||||
"max-tool-calls": {
|
||||
title: "1回の応答で実行できる最大ツール数",
|
||||
description:
|
||||
"エージェントが単一の応答を生成するために使用できるツールの一意な最大数。これにより、ツール呼び出しの過剰や無限ループを防ぐことができます。",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "知的なスキル選択",
|
||||
"beta-badge": "ベータ版",
|
||||
description:
|
||||
"クエリごとに、無制限のツールを使用し、トークン使用量を最大80%削減できます。AnythingLLMは、各プロンプトに対して最適なスキルを自動的に選択します。",
|
||||
"max-tools": {
|
||||
title: "マックスツールズ",
|
||||
description:
|
||||
"各クエリで選択できるツール数の上限。大規模なコンテキストモデルを使用する場合は、この値をより高い値に設定することをお勧めします。",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "ワークスペースチャット履歴",
|
||||
|
||||
@@ -344,6 +344,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "툴 호출 인자",
|
||||
"tools-enabled": "도구 사용 기능 활성화",
|
||||
},
|
||||
settings: {
|
||||
title: "에이전트 스킬 설정",
|
||||
"max-tool-calls": {
|
||||
title: "응답당 최대 툴 호출 횟수",
|
||||
description:
|
||||
"에이전트가 단일 응답을 생성하기 위해 사용할 수 있는 최대 툴의 개수입니다. 이를 통해 불필요한 툴 호출과 무한 루프를 방지합니다.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "지능형 기술 선택",
|
||||
"beta-badge": "베타",
|
||||
description:
|
||||
"쿼리당 무제한의 도구 사용 및 컷 토큰 사용량을 최대 80%까지 줄일 수 있습니다 – AnythingLLM은 모든 프롬프트에 적합한 기술을 자동으로 선택합니다.",
|
||||
"max-tools": {
|
||||
title: "맥스 툴스",
|
||||
description:
|
||||
"각 쿼리에 사용할 수 있는 최대 도구 수입니다. 큰 컨텍스트 모델의 경우, 이 값을 더 높은 값으로 설정하는 것을 권장합니다.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "워크스페이스 채팅",
|
||||
|
||||
@@ -349,6 +349,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Parametri, kas tiek nosūtīti rīkam",
|
||||
"tools-enabled": "rīki atļauti",
|
||||
},
|
||||
settings: {
|
||||
title: "Aģenta spēju iestatījumi",
|
||||
"max-tool-calls": {
|
||||
title: "Maksimālais rēķinu skaits vienam atbildē",
|
||||
description:
|
||||
"Maksimālais rīku skaits, ko aģents var apvienot, lai ģenerētu vienu atbildi. Tas novērina neierobežotu rīku izmantošanu un beidzoties.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Izglītības un prasmu izvēle, kas balstota uz spējām",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
'Ievērojiet neierobežotu rīku un "cut token" izmantošanas samazinājumu līdz 80% uz katru pieprasījumu – AnythingLLM automātiski izvēlas piemērotākās prasmes katram pieprasījumam.',
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Maksimālais rīku skaits, kas var tikt izvēlts katrai meklēšanai. Mēs iesakām iestatīt šo vērtību, lai iegūtu lielāku kontekstu modelus.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Darba telpas sarunas",
|
||||
|
||||
@@ -344,6 +344,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumenten voor het aanroepen van een tool",
|
||||
"tools-enabled": "hulpmiddelen zijn geactiveerd",
|
||||
},
|
||||
settings: {
|
||||
title: "Instellingen voor vaardigheden van agenten",
|
||||
"max-tool-calls": {
|
||||
title: "Maximaal aantal tool-aanroepen per antwoord",
|
||||
description:
|
||||
"Het maximale aantal tools dat een agent kan gebruiken om een enkele reactie te genereren. Dit voorkomt dat tools onbeperkt worden aangeroepen en dat er oneindige loops ontstaan.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Intelligente selectie van vaardigheden",
|
||||
"beta-badge": "Betaling",
|
||||
description:
|
||||
'Maak gebruik van een onbeperkt aantal tools en verminder het gebruik van "cut tokens" met tot wel 80% per query – AnythingLLM selecteert automatisch de juiste vaardigheden voor elke vraag.',
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Het maximale aantal tools dat kan worden geselecteerd voor elke query. Wij raden aan om deze waarde hoger in te stellen voor modellen met een grotere context.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Werkruimte Chats",
|
||||
|
||||
@@ -350,6 +350,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumenty wywoływania funkcji",
|
||||
"tools-enabled": "narzędzia są aktywne",
|
||||
},
|
||||
settings: {
|
||||
title: "Ustawienia umiejętności agenta",
|
||||
"max-tool-calls": {
|
||||
title: "Maksymalna liczba żądań narzędzi na odpowiedź",
|
||||
description:
|
||||
"Maksymalna liczba narzędzi, które agent może łączyć, aby wygenerować pojedynczą odpowiedź. Zapobiega to niekontrolowanemu wywoływaniu narzędzi i tworzeniu nieskończonych pętli.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Inteligentny wybór umiejętności",
|
||||
"beta-badge": "Wersja beta",
|
||||
description:
|
||||
"Umożliwia korzystanie z nieograniczonej liczby narzędzi oraz redukcję zużycia tokenów o do 80% na każde zapytanie – EverythingLLM automatycznie wybiera odpowiednie umiejętności dla każdego zapytania.",
|
||||
"max-tools": {
|
||||
title: "Narzędzia Max",
|
||||
description:
|
||||
"Maksymalna liczba narzędzi, które można wybrać dla każdego zapytania. Zalecamy ustawienie tej wartości na wyższe poziomy dla modeli o większym kontekście.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Czaty w obszarach roboczych",
|
||||
|
||||
@@ -349,6 +349,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumentos de chamada de ferramenta",
|
||||
"tools-enabled": "ferramentas ativadas",
|
||||
},
|
||||
settings: {
|
||||
title: "Configurações de Habilidades do Agente",
|
||||
"max-tool-calls": {
|
||||
title: "Número máximo de chamadas de ferramenta por resposta",
|
||||
description:
|
||||
"O número máximo de ferramentas que um agente pode encadear para gerar uma única resposta. Isso evita chamadas excessivas de ferramentas e loops infinitos.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Seleção Inteligente de Habilidades",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
"Permita o uso ilimitado de ferramentas e reduza o consumo de tokens em até 80% por consulta — O AnythingLLM seleciona automaticamente as habilidades mais adequadas para cada solicitação.",
|
||||
"max-tools": {
|
||||
title: "Ferramentas Max",
|
||||
description:
|
||||
"O número máximo de ferramentas que podem ser selecionadas para cada consulta. Recomendamos definir este valor para modelos com contextos maiores.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Chats do Workspace",
|
||||
|
||||
@@ -796,6 +796,26 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Argumente pentru apelarea unei funcții",
|
||||
"tools-enabled": "instrumentele sunt activate",
|
||||
},
|
||||
settings: {
|
||||
title: "Setări pentru abilitățile agenților",
|
||||
"max-tool-calls": {
|
||||
title:
|
||||
"Numărul maxim de solicitări de instrument (Max Tool Calls Per Response)",
|
||||
description:
|
||||
"Numărul maxim de instrumente pe care un agent le poate utiliza în mod consecutiv pentru a genera un singur răspuns. Această funcție previne apelurile inutile ale instrumentelor și buclele infinite.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Selecție inteligentă a abilităților",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
"Permite utilizarea nelimitată a instrumentelor și reduce utilizarea token-urilor cu până la 80% pentru fiecare interogare – AnythingLLM selectează automat abilitățile potrivite pentru fiecare solicitare.",
|
||||
"max-tools": {
|
||||
title: "Max Tools",
|
||||
description:
|
||||
"Numărul maxim de instrumente care pot fi selectate pentru fiecare interogare. Recomandăm stabilirea acestui parametru la valori mai mari pentru modelele cu un context mai amplu.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Conversații spațiu de lucru",
|
||||
|
||||
@@ -343,6 +343,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Аргументы для вызова функции",
|
||||
"tools-enabled": "инструменты включены/активированы",
|
||||
},
|
||||
settings: {
|
||||
title: "Настройки навыков агента",
|
||||
"max-tool-calls": {
|
||||
title: "Максимальное количество запросов к инструменту в одном ответе",
|
||||
description:
|
||||
"Максимальное количество инструментов, которые агент может использовать последовательно для генерации одного ответа. Это предотвращает чрезмерное использование инструментов и бесконечные циклы.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Интеллектуальный выбор навыков",
|
||||
"beta-badge": "Бета-версия",
|
||||
description:
|
||||
"Позволяет использовать неограниченное количество инструментов и сократить использование токенов до 80% на запрос – AnythingLLM автоматически выбирает наиболее подходящие навыки для каждого запроса.",
|
||||
"max-tools": {
|
||||
title: "Инструменты Max",
|
||||
description:
|
||||
"Максимальное количество инструментов, которые можно выбрать для каждого запроса. Мы рекомендуем устанавливать это значение на более высокие значения для моделей с большим контекстом.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Чаты рабочего пространства",
|
||||
|
||||
@@ -343,6 +343,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Araç çağrı argümanları",
|
||||
"tools-enabled": "gerektiren araçlar etkinleştirildi",
|
||||
},
|
||||
settings: {
|
||||
title: "Ajant Yetenek Ayarları",
|
||||
"max-tool-calls": {
|
||||
title: "Her yanıt için maksimum araç çağrı sayısı",
|
||||
description:
|
||||
"Bir ajantın, tek bir yanıt oluşturmak için zincirlemesini kullanabileceği maksimum araç sayısı. Bu, araçların kontrolsüz bir şekilde çağrılmasını ve sonsuz döngülerin oluşmasını engeller.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Akıllı Becerilerin Seçimi",
|
||||
"beta-badge": "Beta",
|
||||
description:
|
||||
'Her sorgu için sınırsız araç kullanımı ve "cut token" kullanımını %80\'e kadar azaltma imkanı sunar — AnythingLLM, her talep için doğru becerileri otomatik olarak seçer.',
|
||||
"max-tools": {
|
||||
title: "Max Araçları",
|
||||
description:
|
||||
"Her sorgu için seçilebilecek maksimum araç sayısı. Daha büyük bağlam modelleri için bu değeri daha yüksek bir değere ayarlamayı öneririz.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Çalışma Alanı Sohbetleri",
|
||||
|
||||
@@ -342,6 +342,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "Tham số khi gọi hàm/thao tác",
|
||||
"tools-enabled": "các công cụ đã được kích hoạt",
|
||||
},
|
||||
settings: {
|
||||
title: "Cài đặt kỹ năng của đại lý",
|
||||
"max-tool-calls": {
|
||||
title: "Số lượng lệnh gọi công cụ tối đa cho mỗi phản hồi",
|
||||
description:
|
||||
"Số lượng công cụ tối đa mà một người dùng có thể liên kết để tạo ra một phản hồi duy nhất. Điều này ngăn chặn việc gọi công cụ quá mức và tạo ra các vòng lặp vô hạn.",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "Lựa chọn kỹ năng thông minh",
|
||||
"beta-badge": "Phiên bản thử nghiệm",
|
||||
description:
|
||||
"Cho phép sử dụng không giới hạn các công cụ và giảm mức sử dụng token lên đến 80% cho mỗi truy vấn – AnythingLLM tự động chọn các kỹ năng phù hợp nhất cho mỗi yêu cầu.",
|
||||
"max-tools": {
|
||||
title: "Công cụ Max",
|
||||
description:
|
||||
"Số lượng công cụ tối đa có thể chọn cho mỗi truy vấn. Chúng tôi khuyến nghị đặt giá trị này thành các giá trị lớn hơn đối với các mô hình có ngữ cảnh lớn hơn.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "Hội thoại không gian làm việc",
|
||||
|
||||
@@ -333,6 +333,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "工具调用的参数",
|
||||
"tools-enabled": "工具已启用",
|
||||
},
|
||||
settings: {
|
||||
title: "代理技能设置",
|
||||
"max-tool-calls": {
|
||||
title: "每个回复的最大请求次数",
|
||||
description:
|
||||
"单个代理可以使用的最大工具数量,用于生成单个响应。 这样可以防止工具调用数量过多,从而避免无限循环。",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "智能技能选择",
|
||||
"beta-badge": "β 版本",
|
||||
description:
|
||||
"实现无限工具和按查询减少高达 80% 的 Token 使用量——AnythingLLM 能够自动选择最合适的技能,以应对每个提示。",
|
||||
"max-tools": {
|
||||
title: "麦克斯工具",
|
||||
description:
|
||||
"可以选取的工具的最大数量,用于每个查询。我们建议将此值设置为较高的值,以便在处理大型上下文模型时。",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "工作区聊天历史记录",
|
||||
|
||||
@@ -322,6 +322,25 @@ const TRANSLATIONS = {
|
||||
"tool-call-arguments": "工具呼叫的參數",
|
||||
"tools-enabled": "已啟用工具",
|
||||
},
|
||||
settings: {
|
||||
title: "代理人技能設定",
|
||||
"max-tool-calls": {
|
||||
title: "每次回應的最大工具呼叫次數",
|
||||
description:
|
||||
"這設定了代理可以串聯使用的最大工具數量,以確保每次回應只會呼叫有限的工具,並避免無限循環。",
|
||||
},
|
||||
"intelligent-skill-selection": {
|
||||
title: "智能技能選擇",
|
||||
"beta-badge": "β 版本",
|
||||
description:
|
||||
"啟用無限多個工具,並將每個查詢的 token 使用量最多降低 80% — AnythingLLM 能夠自動選擇最適合的技能,以處理每一個提示。",
|
||||
"max-tools": {
|
||||
title: "馬克斯工具",
|
||||
description:
|
||||
"可選取的工具的最大數量,適用於每個查詢。我們建議將此值設定為較高的值,以適用於較大的模型。",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recorded: {
|
||||
title: "工作區對話紀錄",
|
||||
|
||||
215
frontend/src/pages/Admin/Agents/AgentSkillSettings/index.jsx
Normal file
215
frontend/src/pages/Admin/Agents/AgentSkillSettings/index.jsx
Normal file
@@ -0,0 +1,215 @@
|
||||
import { useModal } from "@/hooks/useModal";
|
||||
import ModalWrapper from "@/components/ModalWrapper";
|
||||
import { CircleNotch, SlidersHorizontal, X } from "@phosphor-icons/react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import Toggle from "@/components/lib/Toggle";
|
||||
import System from "@/models/system";
|
||||
import debounce from "lodash.debounce";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function AgentSkillSettings() {
|
||||
const { isOpen, openModal, closeModal } = useModal();
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={openModal}
|
||||
className={`w-10 h-10 flex items-center justify-center light:border-black/10 light:border-solid border-none light:!border rounded-lg transition-colors outline-none bg-transparent hover:bg-theme-bg-secondary`}
|
||||
>
|
||||
<SlidersHorizontal size={24} className={`text-theme-text-secondary`} />
|
||||
</button>
|
||||
<AgentSkillSettingsModal isOpen={isOpen} closeModal={closeModal} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AgentSkillSettingsModal({ isOpen, closeModal }) {
|
||||
const { t } = useTranslation();
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<ModalWrapper isOpen={isOpen}>
|
||||
<div className="w-[500px] bg-theme-bg-sidebar px-6 py-4 rounded-lg flex flex-col items-center justify-between relative shadow-lg border border-white/10">
|
||||
<div className="w-full flex items-center justify-between">
|
||||
<div className="text-white text-left font-medium text-lg">
|
||||
{t("agent.settings.title")}
|
||||
</div>
|
||||
<button
|
||||
onClick={closeModal}
|
||||
className="text-white opacity-60 hover:text-white hover:opacity-100 border-none outline-none"
|
||||
>
|
||||
<X size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="flex flex-col gap-y-5 w-full">
|
||||
<MaxToolCallStack />
|
||||
<div className="border-b border-white/10 h-[1px] w-full" />
|
||||
<AgentSkillReranker />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
function MaxToolCallStack() {
|
||||
const { t } = useTranslation();
|
||||
const [maxCallStack, setMaxCallStack] = useState(10);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const debouncedUpdateMaxCallStack = useMemo(
|
||||
() =>
|
||||
debounce(async (newMaxCallStack) => {
|
||||
await System.updateSystem({
|
||||
AgentSkillMaxToolCalls: newMaxCallStack.toString(),
|
||||
});
|
||||
}, 800),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
System.keys()
|
||||
.then((res) => {
|
||||
setMaxCallStack(parseInt(res.AgentSkillMaxToolCalls));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
return () => debouncedUpdateMaxCallStack.cancel();
|
||||
}, [debouncedUpdateMaxCallStack]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2 mt-4">
|
||||
<div className="flex items-center gap-x-4 mt-2">
|
||||
<div className="flex flex-col gap-y-1 flex-1">
|
||||
<label className="block text-md font-medium text-white">
|
||||
{t("agent.settings.max-tool-calls.title")}
|
||||
</label>
|
||||
<p className="text-xs text-white/60">
|
||||
{t("agent.settings.max-tool-calls.description")}
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
type="number"
|
||||
name="agentSkillMaxToolCalls"
|
||||
min={1}
|
||||
value={maxCallStack}
|
||||
disabled={loading}
|
||||
onChange={(e) => {
|
||||
if (e.target.value < 1) return;
|
||||
debouncedUpdateMaxCallStack(e.target.value);
|
||||
setMaxCallStack(parseInt(e.target.value));
|
||||
}}
|
||||
onWheel={(e) => e.target.blur()}
|
||||
className="border border-white/10 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-[80px] p-2.5 text-center"
|
||||
placeholder="10"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AgentSkillReranker() {
|
||||
const { t } = useTranslation();
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [maxTools, setMaxTools] = useState(15);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const debouncedUpdateMaxTools = useMemo(
|
||||
() =>
|
||||
debounce(async (newMaxToolsCount) => {
|
||||
await System.updateSystem({
|
||||
AgentSkillRerankerTopN: newMaxToolsCount.toString(),
|
||||
});
|
||||
}, 800),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
System.keys()
|
||||
.then((res) => {
|
||||
setEnabled(res.AgentSkillRerankerEnabled);
|
||||
setMaxTools(parseInt(res.AgentSkillRerankerTopN));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
return () => debouncedUpdateMaxTools.cancel();
|
||||
}, [debouncedUpdateMaxTools]);
|
||||
|
||||
async function toggleEnabled(enabled) {
|
||||
setEnabled(enabled);
|
||||
await System.updateSystem({
|
||||
AgentSkillRerankerEnabled: String(enabled),
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-4">
|
||||
<div className="flex items-center gap-x-1">
|
||||
<label className="block text-md font-medium text-white flex items-center gap-x-1">
|
||||
{t("agent.settings.intelligent-skill-selection.title")}{" "}
|
||||
<i className="ml-1 text-xs text-white pl-2 bg-blue-500/40 rounded-md px-2 py-0.5">
|
||||
{t("agent.settings.intelligent-skill-selection.beta-badge")}
|
||||
</i>
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-4">
|
||||
<p className="text-xs text-white/60">
|
||||
{t("agent.settings.intelligent-skill-selection.description")}
|
||||
</p>
|
||||
{loading ? (
|
||||
<CircleNotch
|
||||
size={16}
|
||||
className="shrink-0 animate-spin text-theme-text-primary"
|
||||
/>
|
||||
) : (
|
||||
<Toggle
|
||||
size="lg"
|
||||
name="agentSkillRerankerEnabled"
|
||||
enabled={enabled}
|
||||
onChange={toggleEnabled}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{enabled && (
|
||||
<div className="flex items-center gap-x-4">
|
||||
<div className="flex flex-col gap-y-1 flex-1">
|
||||
<label className="block text-md font-medium text-white">
|
||||
{t("agent.settings.intelligent-skill-selection.max-tools.title")}
|
||||
</label>
|
||||
<p className="text-xs text-white/60">
|
||||
{t(
|
||||
"agent.settings.intelligent-skill-selection.max-tools.description"
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
type="number"
|
||||
name="agentSkillRerankerTopN"
|
||||
min={10}
|
||||
value={maxTools}
|
||||
onChange={(e) => {
|
||||
if (e.target.value < 10) return;
|
||||
debouncedUpdateMaxTools(e.target.value);
|
||||
setMaxTools(parseInt(e.target.value));
|
||||
}}
|
||||
onWheel={(e) => e.target.blur()}
|
||||
className="border border-white/10 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-[80px] p-2.5 text-center"
|
||||
placeholder="15"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -29,6 +29,13 @@ import ServerPanel from "./MCPServers/ServerPanel";
|
||||
import { Link } from "react-router-dom";
|
||||
import paths from "@/utils/paths";
|
||||
import AgentFlows from "@/models/agentFlows";
|
||||
import AgentSkillSettings from "./AgentSkillSettings";
|
||||
|
||||
const IGNORE_CHANGE_SETTINGS = [
|
||||
"agentSkillRerankerEnabled",
|
||||
"agentSkillRerankerTopN",
|
||||
"agentSkillMaxToolCalls",
|
||||
];
|
||||
|
||||
export default function AdminAgents() {
|
||||
const { t } = useTranslation();
|
||||
@@ -483,9 +490,10 @@ export default function AdminAgents() {
|
||||
>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
onChange={() =>
|
||||
!selectedSkill?.imported && !selectedFlow && setHasChanges(true)
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (IGNORE_CHANGE_SETTINGS.includes(e.target.name)) return;
|
||||
if (!selectedSkill?.imported && !selectedFlow) setHasChanges(true);
|
||||
}}
|
||||
ref={formEl}
|
||||
className="flex-1 flex gap-x-6 p-4 mt-10"
|
||||
>
|
||||
@@ -508,11 +516,12 @@ export default function AdminAgents() {
|
||||
|
||||
{/* Skill settings nav - Make this section scrollable */}
|
||||
<div className="flex flex-col min-w-[360px] h-[calc(100vh-90px)]">
|
||||
<div className="flex-none mb-4">
|
||||
<div className="flex-none flex justify-between items-center mb-4">
|
||||
<div className="text-theme-text-primary flex items-center gap-x-2">
|
||||
<Robot size={24} />
|
||||
<p className="text-lg font-medium">Agent Skills</p>
|
||||
</div>
|
||||
<AgentSkillSettings />
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto pr-2 pb-4">
|
||||
|
||||
@@ -436,4 +436,15 @@ TTS_PROVIDER="native"
|
||||
# Allow native tool calling for specific providers.
|
||||
# This can VASTLY improve performance and speed of agent calls.
|
||||
# Check code for supported providers who can be enabled here via this flag
|
||||
# PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING="generic-openai,bedrock,localai,groq,litellm,openrouter"
|
||||
# PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING="generic-openai,bedrock,localai,groq,litellm,openrouter"
|
||||
|
||||
# (optional) Maximum number of tools an agent can chain for a single response.
|
||||
# This prevents some lower-end models from infinite recursive tool calls.
|
||||
# AGENT_MAX_TOOL_CALLS=10
|
||||
|
||||
# Enable agent tool reranking to reduce token usage by selecting only the most relevant tools
|
||||
# for each query. Uses the native embedding reranker to score tools against the user's prompt.
|
||||
# Set to "true" to enable. This can reduce token costs by 80% when you have
|
||||
# many tools/MCP servers enabled.
|
||||
# AGENT_SKILL_RERANKER_ENABLED="true"
|
||||
# AGENT_SKILL_RERANKER_TOP_N=15 # (optional) Number of top tools to keep after reranking (default: 15)
|
||||
@@ -208,6 +208,11 @@ const SystemSettings = {
|
||||
},
|
||||
currentSettings: async function () {
|
||||
const { hasVectorCachedFiles } = require("../utils/files");
|
||||
const {
|
||||
ToolReranker,
|
||||
} = require("../utils/agents/aibitat/utils/toolReranker");
|
||||
const AIbitat = require("../utils/agents/aibitat");
|
||||
|
||||
const llmProvider = process.env.LLM_PROVIDER;
|
||||
const vectorDB = process.env.VECTOR_DB;
|
||||
const embeddingEngine = process.env.EMBEDDING_ENGINE ?? "native";
|
||||
@@ -316,6 +321,13 @@ const SystemSettings = {
|
||||
SimpleSSOEnabled: "SIMPLE_SSO_ENABLED" in process.env || false,
|
||||
SimpleSSONoLogin: "SIMPLE_SSO_NO_LOGIN" in process.env || false,
|
||||
SimpleSSONoLoginRedirect: this.simpleSSO.noLoginRedirect(),
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Agent Skill Settings
|
||||
// --------------------------------------------------------
|
||||
AgentSkillMaxToolCalls: AIbitat.defaultMaxToolCalls(),
|
||||
AgentSkillRerankerEnabled: ToolReranker.isEnabled(),
|
||||
AgentSkillRerankerTopN: ToolReranker.getTopN(),
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ const { APIError } = require("./error.js");
|
||||
const Providers = require("./providers/index.js");
|
||||
const { Telemetry } = require("../../../models/telemetry.js");
|
||||
const { v4 } = require("uuid");
|
||||
const { ToolReranker } = require("./utils/toolReranker.js");
|
||||
|
||||
/**
|
||||
* AIbitat is a class that manages the conversation between agents.
|
||||
@@ -44,12 +45,34 @@ class AIbitat {
|
||||
*/
|
||||
_pendingCitations = [];
|
||||
|
||||
/**
|
||||
* Get the default maximum number of tools an agent can chain for a single response.
|
||||
* @returns {number}
|
||||
*/
|
||||
static defaultMaxToolCalls() {
|
||||
const envMaxToolCalls = parseInt(process.env.AGENT_MAX_TOOL_CALLS, 10);
|
||||
return !isNaN(envMaxToolCalls) && envMaxToolCalls > 0
|
||||
? envMaxToolCalls
|
||||
: 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AIbitat instance.
|
||||
* @param {Object} props - The properties for the AIbitat instance.
|
||||
* @param {Array} props.chats - [default: []] The chat history between agents and channels.
|
||||
* @param {string} props.interrupt - [default: "NEVER"] The interrupt mode for the AIbitat instance.
|
||||
* @param {number} props.maxRounds - [default: 100] The maximum number of rounds for the AIbitat instance.
|
||||
* @param {number} props.maxToolCalls - [default: AIbitat.defaultMaxToolCalls()] The maximum number of tools an agent can chain for a single response.
|
||||
* @param {string} props.provider - [default: "openai"] The provider for the AIbitat instance.
|
||||
* @param {Object} props.handlerProps - The handler properties for the AIbitat instance.
|
||||
* @param {Object} rest - The rest of the properties for the AIbitat instance.
|
||||
*/
|
||||
constructor(props = {}) {
|
||||
const {
|
||||
chats = [],
|
||||
interrupt = "NEVER",
|
||||
maxRounds = 100,
|
||||
maxToolCalls = 10,
|
||||
maxToolCalls = AIbitat.defaultMaxToolCalls(),
|
||||
provider = "openai",
|
||||
handlerProps = {}, // Inherited props we can spread so aibitat can access.
|
||||
...rest
|
||||
@@ -534,9 +557,7 @@ class AIbitat {
|
||||
{
|
||||
role: "user",
|
||||
content: `You are in a role play game. The following roles are available:
|
||||
${availableNodes
|
||||
.map((node) => `@${node}: ${this.getAgentConfig(node).role}`)
|
||||
.join("\n")}.
|
||||
${availableNodes.map((node) => `@${node}: ${this.getAgentConfig(node).role}`).join("\n")}.
|
||||
|
||||
Read the following conversation.
|
||||
|
||||
@@ -574,6 +595,27 @@ Only return the role.
|
||||
return pluginName.split("#")[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the user's prompt from the messages array for tool reranking.
|
||||
* Gets the content of the last user message.
|
||||
* @param {Array} messages - Array of chat messages
|
||||
* @returns {string|null} The user's prompt or null if not found
|
||||
*/
|
||||
#extractUserPrompt(messages) {
|
||||
if (!messages || !Array.isArray(messages)) return null;
|
||||
|
||||
// Find the last user message
|
||||
for (let i = messages.length - 1; i >= 0; i--) {
|
||||
const msg = messages[i];
|
||||
if (msg.role === "user" && msg.content) {
|
||||
return typeof msg.content === "string"
|
||||
? msg.content
|
||||
: JSON.stringify(msg.content);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the chat has reached the maximum number of rounds.
|
||||
*/
|
||||
@@ -665,10 +707,30 @@ ${this.getHistory({ to: route.to })
|
||||
];
|
||||
|
||||
// get the functions that the node can call
|
||||
const functions = fromConfig.functions
|
||||
let functions = fromConfig.functions
|
||||
?.map((name) => this.functions.get(this.#parseFunctionName(name)))
|
||||
.filter((a) => !!a);
|
||||
|
||||
// Rerank tools based on user prompt if enabled
|
||||
if (ToolReranker.isEnabled() && functions?.length) {
|
||||
const toolReranker = new ToolReranker();
|
||||
const userPrompt = this.#extractUserPrompt(messages);
|
||||
if (userPrompt)
|
||||
functions = await toolReranker.rerank(userPrompt, functions);
|
||||
} else {
|
||||
if (functions?.length > ToolReranker.defaultTopN) {
|
||||
this.handlerProps.log?.(
|
||||
`
|
||||
|
||||
\x1b[44m[HINT]\x1b[0m: You are injecting \x1b[0;93m${functions.length} tools\x1b[0m into every request.
|
||||
Consider enabling \x1b[0;93mIntelligent Skill Selection\x1b[0m to reduce token usage from tool call bloat by up to \x1b[0;93m80% per request\x1b[0m.
|
||||
https://docs.anythingllm.com/agent/intelligent-tool-selection
|
||||
|
||||
`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const provider = this.getProviderForConfig({
|
||||
...this.defaultProvider,
|
||||
...fromConfig,
|
||||
|
||||
@@ -16,13 +16,13 @@ const memory = {
|
||||
tracker: new Deduplicator(),
|
||||
name: this.name,
|
||||
description:
|
||||
"Search against local documents for context that is relevant to the query or store a snippet of text into memory for retrieval later. Storing information should only be done when the user specifically requests for information to be remembered or saved to long-term memory. You should use this tool before search the internet for information. Do not use this tool unless you are explicitly told to 'remember' or 'store' information.",
|
||||
"Search your local documents and workspace files for relevant information, or store information to long-term memory. Use search to find answers in uploaded documents, embedded files, or previously stored memories. Use store only when explicitly asked to remember or save something.",
|
||||
examples: [
|
||||
{
|
||||
prompt: "What is AnythingLLM?",
|
||||
prompt: "Check my files for information about the project",
|
||||
call: JSON.stringify({
|
||||
action: "search",
|
||||
content: "What is AnythingLLM?",
|
||||
content: "<project information to search for>",
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -39,13 +39,6 @@ const memory = {
|
||||
content: "I am a robot, the user told me that i am.",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "Save that to memory please.",
|
||||
call: JSON.stringify({
|
||||
action: "store",
|
||||
content: "<insert summary of conversation until now>",
|
||||
}),
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
|
||||
@@ -16,7 +16,12 @@ const rechart = {
|
||||
name: this.name,
|
||||
tracker: new Deduplicator(),
|
||||
description:
|
||||
"Generates the JSON data required to generate a RechartJS chart to the user based on their prompt and available data.",
|
||||
"Create a chart, graph, or data visualization. Generate bar charts, line graphs, pie charts, area charts, or scatter plots to visualize data, statistics, trends, or results. Use to display numbers and data visually.",
|
||||
examples: [
|
||||
{ prompt: "Create a chart from that data" },
|
||||
{ prompt: "Make a bar graph of the results" },
|
||||
{ prompt: "Visualize these numbers" },
|
||||
],
|
||||
parameters: {
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
type: "object",
|
||||
|
||||
@@ -15,32 +15,29 @@ const saveFileInBrowser = {
|
||||
tracker: new Deduplicator(),
|
||||
name: this.name,
|
||||
description:
|
||||
"Save content to a file when the user explicitly asks for a download of the file.",
|
||||
"Download or export content as a file. Save text, code, data, or conversation content to a downloadable file. Use when the user wants to save, download, or export something as a file.",
|
||||
examples: [
|
||||
{
|
||||
prompt: "Download that as a file",
|
||||
call: JSON.stringify({
|
||||
file_content: "<content to save>",
|
||||
filename: "download.txt",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "Save that code to a file",
|
||||
call: JSON.stringify({
|
||||
file_content: "<code content>",
|
||||
filename: "code.js",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "Save me that to a file named 'output'",
|
||||
call: JSON.stringify({
|
||||
file_content:
|
||||
"<content of the file we will write previous conversation>",
|
||||
file_content: "<content of the file>",
|
||||
filename: "output.txt",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "Save me that to my desktop",
|
||||
call: JSON.stringify({
|
||||
file_content:
|
||||
"<content of the file we will write previous conversation>",
|
||||
filename: "<relevant filename>.txt",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "Save me that to a file",
|
||||
call: JSON.stringify({
|
||||
file_content:
|
||||
"<content of the file we will write from previous conversation>",
|
||||
filename: "<descriptive filename>.txt",
|
||||
}),
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
|
||||
@@ -17,26 +17,26 @@ const docSummarizer = {
|
||||
name: this.name,
|
||||
controller: new AbortController(),
|
||||
description:
|
||||
"Can get the list of files available to search with descriptions and can select a single file to open and summarize.",
|
||||
"List all documents in the workspace or summarize a specific document. See what files are available, get a summary of a document's contents, or read and condense a file into key points.",
|
||||
examples: [
|
||||
{
|
||||
prompt: "Summarize example.txt",
|
||||
call: JSON.stringify({
|
||||
action: "summarize",
|
||||
document_filename: "example.txt",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "What files can you see?",
|
||||
prompt: "List my files",
|
||||
call: JSON.stringify({ action: "list", document_filename: null }),
|
||||
},
|
||||
{
|
||||
prompt: "Tell me about readme.md",
|
||||
prompt: "Summarize the readme file",
|
||||
call: JSON.stringify({
|
||||
action: "summarize",
|
||||
document_filename: "readme.md",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "Give me a summary of example.txt",
|
||||
call: JSON.stringify({
|
||||
action: "summarize",
|
||||
document_filename: "example.txt",
|
||||
}),
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
|
||||
@@ -20,19 +20,21 @@ const webBrowsing = {
|
||||
.toString()
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ","),
|
||||
description:
|
||||
"Searches for a given query using a search engine to get better results for the user query.",
|
||||
"Search the internet for real-time information. Look online for current news, recent updates, latest changes, or any information not available locally. Browse the web to find answers about current events, prices, weather, or live data.",
|
||||
examples: [
|
||||
{
|
||||
prompt: "Who won the world series today?",
|
||||
call: JSON.stringify({ query: "Winner of today's world series" }),
|
||||
prompt: "Look online for recent changes to AnythingLLM",
|
||||
call: JSON.stringify({
|
||||
query: "AnythingLLM recent changes updates",
|
||||
}),
|
||||
},
|
||||
{
|
||||
prompt: "What is AnythingLLM?",
|
||||
call: JSON.stringify({ query: "AnythingLLM" }),
|
||||
prompt: "Search the internet for the latest news",
|
||||
call: JSON.stringify({ query: "latest news today" }),
|
||||
},
|
||||
{
|
||||
prompt: "Current AAPL stock price",
|
||||
call: JSON.stringify({ query: "AAPL stock price today" }),
|
||||
prompt: "What's the current weather in NYC?",
|
||||
call: JSON.stringify({ query: "current weather New York City" }),
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
|
||||
@@ -16,8 +16,12 @@ const webScraping = {
|
||||
name: this.name,
|
||||
controller: new AbortController(),
|
||||
description:
|
||||
"Scrapes the content of a webpage or online resource from a provided URL.",
|
||||
"Read and extract content from a specific webpage URL. Fetch the text from a website, get the contents of a link, or visit a URL to see what it says. Use when you have a specific web address to read.",
|
||||
examples: [
|
||||
{
|
||||
prompt: "Read that URL for me",
|
||||
call: JSON.stringify({ url: "https://example.com" }),
|
||||
},
|
||||
{
|
||||
prompt: "What is anythingllm.com about?",
|
||||
call: JSON.stringify({ url: "https://anythingllm.com" }),
|
||||
|
||||
164
server/utils/agents/aibitat/utils/toolReranker.js
Normal file
164
server/utils/agents/aibitat/utils/toolReranker.js
Normal file
@@ -0,0 +1,164 @@
|
||||
const {
|
||||
NativeEmbeddingReranker,
|
||||
} = require("../../../EmbeddingRerankers/native");
|
||||
const { TokenManager } = require("../../../helpers/tiktoken");
|
||||
|
||||
class ToolReranker {
|
||||
/**
|
||||
* The default number of top tools to keep after reranking
|
||||
* @type {number}
|
||||
*/
|
||||
static defaultTopN = 15;
|
||||
|
||||
static instance = null;
|
||||
static #reranker = null;
|
||||
|
||||
constructor() {
|
||||
if (ToolReranker.instance) return ToolReranker.instance;
|
||||
ToolReranker.instance = this;
|
||||
this.tokenManager = new TokenManager();
|
||||
}
|
||||
|
||||
log(text, ...args) {
|
||||
console.log(`\x1b[33m[IntelligentSkillSelector]\x1b[0m ${text}`, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if tool reranking is enabled via environment variable
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isEnabled() {
|
||||
if (!("AGENT_SKILL_RERANKER_ENABLED" in process.env)) return false;
|
||||
if (process.env.AGENT_SKILL_RERANKER_ENABLED === "false") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configured topN value from environment or use default
|
||||
* @returns {number}
|
||||
*/
|
||||
static getTopN() {
|
||||
const envTopN = parseInt(process.env.AGENT_SKILL_RERANKER_TOP_N, 10);
|
||||
return !isNaN(envTopN) && envTopN > 0 ? envTopN : ToolReranker.defaultTopN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create the reranker singleton
|
||||
* @returns {NativeEmbeddingReranker}
|
||||
*/
|
||||
async #getReranker() {
|
||||
if (!ToolReranker.#reranker) {
|
||||
ToolReranker.#reranker = new NativeEmbeddingReranker();
|
||||
await ToolReranker.#reranker.initClient();
|
||||
}
|
||||
return ToolReranker.#reranker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a tool/function definition to a text representation for reranking.
|
||||
* Format follows the best practices benchmark we have: name, description, param descriptions, example prompts
|
||||
* @param {Object} tool - The tool definition object
|
||||
* @returns {{text: string, toolName: string, tool: Object, tokens: number}}
|
||||
*/
|
||||
#toolToDocument(tool) {
|
||||
const parts = [];
|
||||
if (!tool || !tool.name)
|
||||
return { text: null, toolName: null, tool: null, tokens: 0 };
|
||||
|
||||
parts.push(tool.name);
|
||||
if (tool.description) parts.push(tool.description);
|
||||
|
||||
if (tool.parameters?.properties) {
|
||||
const paramNames = Object.keys(tool.parameters.properties);
|
||||
if (paramNames.length > 0) {
|
||||
const paramDescriptions = paramNames.map((name) => {
|
||||
const prop = tool.parameters.properties[name];
|
||||
return prop.description ? `${name}: ${prop.description}` : name;
|
||||
});
|
||||
parts.push(paramDescriptions.join(", "));
|
||||
}
|
||||
}
|
||||
|
||||
// Include example prompts if available (common in aibitat built-in tools)
|
||||
if (
|
||||
tool.examples &&
|
||||
Array.isArray(tool.examples) &&
|
||||
tool.examples.length > 0
|
||||
) {
|
||||
const examplePrompts = tool.examples
|
||||
.map((ex) => ex.prompt)
|
||||
.filter(Boolean);
|
||||
if (examplePrompts.length > 0) {
|
||||
parts.push(examplePrompts.join("; "));
|
||||
}
|
||||
}
|
||||
|
||||
const textContent = parts.join("\n");
|
||||
return {
|
||||
text: textContent,
|
||||
toolName: tool.name,
|
||||
tool,
|
||||
tokens: this.tokenManager.countFromString(textContent),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Rerank tools based on the user prompt and return the top N most relevant tools
|
||||
* @param {string} userPrompt - The user's query/prompt
|
||||
* @param {Object[]} tools - Array of tool/function definitions from aibitat.functions
|
||||
* @param {Object} options - Options for reranking
|
||||
* @param {number} options.topN - (optional) Number of top tools to return (default: ToolReranker.getTopN())
|
||||
* @returns {Promise<Object[]>} - Array of reranked tools (top N)
|
||||
*/
|
||||
async rerank(userPrompt, tools = [], options = {}) {
|
||||
if (!ToolReranker.isEnabled()) return tools;
|
||||
if (!tools || tools.length === 0) return tools;
|
||||
const { topN = ToolReranker.getTopN() } = options;
|
||||
|
||||
if (tools.length <= topN) {
|
||||
this.log(`${tools.length} tools <= ${topN}, skipping reranking`);
|
||||
return tools;
|
||||
}
|
||||
|
||||
try {
|
||||
this.log(`Starting tool reranking for ${tools.length} tools...`);
|
||||
const documents = tools.map((tool) => this.#toolToDocument(tool));
|
||||
const originalTokenCount = documents.reduce(
|
||||
(acc, doc) => acc + doc.tokens,
|
||||
0
|
||||
);
|
||||
|
||||
const startTime = Date.now();
|
||||
const reranker = await this.#getReranker();
|
||||
const rerankedDocs = await reranker.rerank(userPrompt, documents, {
|
||||
topK: topN,
|
||||
});
|
||||
const elapsedMs = Date.now() - startTime;
|
||||
|
||||
const rerankedTools = rerankedDocs.map((doc) => doc.tool);
|
||||
const newTokenCount = rerankedDocs.reduce(
|
||||
(acc, doc) => acc + doc.tokens,
|
||||
0
|
||||
);
|
||||
const percentSaved = Math.round(
|
||||
((originalTokenCount - newTokenCount) / originalTokenCount) * 100
|
||||
);
|
||||
this.log(`
|
||||
Identified top ${rerankedTools.length} of ${tools.length} tools in ${elapsedMs}ms
|
||||
${originalTokenCount.toLocaleString()} -> ${newTokenCount.toLocaleString()} tokens \x1b[0;93m(${percentSaved}% reduction)\x1b[0m`);
|
||||
|
||||
let logText = "Selected tools:\n";
|
||||
rerankedDocs.forEach((doc, index) => {
|
||||
logText += ` ${index + 1}. ${doc.toolName}\n`;
|
||||
});
|
||||
this.log(logText);
|
||||
return rerankedTools;
|
||||
} catch (error) {
|
||||
this.log(`Error during tool reranking: ${error.message}`);
|
||||
this.log("Falling back to original tool set");
|
||||
return tools;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { ToolReranker };
|
||||
@@ -837,6 +837,20 @@ const KEY_MAPPING = {
|
||||
envKey: "LEMONADE_LLM_MODEL_TOKEN_LIMIT",
|
||||
checks: [nonZero],
|
||||
},
|
||||
|
||||
// Agent Skill Settings
|
||||
AgentSkillMaxToolCalls: {
|
||||
envKey: "AGENT_MAX_TOOL_CALLS",
|
||||
checks: [nonZero],
|
||||
},
|
||||
AgentSkillRerankerEnabled: {
|
||||
envKey: "AGENT_SKILL_RERANKER_ENABLED",
|
||||
checks: [],
|
||||
},
|
||||
AgentSkillRerankerTopN: {
|
||||
envKey: "AGENT_SKILL_RERANKER_TOP_N",
|
||||
checks: [nonZero],
|
||||
},
|
||||
};
|
||||
|
||||
function isNotEmpty(input = "") {
|
||||
|
||||
Reference in New Issue
Block a user