agently
Version:
🤵 Agently is a framework helps developers to create amazing LLM based applications. 🎭 You can use it to create an LLM bansed agent instance with role set and memory easily. ⚙️ You can use Agently agent instance just like an async function and put it any
172 lines (171 loc) • 9.32 kB
JavaScript
const format = require('../lib/format')
module.exports = (Agently) => {
Agently.ProcessUnit.Manage
//Generate system message to set agent's role settings
//ONLY WORKS WHEN role HAVE AT LEAST 1 PROPERTY
//input data example:
//role = { 'Character': 'Love smiling and always be positive', 'Profession': 'Science Teacher' }
.generateRole(
(role) => {
let content = `# Role\n`
for (let key in role) {
content += `**${ key }**: ${ role[key] }\n`
}
return { role: 'system', content: content }
}
)
//Generate system message to set agent's status (usually used for game role-play)
//ONLY WORKS WHEN Agent.useStatus() IS STATED
//input data example:
//status = { status: { playerStatus: { HP: 100, SP: 100, MP: 0 } }, getStatus: function() }
//you can use method like getStatus('playerStatus.HP') to get the value of specific property
.generateStatus(
(status) => {
let content = `# Assistant Status\n`
content += format.toJSONString(status.status)
return { role: 'system', content: content }
}
)
//Generate assistant message to tell agent some memories it should remember
//ONLY WORKS WHEN Agent.useMemory() IS STATED
//input data example:
//memories = { 'Experience': 'I lived in countryside in childhood.', 'Friends': 'User and I have a common friend named Sara who lived in LA.' }
.generateMemories(
(memories) => {
let content = `I remember:\n`
for (let key in memories.memories) {
content += `* [${ key }]: ${ format.toJSONString(memories.memories[key]) }\n`
}
return { role: 'assistant', content: content }
}
)
//Generate assistant message to tell agent all skills it can use
//ONLY WORKS WHEN Agent.useSkills() IS STATED
.generateSkillTips(
(agentUsedSkillNameList, completeSkillList) => {
if (agentUsedSkillNameList.length > 0) {
let content = `You can use skills list below:\n# SKILL_LIST\n\n`
for (let i = 0; i < agentUsedSkillNameList.length; i++) {
const skill = completeSkillList[agentUsedSkillNameList[i]]
if (skill) {
content += `## [${ skill.name }]: \n` +
`* desc: ${ skill.desc }\n` +
`* ACTIVE_DATA_FORMAT: ${ format.toJSONString(skill.activeFormat) }\n\n`
}
}
return { role: 'system', content: content }
} else {
return []
}
}
)
.generateSkillJudgePrompt(
(prompt, skillList) => {
return {
role: 'user',
content : `# INPUT\n` +
`input = ${ JSON.stringify(prompt.input) }\n\n` +
`# OUTPUT PROCESS RULE\n` +
`Judge if to reply #INPUT, which skills you want to use?\n` +
`OUTPUT JSON ONLY that can be parsed by python.\n` +
`If you don't want to use skills, output []\n\n` +
`# OUTPUT FORMAT\n\n` +
`TYPE: JSON\n\n` +
`FORMAT DEFINITION:\n\n` +
`\`\`\`JSON\n` +
format.toJSONString([
{
skillName: '<String>,//MUST USE skill name in #SKILL_LIST',
data: '<any>,//MUST IN ##{callSkillName}.{ACTIVE_DATA_FORMAT} IF IT IS NOT null!'
},
]) +
`\n\`\`\`\n\n` +
`# OUTPUT\n` +
`output = `
}
}
)
//Generate context messages (usually saved in multi-round chat or appendContext()/coverContext() by user)
//ONLY WORKS WHEN AgentSession.setLoadContext(true) IS SET
//input data example:
//context = { full: [Messages of full context], request: [Messages used to request last time] }
.generateContext(
(context) => context.request
)
//Method to shorten context messages if it is to long (exceed maxContentLength)
//By default, this method will cut messages from the earliest ones to the most recent ones.
//You can change this method to summarize or whatever you want
.shortenContext(
(requestContext, fullContext, maxContentLength) => {
let newContext = Array.from(requestContext)
for (let i = 0; i < newContext.length; i++) {
if (JSON.stringify(newContext).length <= maxContentLength) break
newContext.splice(i, 1)
i--
}
return newContext
}
)
//Generate user message for current request prompt
//If user only state AgentSession.input() then .start(), it will simply generate { role: 'user', content: prompt.input }
//Or it will generate prompt with structure
//input data example:
//prompt = {
// input: <String | Object>,
// prompt: <Array of { title: <String>, content: <String> }>,/*Each item is a paragraph of prompt with title and content>*/
// output: { desc: <String | Object>, type: <String, optional> },/*If desc is Object and type is undefined, type will be set to 'JSON' by default. Only works when multiOutput is not stated.*/
// multiOutput: <Array of { title: <String>, desc: <String | Object>, type: <String> }>,/*Each item is a segment of output*/
//}
.generatePrompt(
(prompt) => {
if (prompt.input && prompt.prompt.length === 0 && !prompt.output && prompt.multiOutput.length === 0) {
return { role: 'user', content: prompt.input }
} else {
let content = '# INPUT\n'
content += `input = ${ JSON.stringify(prompt.input) }\n\n`
for (let i = 0; i < prompt.prompt.length; i++) {
content += `# ${ prompt.prompt[i].title }\n${ format.toJSONString(prompt.prompt[i].content) }\n`
}
content += '\n'
if (prompt.multiOutput.length > 0) {
content += `# OUTPUT FORMAT\n\n` +
`## RULE\nEach output block must be warp by tag "<$$$node={nodeValue}>...</$$$>"!\n\n` +
`## FULL OUTPUT CONTENT\n`
for (let i = 0; i < prompt.multiOutput.length; i++) {
content += `<$$$node=${ prompt.multiOutput[i].title }>\n`
if (!prompt.multiOutput[i].type) {
if (Object.prototype.toString.call(prompt.multiOutput[i].desc) === '[object Object]') {
prompt.multiOutput[i].type = 'JSON'
} else {
prompt.multiOutput[i].type = 'customize'
}
}
if (prompt.multiOutput[i].type === 'JSON') {
content += `TYPE: ${ prompt.multiOutput[i].type } can be parsed in Python\n\nFORMAT DEFINITION:\n\n\`\`\`${ prompt.multiOutput[i].type }\n${ format.toJSONString(prompt.multiOutput[i].desc) }\n\`\`\`\n\n`
} else {
content += `\`\`\`${ prompt.multiOutput[i].type }\n${ prompt.multiOutput[i].desc }\n\`\`\`\n\n`
}
content += `</$$$>\n\n`
}
} else if (prompt.output) {
content += '# OUTPUT FORMAT\n\n'
if (!prompt.output.type) {
if (Object.prototype.toString.call(prompt.output.desc) === '[object Object]') {
prompt.output.type = 'JSON'
} else {
prompt.output.type = 'customize'
}
}
if (prompt.output.type === 'JSON') {
content += `TYPE: ${ prompt.output.type } can be parsed in Python\n\nFORMAT DEFINITION:\n\n\`\`\`${ prompt.output.type }\n${ format.toJSONString(prompt.output.desc) }\n\`\`\`\n\n`
} else {
content += `\`\`\`${ prompt.output.type }\n${ prompt.output.desc }\n\`\`\`\n\n`
}
}
content += `# OUTPUT\n\noutput = `
return { role: 'user', content: content }
}
}
)
.register()
}