diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts
index 91de4f4c..92b32b59 100644
--- a/packages/server/src/index.ts
+++ b/packages/server/src/index.ts
@@ -64,6 +64,9 @@ import { ChatflowPool } from './ChatflowPool'
import { CachePool } from './CachePool'
import { ICommonObject, INodeOptionsValue } from 'flowise-components'
import { createRateLimiter, getRateLimiter, initializeRateLimiter } from './utils/rateLimit'
+import axios from 'axios'
+import { Client } from 'langchainhub'
+import { parsePrompt } from './utils/hub'
export class App {
app: express.Application
@@ -1093,6 +1096,43 @@ export class App {
await this.buildChatflow(req, res, undefined, true, true)
})
+ // ----------------------------------------
+ // Prompt from Hub
+ // ----------------------------------------
+ this.app.post('/api/v1/load-prompt', async (req: Request, res: Response) => {
+ try {
+ const credential = await this.AppDataSource.getRepository(Credential).findOneBy({
+ id: req.body.credential
+ })
+
+ if (!credential) return res.status(404).json({ error: `Credential ${req.body.credential} not found` })
+
+ // Decrypt credentialData
+ const decryptedCredentialData = await decryptCredentialData(credential.encryptedData, credential.credentialName, undefined)
+ let hub = new Client({ apiKey: decryptedCredentialData.langsmithApiKey, apiUrl: decryptedCredentialData.langsmithEndpoint })
+ const prompt = await hub.pull(req.body.promptName)
+ const templates = parsePrompt(prompt)
+
+ return res.json({ status: 'OK', prompt: req.body.promptName, templates: templates })
+ } catch (e: any) {
+ return res.json({ status: 'ERROR', prompt: req.body.promptName, error: e?.message })
+ }
+ })
+
+ this.app.post('/api/v1/prompts-list', async (req: Request, res: Response) => {
+ try {
+ const tags = req.body.tags ? `tags=${req.body.tags}` : ''
+ const url = `https://web.hub.langchain.com/repos/?${tags}offset=0&limit=20&has_commits=true&sort_field=num_likes&sort_direction=desc&is_archived=false`
+ axios.get(url).then((response) => {
+ if (response.data.repos) {
+ return res.json({ status: 'OK', repos: response.data.repos })
+ }
+ })
+ } catch (e: any) {
+ return res.json({ status: 'ERROR', repos: [] })
+ }
+ })
+
// ----------------------------------------
// Prediction
// ----------------------------------------
diff --git a/packages/server/src/utils/hub.ts b/packages/server/src/utils/hub.ts
new file mode 100644
index 00000000..79e7136f
--- /dev/null
+++ b/packages/server/src/utils/hub.ts
@@ -0,0 +1,27 @@
+export function parsePrompt(prompt: string): any[] {
+ const promptObj = JSON.parse(prompt)
+ let response = []
+ if (promptObj.kwargs.messages) {
+ promptObj.kwargs.messages.forEach((message: any) => {
+ let messageType = message.id.includes('SystemMessagePromptTemplate')
+ ? 'systemMessagePrompt'
+ : message.id.includes('HumanMessagePromptTemplate')
+ ? 'humanMessagePrompt'
+ : message.id.includes('AIMessagePromptTemplate')
+ ? 'aiMessagePrompt'
+ : 'template'
+ let template = message.kwargs.prompt.kwargs.template
+ response.push({
+ type: messageType,
+ template: template
+ })
+ })
+ } else if (promptObj.kwargs.template) {
+ let template = promptObj.kwargs.template
+ response.push({
+ type: 'template',
+ template: template
+ })
+ }
+ return response
+}
diff --git a/packages/ui/src/api/prompt.js b/packages/ui/src/api/prompt.js
new file mode 100644
index 00000000..42b1bdbc
--- /dev/null
+++ b/packages/ui/src/api/prompt.js
@@ -0,0 +1,9 @@
+import client from './client'
+
+const getAvailablePrompts = (body) => client.post(`/prompts-list`, body)
+const getPrompt = (body) => client.post(`/load-prompt`, body)
+
+export default {
+ getAvailablePrompts,
+ getPrompt
+}
diff --git a/packages/ui/src/ui-component/dialog/PromptLangsmithHubDialog.js b/packages/ui/src/ui-component/dialog/PromptLangsmithHubDialog.js
index 16d5c30f..4db61633 100644
--- a/packages/ui/src/ui-component/dialog/PromptLangsmithHubDialog.js
+++ b/packages/ui/src/ui-component/dialog/PromptLangsmithHubDialog.js
@@ -25,9 +25,9 @@ import { useDispatch } from 'react-redux'
import FormControl from '@mui/material/FormControl'
import Checkbox from '@mui/material/Checkbox'
import MenuItem from '@mui/material/MenuItem'
-import axios from 'axios'
import ReactMarkdown from 'react-markdown'
import CredentialInputHandler from '../../views/canvas/CredentialInputHandler'
+import promptApi from '../../api/prompt'
const PromptLangsmithHubDialog = ({ promptType, show, onCancel }) => {
const portalElement = document.getElementById('portal')
@@ -96,13 +96,24 @@ const PromptLangsmithHubDialog = ({ promptType, show, onCancel }) => {
{ id: 306, name: 'Spanish' }
]
const [language, setLanguage] = useState([])
- const [prompts, setPrompts] = useState([])
+ const [availablePrompNameList, setAvailablePrompNameList] = useState([])
const [selectedPrompt, setSelectedPrompt] = useState({})
const [credentialId, setCredentialId] = useState('')
- const handleListItemClick = (event, index) => {
- setSelectedPrompt(prompts[index])
+ const handleListItemClick = async (event, index) => {
+ const prompt = availablePrompNameList[index]
+
+ if (!prompt.detailed) {
+ const createResp = await promptApi.getPrompt({
+ credential: credentialId,
+ promptName: selectedPrompt.full_name
+ })
+ if (createResp.data) {
+ prompt.detailed = createResp.data.templates
+ }
+ }
+ setSelectedPrompt(prompt)
}
const fetchPrompts = async () => {
@@ -116,17 +127,15 @@ const PromptLangsmithHubDialog = ({ promptType, show, onCancel }) => {
language.forEach((item) => {
tags += `tags=${item.name}&`
})
- const url = `https://web.hub.langchain.com/repos/?${tags}offset=0&limit=20&has_commits=true&sort_field=num_likes&sort_direction=desc&is_archived=false`
- axios.get(url).then((response) => {
- if (response.data.repos) {
- setPrompts(response.data.repos)
- // response.data.repos.forEach((item) => {
- // console.log(item)
- // })
- }
+ const createResp = await promptApi.getAvailablePrompts({
+ credential: credentialId,
+ tags: tags
})
- // latestReleaseReq.then()
+ if (createResp.data) {
+ setAvailablePrompNameList(createResp.data.repos)
+ }
}
+
const removeDuplicates = (value) => {
let duplicateRemoved = []
@@ -173,26 +182,29 @@ const PromptLangsmithHubDialog = ({ promptType, show, onCancel }) => {
Load Prompts from Langsmith Hub ({promptType === 'template' ? 'PromptTemplate' : 'ChatPromptTemplate'})
-
-
+
+
Langsmith Credential
*
- {
- setCredentialId(newValue)
- }}
- />
+
+ {
+ setCredentialId(newValue)
+ }}
+ />
+
{
Model