diff --git a/config_template.yaml b/config_template.yaml index fedd3b642..51c090dec 100644 --- a/config_template.yaml +++ b/config_template.yaml @@ -4,6 +4,8 @@ PINECONE_ENVIRONMENT: YOUR_PINECONE_ENVIRONMENT OPENAI_API_KEY: YOUR_OPEN_API_KEY PALM_API_KEY: YOUR_PALM_API_KEY +REPLICATE_API_TOKEN: YOUR_REPLICATE_API_TOKEN +HUGGING_API_TOKEN: YOUR_HUGGING_FACE_API_TOKEN # For locally hosted LLMs comment out the next line and uncomment the one after # to configure a local llm point your browser to 127.0.0.1:7860 and click on the model tab in text generation web ui. diff --git a/gui/pages/Content/APM/ApmDashboard.js b/gui/pages/Content/APM/ApmDashboard.js index 314ddc915..d56f12466 100644 --- a/gui/pages/Content/APM/ApmDashboard.js +++ b/gui/pages/Content/APM/ApmDashboard.js @@ -75,7 +75,7 @@ export default function ApmDashboard() { const fetchData = async () => { try { const [metricsResponse, agentsResponse, activeRunsResponse, toolsUsageResponse] = await Promise.all([getMetrics(), getAllAgents(), getActiveRuns(), getToolsUsage()]); - const models = ['gpt-4', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-4-32k', 'google-palm-bison-001']; + const models = ['gpt-4', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-4-32k', 'google-palm-bison-001', 'replicate-llama13b-v2-chat']; assignDefaultDataPerModel(metricsResponse.data.agent_details.model_metrics, models); assignDefaultDataPerModel(metricsResponse.data.tokens_details.model_metrics, models); diff --git a/gui/pages/Content/Agents/AgentCreate.js b/gui/pages/Content/Agents/AgentCreate.js index 3f7f62b30..4d2849042 100644 --- a/gui/pages/Content/Agents/AgentCreate.js +++ b/gui/pages/Content/Agents/AgentCreate.js @@ -10,8 +10,8 @@ import { getLlmModels, updateExecution, uploadFile, - getAgentDetails, addAgentRun, - getAgentWorkflows + getAgentDetails, addAgentRun, fetchModels, + getAgentWorkflows, validateOrAddModels } from "@/pages/api/DashboardService"; import { formatBytes, @@ -56,6 +56,7 @@ export default function AgentCreate({ const [searchValue, setSearchValue] = useState(''); const [showButton, setShowButton] = useState(false); const [showPlaceholder, setShowPlaceholder] = useState(true); + const [modelsArray, setModelsArray] = useState(['gpt-4', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k']); const constraintsArray = [ "If you are unsure how you previously did something or want to recall past events, thinking about similar events will help you remember.", @@ -68,8 +69,8 @@ export default function AgentCreate({ const [goals, setGoals] = useState(['Describe the agent goals here']); const [instructions, setInstructions] = useState(['']); - const [modelsArray, setModelsArray] = useState([]); - const [model, setModel] = useState(''); + const models = ['gpt-4', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k'] + const [model, setModel] = useState(models[1]); const modelRef = useRef(null); const [modelDropdown, setModelDropdown] = useState(false); @@ -150,9 +151,9 @@ export default function AgentCreate({ }, [toolNames]); useEffect(() => { - getLlmModels() + fetchModels() .then((response) => { - const models = response.data || []; + const models = response.data.map(model => model.name) || []; const selected_model = localStorage.getItem("agent_model_" + String(internalId)) || ''; setModelsArray(models); if (models.length > 0 && !selected_model) { @@ -160,6 +161,7 @@ export default function AgentCreate({ } else { setModel(selected_model); } + console.log(response) }) .catch((error) => { console.error('Error fetching models:', error); @@ -350,8 +352,8 @@ export default function AgentCreate({ const handleModelSelect = (index) => { setLocalStorageValue("agent_model_" + String(internalId), modelsArray[index], setModel); - if (modelsArray[index] === "google-palm-bison-001") { - setAgentWorkflow("Fixed Task Queue") + if (modelsArray[index] === "google-palm-bison-001" || modelsArray[index] === "replicate-llama13b-v2-chat") { + setAgentType("Fixed Task Queue") } setModelDropdown(false); }; @@ -492,7 +494,7 @@ export default function AgentCreate({ return true; } - const handleAddAgent = () => { + const handleAddAgent = async () => { if (!validateAgentData(true)) { return; } @@ -869,6 +871,11 @@ export default function AgentCreate({ return false; } + const openModelMarket = () => { + openNewTab(-4, "Marketplace", "Marketplace", false); + localStorage.setItem('marketplace_tab', 'market_models'); + } + return (<>
@@ -941,13 +948,28 @@ export default function AgentCreate({ alt="expand-icon"/>
- {modelDropdown &&
- {modelsArray?.map((model, index) => ( -
handleModelSelect(index)} - style={{padding: '12px 14px', maxWidth: '100%'}}> - {model} -
))} -
} + {modelDropdown && ( +
+
+ {modelsArray?.map((model, index) => ( +
handleModelSelect(index)} + style={{padding: '12px 14px', maxWidth: '100%'}}> + {model} +
+ ))} +
+
+
openModelMarket()} className="custom_select_option horizontal_container mxw_100 padding_12_14 gap_6 bt_white"> + marketplace_logo + Browse models from marketplace +
+
openNewTab(-5, "new model", "Add_Model", false)} className="custom_select_option horizontal_container mxw_100 padding_12_14 gap_6 bt_white"> + plus_image + Add new custom model +
+
+
+ )}
diff --git a/gui/pages/Content/Agents/AgentTemplatesList.js b/gui/pages/Content/Agents/AgentTemplatesList.js index 0dedde4b2..797383b04 100644 --- a/gui/pages/Content/Agents/AgentTemplatesList.js +++ b/gui/pages/Content/Agents/AgentTemplatesList.js @@ -74,9 +74,9 @@ export default function AgentTemplatesList({
- {agentTemplates.length > 0 ?
+ {agentTemplates.length > 0 ?
{agentTemplates.map((item) => ( -
handleTemplateClick(item)}>
{item.name}
@@ -84,7 +84,7 @@ export default function AgentTemplatesList({
))} -
diff --git a/gui/pages/Content/Agents/AgentWorkspace.js b/gui/pages/Content/Agents/AgentWorkspace.js index 898bf6efb..736ac6f50 100644 --- a/gui/pages/Content/Agents/AgentWorkspace.js +++ b/gui/pages/Content/Agents/AgentWorkspace.js @@ -290,7 +290,7 @@ export default function AgentWorkspace({env, agentId, agentName, selectedView, a // } function saveAgentTemplate() { - saveAgentAsTemplate(selectedRun?.id) + saveAgentAsTemplate(agentId, selectedRun?.id ? selectedRun?.id : -1) .then((response) => { toast.success("Agent saved as template successfully", {autoClose: 1800}); }) diff --git a/gui/pages/Content/Marketplace/Market.js b/gui/pages/Content/Marketplace/Market.js index 55d89fe90..9ab03a4ed 100644 --- a/gui/pages/Content/Marketplace/Market.js +++ b/gui/pages/Content/Marketplace/Market.js @@ -4,7 +4,9 @@ import styles from './Market.module.css'; import MarketKnowledge from './MarketKnowledge'; import MarketAgent from './MarketAgent'; import MarketTools from './MarketTools'; +import MarketModels from '../Models/MarketModels'; import ToolkitTemplate from './ToolkitTemplate'; +import ModelTemplate from "../Models/ModelTemplate"; import {EventBus} from "@/utils/eventBus"; import AgentTemplate from "./AgentTemplate"; import KnowledgeTemplate from "./KnowledgeTemplate"; @@ -64,48 +66,36 @@ export default function Market({env}) {
-
- -
-
- -
-
- -
+ + + +
{activeTab === 'market_tools' && } {activeTab === 'market_knowledge' && } {activeTab === 'market_agents' && } + {activeTab === 'market_models' && }
:
{detailType === 'agent_template' && } {detailType === 'knowledge_template' && } {detailType === 'tool_template' && } + {detailType === 'model_template' && }
}
); diff --git a/gui/pages/Content/Marketplace/Market.module.css b/gui/pages/Content/Marketplace/Market.module.css index 4bd162ade..c309f41cd 100644 --- a/gui/pages/Content/Marketplace/Market.module.css +++ b/gui/pages/Content/Marketplace/Market.module.css @@ -290,7 +290,7 @@ display: flex; justify-content: flex-start; flex-wrap: wrap; - gap: 0.3vw; + gap: 6px; } .agent_resources { diff --git a/gui/pages/Content/Marketplace/MarketAgent.js b/gui/pages/Content/Marketplace/MarketAgent.js index 53fa3f34f..3055ebd27 100644 --- a/gui/pages/Content/Marketplace/MarketAgent.js +++ b/gui/pages/Content/Marketplace/MarketAgent.js @@ -1,6 +1,5 @@ import React, {useEffect, useState} from "react"; import Image from "next/image"; -import styles from './Market.module.css'; import {fetchAgentTemplateList} from "@/pages/api/DashboardService"; import {EventBus} from "@/utils/eventBus"; import {loadingTextEffect} from "@/utils/utils"; @@ -48,8 +47,8 @@ export default function MarketAgent() {
{!isLoading ?
- {agentTemplates.length > 0 ?
{agentTemplates.map((item, index) => ( -
handleTemplateClick(item)}> + {agentTemplates.length > 0 ?
{agentTemplates.map((item, index) => ( +
handleTemplateClick(item)}>
{item.name}
by SuperAgi 
{!isLoading ?
- {knowledgeTemplates.length > 0 ?
{knowledgeTemplates.map((item, index) => ( -
0 ?
{knowledgeTemplates.map((item, index) => ( +
handleTemplateClick(item)}>
diff --git a/gui/pages/Content/Marketplace/MarketTools.js b/gui/pages/Content/Marketplace/MarketTools.js index 87a140d4e..90d1cbccd 100644 --- a/gui/pages/Content/Marketplace/MarketTools.js +++ b/gui/pages/Content/Marketplace/MarketTools.js @@ -1,6 +1,5 @@ import React, {useEffect, useState} from "react"; import Image from "next/image"; -import styles from './Market.module.css'; import {fetchToolTemplateList} from "@/pages/api/DashboardService"; import {EventBus} from "@/utils/eventBus"; import {loadingTextEffect, excludedToolkits, returnToolkitIcon} from "@/utils/utils"; @@ -50,8 +49,8 @@ export default function MarketTools() {
{!isLoading ?
- {toolTemplates.length > 0 ?
{toolTemplates.map((item) => ( -
handleTemplateClick(item)}> + {toolTemplates.length > 0 ?
{toolTemplates.map((item) => ( +
handleTemplateClick(item)}>
tool-icon
diff --git a/gui/pages/Content/Models/AddModel.js b/gui/pages/Content/Models/AddModel.js new file mode 100644 index 000000000..e596cb80c --- /dev/null +++ b/gui/pages/Content/Models/AddModel.js @@ -0,0 +1,17 @@ +import React, {useEffect, useState} from "react"; +import ModelForm from "./ModelForm"; + +export default function AddModel({internalId, getModels, sendModelData}){ + + return( +
+
+
+
+ +
+
+
+
+ ) +} \ No newline at end of file diff --git a/gui/pages/Content/Models/AddModelMarketPlace.js b/gui/pages/Content/Models/AddModelMarketPlace.js new file mode 100644 index 000000000..6365c06ba --- /dev/null +++ b/gui/pages/Content/Models/AddModelMarketPlace.js @@ -0,0 +1,116 @@ +import React, {useState, useEffect} from "react"; +import Image from "next/image"; +import {openNewTab, modelIcon} from "@/utils/utils"; +import {fetchApiKey, storeModel} from "@/pages/api/DashboardService"; +import {toast} from "react-toastify"; + +export default function AddModelMarketPlace(template){ + const [modelTokenLimit, setModelTokenLimit] = useState(4096); + const [modelVersion, setModelVersion] = useState(''); + const [modelEndpoint, setModelEndpoint] = useState(''); + const [tokenError, setTokenError] = useState(false); + const [templateData, setTemplateData] = useState(template.template); + const [isLoading, setIsLoading] = useState(false); + const [providerId, setProviderId] = useState(1); + const [disableInstall, setDisableInstall] = useState(false); + + useEffect(() => { + if(modelVersion === '' && modelEndpoint === '') + setDisableInstall(true) + else + setDisableInstall(false) + },[modelVersion, modelEndpoint]) + + useEffect(()=>{ + console.log(templateData) + checkModelProvider().then().catch(); + },[]) + + const checkModelProvider = async () => { + const response = await fetchApiKey(templateData.provider); + console.log(response.data) + if(response.data.length === 0) { + setTokenError(true) + return true + } + else { + setTokenError(false) + setProviderId(response.data[0].id) + return false + } + } + + const storeModelDetails = () => { + storeModel(templateData.model_name, templateData.description, modelEndpoint, providerId, modelTokenLimit, "Marketplace", modelVersion).then((response) =>{ + setIsLoading(false) + console.log(response) + if (response.data.error) { + toast.error(response.data.error,{autoClose: 1800}); + } else if (response.data.success) { + toast.success(response.data.success,{autoClose: 1800}); + } + }).catch((error) => { + console.log("SORRY, There was an error storing the model details" + error); + setIsLoading(false) + }); + } + + return( +
+
+
+
+ Add Model + +
+ {templateData.model_name} +
+ By {templateData.provider} ·  + logo-icon + {templateData.provider} +
+
+ {templateData.provider === 'Hugging Face' &&
+ {templateData.provider} Model Endpoint + setModelEndpoint(event.target.value)}/> +
} + + {templateData.provider === 'Replicate' &&
+ {templateData.provider} Version + setModelVersion(event.target.value)}/> +
} + + Token Limit + setModelTokenLimit(+event.target.value)} /> + + {tokenError &&
+ error-icon +
+ The {templateData.provider} auth token is not added to your settings. In order to start using the model, you need to add the auth token to your settings. You can find the auth token in the {templateData.provider} dashboard. +
+ + +
+
+
} + + {templateData.provider === 'Hugging Face' &&
+ error-icon +
+ In order to get the endpoint for this model, you will need to deploy it on your Replicate dashboard. Once you have deployed your model on Hugging Face, you will be able to access the endpoint through the Hugging Face dashboard. The endpoint is a URL that you can use to send requests to your model. + +
+
} + + +
+
+
+
+ ) +} \ No newline at end of file diff --git a/gui/pages/Content/Models/MarketModels.js b/gui/pages/Content/Models/MarketModels.js new file mode 100644 index 000000000..5b864febf --- /dev/null +++ b/gui/pages/Content/Models/MarketModels.js @@ -0,0 +1,57 @@ +import React, {useState, useEffect} from "react"; +import styles from "@/pages/Content/Marketplace/Market.module.css"; +import Image from "next/image"; +import {loadingTextEffect, modelIcon, returnToolkitIcon} from "@/utils/utils"; +import {EventBus} from "@/utils/eventBus"; +import {fetchMarketPlaceModel} from "@/pages/api/DashboardService"; + +export default function MarketModels(){ + const [showMarketplace, setShowMarketplace] = useState(false); + const [isLoading, setIsLoading] = useState(false) + const [loadingText, setLoadingText] = useState("Loading Models"); + const [modelTemplates, setModelTemplates] = useState([]); + + useEffect(() => { + loadingTextEffect('Loading Models', setLoadingText, 500); + },[]); + + useEffect(() => { + fetchMarketPlaceModel().then((response) => { + console.log(response.data) + setModelTemplates(response.data) + }) + },[]) + + function handleTemplateClick(item) { + const contentType = 'model_template'; + EventBus.emit('openTemplateDetails', {item, contentType}); + } + + return( +
+
+ {!isLoading ?
+ {modelTemplates.length > 0 ?
{modelTemplates.map((item) => ( +
handleTemplateClick(item)}> +
{item.model_name && item.model_name.includes('/') ? item.model_name.split('/')[1] : item.model_name}
+
+ by { item.model_name && item.model_name.includes('/') ? item.model_name.split('/')[0] : item.provider } + is_verified· + source-icon + {item.provider}· + download-icon + {item.installs} +
+
{item.description}
+
+ ))}
:
+ no-permissions + No Models found! +
} +
:
+
{loadingText}
+
} +
+
+ ) +} \ No newline at end of file diff --git a/gui/pages/Content/Models/ModelDetails.js b/gui/pages/Content/Models/ModelDetails.js new file mode 100644 index 000000000..751b50568 --- /dev/null +++ b/gui/pages/Content/Models/ModelDetails.js @@ -0,0 +1,41 @@ +import React, {useState, useEffect} from "react"; +import Image from "next/image"; +import ModelMetrics from "./ModelMetrics"; +import ModelInfo from "./ModelInfo"; +import {fetchModel} from "@/pages/api/DashboardService"; + +export default function ModelDetails({modelId, modelName}){ + const [modelDetails, setModelDetails] = useState([]) + const [selectedOption, setSelectedOption] = useState('metrics') + + useEffect(() => { + const fetchModelDetails = async () => { + try { + const response = await fetchModel(modelId); + console.log(response.data) + setModelDetails(response.data) + } catch(error) { + console.log(`Error Fetching the Details of the Model ${modelName}`, error) + } + }; + + fetchModelDetails().then().catch(); + },[]) + + return( +
+
+ { modelDetails.name ? (modelDetails.name.split('/')[1] || modelDetails.name) : ""} + {modelDetails.description} +
+ + +
+
+ {selectedOption === 'metrics' && } + {selectedOption === 'details' && } +
+ ) +} \ No newline at end of file diff --git a/gui/pages/Content/Models/ModelForm.js b/gui/pages/Content/Models/ModelForm.js new file mode 100644 index 000000000..b157296d3 --- /dev/null +++ b/gui/pages/Content/Models/ModelForm.js @@ -0,0 +1,177 @@ +import React, {useEffect, useRef, useState} from "react"; +import {removeTab, openNewTab, createInternalId} from "@/utils/utils"; +import Image from "next/image"; +import {fetchApiKey, storeModel, verifyEndPoint} from "@/pages/api/DashboardService"; +import {BeatLoader, ClipLoader} from "react-spinners"; +import {ToastContainer, toast} from 'react-toastify'; + +export default function ModelForm({internalId, getModels, sendModelData}){ + const models = [{'provider':'OpenAI','link':'https://platform.openai.com/account/api-keys'}, + {'provider':'Replicate','link':'https://huggingface.co/settings/tokens'}, + {'provider':'Hugging Face','link':'https://huggingface.co/settings/tokens'}, + {'provider':'Google Palm','link':'https://developers.generativeai.google/products/palm'}]; + const [selectedModel, setSelectedModel] = useState('Select a Model'); + const [selectedLink, setSelectedLink] = useState(''); + const [modelName, setModelName] = useState(''); + const [modelDescription, setModelDescription] = useState(''); + const [modelTokenLimit, setModelTokenLimit] = useState(4096); + const [modelEndpoint, setModelEndpoint] = useState(''); + const [modelDropdown, setModelDropdown] = useState(false); + const [modelVersion, setModelVersion] = useState(''); + const [tokenError, setTokenError] = useState(false); + const [lockAddition, setLockAddition] = useState(true); + const [isLoading, setIsLoading] = useState(false) + const modelRef = useRef(null); + + useEffect(() => { + function handleClickOutside(event) { + if (modelRef.current && !modelRef.current.contains(event.target)) { + setModelDropdown(false) + } + } + },[]); + + useEffect(() => { + const fetchMyAPI = async () => { + const error = await checkModelProvider(selectedModel) + if(selectedModel !== 'Select a Model' && !error) + setLockAddition(false) + else + setLockAddition(true) + } + + fetchMyAPI(); + },[selectedModel]) + + const handleModelSelect = async (index) => { + setSelectedModel(models[index].provider) + setSelectedLink(models[index].link) + setModelDropdown(false); + } + + const checkModelProvider = async (model_provider) => { + const response = await fetchApiKey(model_provider); + console.log(response.data) + if(selectedModel !== 'Select a Model'){ + if(response.data.length === 0) { + setTokenError(true) + return true + } + else { + setTokenError(false) + return false + } + } + } + + const handleAddModel = () =>{ + setIsLoading(true) + fetchApiKey(selectedModel).then((response) =>{ + if(response.data.length > 0) + { + const modelProviderId = response.data[0].id + verifyEndPoint(response.data[0].api_key, modelEndpoint, selectedModel).then((response) =>{ + if(response.data.success) + storeModelDetails(modelProviderId) + else{ + toast.error("The Endpoint is not Valid",{autoClose: 1800}); + setIsLoading(false); + } + }).catch((error) => { + console.log("Error Message:: " + error) + }) + } + }) + } + + const handleModelSuccess = (model) => { + model.contentType = 'Model' + sendModelData(model) + } + + const storeModelDetails = (modelProviderId) => { + storeModel(modelName,modelDescription, modelEndpoint, modelProviderId, modelTokenLimit, "Custom", modelVersion).then((response) =>{ + setIsLoading(false) + let data = response.data + if (data.error) { + toast.error(data.error,{autoClose: 1800}); + } else if (data.success) { + toast.success(data.success,{autoClose: 1800}); + getModels() + handleModelSuccess({id: data.model_id, name: modelName}) + } + }).catch((error) => { + console.log("SORRY, There was an error storing the model details:", error); + setIsLoading(false) + }); + } + + return( +
+
Add new model
+ + Name + setModelName(event.target.value)}/> + + Description +