agenty
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
330 lines (283 loc) • 10.1 kB
JavaScript
const { v4: uuidv4 } = require('uuid')
class AgentSession {
constructor (sessionSettings, Agent) {
const self = this
this.id = uuidv4()
this.context = {
full: [],
request: [],
}
this.debug = (content) => { if (this.sessionSettings.debug) Agent.debug(content) }
this.agentSettings = Agent.agentSettings
this.getAgentSettings = () => Agent.agentSettings
this.getMemories = Agent.getMemories
this.getMemory = Agent.getMemory
this.getStatus = Agent.getStatus
this.sessionSettings = {
loadContext: this.agentSettings.loadSessionContext || true,
saveContext: this.agentSettings.saveSessionContext || true,
saveFullPrompt: this.agentSettings.saveFullPrompt || false,
maxContextLength: this.agentSettings.maxContextLength || 3000,
debug: this.agentSettings.debug || false,
}
sessionSettings = sessionSettings || {}
for (let key in sessionSettings) {
this.sessionSettings[key] = sessionSettings[key]
}
this.getSessionSettings = () => self.sessionSettings
this.prompt = {}
this.getPrompt = () => self.prompt
this.responseHandlers = []
this.getResponseHandlers = () => self.responseHandlers
this.streamingHandlers = []
this.getStreamingHandlers = () => self.streamingHandlers
this.runtime = {}
this.initRuntime()
this.Request = Agent.ProcessUnit.Request(this)
}
setDebug (isDebug) {
this.sessionSettings.debug = isDebug
return this
}
initRuntime () {
this.prompt = {
input: undefined,
prompt: [],
output: undefined,
multiOutput: [],
}
this.responseHandlers = []
this.streamingHandlers = []
this.runtime = {}
}
//Manage Context
setLoadContext (isLoadContext) {
this.sessionSettings.loadSessionsContext = isLoadContext
return this
}
setSaveContext (isSaveContext) {
this.sessionSettings.saveSessionsContext = isSaveContext
return this
}
setSaveFullPrompt (isSaveFullPrompt) {
this.sessionSettings.saveFullPrompt = isSaveFullPrompt
return this
}
setMaxContextLength (maxContextLength) {
this.sessionSettings.maxContextLength = maxContextLength
return this
}
appendContext (contextMessages) {
if (!(contextMessages instanceof Array)) contextMessages = [contextMessages]
this.context.full = this.context.full.concat(contextMessages)
this.context.request = this.context.request.concat(contextMessages)
return this
}
coverContext (contextMessages) {
contextMessages = contextMessages || []
if (!(contextMessages instanceof Array)) contextMessages = [contextMessages]
this.context.full = contextMessages
this.context.request = contextMessages
return this
}
//Prompt
input (inputDesc) {
this.prompt.input = inputDesc
//console.log(this.prompt)
return this
}
instruct (title, content) {
this.prompt.prompt.push({ title: title, content: content })
return this
}
output (desc, type) {
this.prompt.output = { desc: desc, type: type }
return this
}
multiOutput (title, desc, type) {
type = type || (Object.prototype.toString.call(desc) === '[object Object]') ? 'JSON' : 'text'
this.prompt.multiOutput.push({ title: title, desc: desc, type: type })
return this
}
//Handle Response
addResponseHandler (responseHandler) {
if (responseHandler) this.responseHandlers.push(responseHandler)
return this
}
//Handle Streaming
addStreamingHandler (streamingHandler) {
if (streamingHandler) {
if (streamingHandler.node) {
this.streamingHandlers.push(streamingHandler)
} else {
this.streamingHandlers.push({
node: null,
handler: streamingHandler
})
}
}
return this
}
//Streaming Flow Syntactic Sugar
flow (flowDesc) {
flowDesc = {
node: flowDesc.node || uuidv4(),
desc: flowDesc.desc,
type: flowDesc.type || (Object.prototype.toString.call(flowDesc.desc) === '[object Object]') ? 'JSON' : 'text',
handler: flowDesc.handler,
}
this.multiOutput(flowDesc.node, flowDesc.desc, flowDesc.type)
if (flowDesc.handler) this.addStreamingHandler({ node: flowDesc.node, handler: flowDesc.handler })
return this
}
//Start Request
async request() {
const response = await this.Request.start('request')
this.initRuntime()
return response
}
async streaming() {
const response = await this.Request.start('streaming')
return response
}
}
class Agent {
constructor
(agentSettings, Agently) {
const self = this
this.Options = Agently.Options
this.debug = Agently.debug
this.LLM = Agently.LLM
this.ProcessUnit = Agently.ProcessUnit
this.agentSettings = {
role: {},
skills: [],
useSkills: false,
useMemory: false,
useStatus: false,
loadSessionContext: true,
saveSessionContext: true,
debug: this.Options.get('debug') || false,
}
const defaultAgentSettings = this.Options.get('defaultAgentSettings') || {}
for (let key in defaultAgentSettings) {
this.agentSettings[key] = defaultAgentSettings[key]
}
agentSettings = agentSettings || {}
if (typeof(agentSettings) === 'string') {
this.setLLM(agentSettings)
agentSettings = {}
}
for (let key in agentSettings) {
this.agentSettings[key] = agentSettings[key]
}
if (this.agentSettings.llmName) this.setLLM(this.agentSettings.llmName)
this.getAgentSettings = () => self.agentSettings
this.getRole = (key) => self.agentSettings.role[key]
this.memories = {}
this.getMemories = () => self.memories
this.getMemory = (key) => self.memories[key]
this.status = {}
this.getStatus = (key) => {
key = key || ''
const splitedKey = key.split('.')
let result = self.status
for (let i = 0; i < splitedKey.length; i++) {
if (splitedKey[i] && splitedKey[i] !== '') result = result[splitedKey[i]]
if (!result) return undefined
}
return result
}
this.addSkill = (skillName) => {
if (self.agentSettings.skills.indexOf(skillName) === -1) self.agentSettings.skills.push(skillName)
return this
}
this.removeSkill = (skillName) => {
const index = self.agentSettings.skills.indexOf(skillName)
if (index > -1) self.agentSettings.splice(index, 1)
return this
}
this.Session = (sessionSettings) => new AgentSession(sessionSettings, this)
this.ChatSession = () => this.Session()
this.FunctionSession = () => this.Session({ loadSessionContext: false, saveSessionContext: false })
}
setDebug (isDebug) {
this.agentSettings.debug = isDebug
return this
}
setLLM (llmName) {
this.agentSettings.llmName = llmName
this.agentSettings.maxContextLength = this.LLM.llmList[llmName].defaultMaxContextLength || 3000
return this
}
setRequestOptions (requestOptions) {
this.agentSettings.requestOptions = requestOptions
return this
}
setMaxContentLength (maxContextLength) {
this.agentSettings.maxContextLength = maxContextLength
return this
}
setRole (key, value) {
if (!value) {
value = key
key = 'role'
}
this.agentSettings.role[key] = value
return this
}
useSkills (isUseSkills = true) {
this.agentSettings.useSkills = isUseSkills
return this
}
useMemory (isUseMemory = true) {
this.agentSettings.useMemory = isUseMemory
return this
}
setMemory (key, value) {
this.memories[key] = value
return this
}
pushMemory (key, value) {
if (!(this.memories[key] instanceof Array)) this.memories[key] = this.memories[key] ? [this.memories[key]] : []
if (this.memories[key].indexOf(value) === -1) this.memories[key].push(value)
return this
}
removeMemory (key, value) {
if (this.memories[key]) {
if (this.memories[key] instanceof Array) {
const targetIndex = this.memories[key].indexOf(value)
if (value === true) {
this.memories[key] = []
} else if ( targetIndex >= 0) {
this.memories[key].splice(targetIndex, 1)
}
} else {
if (value === true) this.memories[key] = null
}
}
return this
}
useStatus (isUseStatus = true) {
this.agentSettings.useStatus = isUseStatus
return this
}
setStatus (key, value) {
if (!key) return false
const splitedKey = key.split('.')
let current = this.status
for (let i = 0; i < splitedKey.length - 1; i++) {
if (splitedKey[i] && splitedKey[i] !== '' && !current[splitedKey[i]]) {
current[splitedKey[i]] = {}
}
current = current[splitedKey[i]]
}
current[splitedKey[splitedKey.length - 1]] = value
return this
}
useSkills (isUseSkills = true) {
this.agentSettings.useSkills = isUseSkills
return this
}
}
module.exports = Agent