Skip to content

Commit

Permalink
helpers 2
Browse files Browse the repository at this point in the history
  • Loading branch information
grabbou committed Dec 12, 2024
1 parent da613f3 commit 23e6a5e
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 93 deletions.
47 changes: 14 additions & 33 deletions packages/framework/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { zodFunction, zodResponseFormat } from 'openai/helpers/zod.js'
import { z } from 'zod'

import { openai, Provider } from './models.js'
import { finish, WorkflowState } from './state.js'
import { finish, request, response, WorkflowState } from './state.js'
import { Tool } from './tool.js'
import { Message } from './types.js'
import { Workflow } from './workflow.js'
Expand Down Expand Up @@ -39,7 +39,7 @@ export const agent = (options: AgentOptions = {}): Agent => {
)
: []

const response = await provider.completions({
const res = await provider.completions({
messages: [
{
role: 'system',
Expand All @@ -56,18 +56,9 @@ export const agent = (options: AgentOptions = {}): Agent => {
Try to complete the task on your own.
`,
},
{
role: 'assistant',
content: 'What have been done so far?',
},
{
role: 'user',
content: `Here is all the work done so far by other agents: ${JSON.stringify(context)}`,
},
{
role: 'assistant',
content: 'What do you want me to do now?',
},
response('What have been done so far?'),
request(`Here is all the work done so far by other agents: ${JSON.stringify(context)}`),
response('What do you want me to do now?'),
...state.messages,
],
tools: mappedTools.length > 0 ? mappedTools : undefined,
Expand All @@ -94,40 +85,30 @@ export const agent = (options: AgentOptions = {}): Agent => {
),
})

if (response.choices[0].message.tool_calls.length > 0) {
if (res.choices[0].message.tool_calls.length > 0) {
return {
...state,
status: 'paused',
messages: state.messages.concat(response.choices[0].message),
messages: state.messages.concat(res.choices[0].message),
}
}

const result = response.choices[0].message.parsed
if (!result) {
const message = res.choices[0].message.parsed
if (!message) {
throw new Error('No parsed response received')
}

if (result.response.kind === 'error') {
throw new Error(result.response.reasoning)
if (message.response.kind === 'error') {
throw new Error(message.response.reasoning)
}

const agentResponse = {
role: 'assistant' as const,
content: result.response.result,
}
const agentResponse = response(message.response.result)

if (result.response.nextStep) {
if (message.response.nextStep) {
return {
...state,
status: 'running',
messages: [
...state.messages,
agentResponse,
{
role: 'user',
content: result.response.nextStep,
},
],
messages: [...state.messages, agentResponse, request(message.response.nextStep)],
}
}

Expand Down
21 changes: 9 additions & 12 deletions packages/framework/src/agents/final_boss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { zodResponseFormat } from 'openai/helpers/zod'
import { z } from 'zod'

import { agent, AgentOptions } from '../agent.js'
import { finish } from '../state.js'
import { finish, request, response } from '../state.js'

const defaults: AgentOptions = {
run: async (state, context, workflow) => {
const response = await workflow.team[state.agent].provider.completions({
const res = await workflow.team[state.agent].provider.completions({
messages: [
{
role: 'system',
Expand All @@ -16,13 +16,10 @@ const defaults: AgentOptions = {
`,
},
...context,
{
role: 'user',
content: s`
Please summarize all executed steps and do your best to achieve
the main goal while responding with the final answer
`,
},
request(s`
Please summarize all executed steps and do your best to achieve
the main goal while responding with the final answer
`),
],
response_format: zodResponseFormat(
z.object({
Expand All @@ -31,11 +28,11 @@ const defaults: AgentOptions = {
'task_result'
),
})
const result = response.choices[0].message.parsed
if (!result) {
const message = res.choices[0].message.parsed
if (!message) {
throw new Error('No parsed response received')
}
return finish(state, { role: 'assistant', content: result.finalAnswer })
return finish(state, response(message.finalAnswer))
},
}

Expand Down
23 changes: 8 additions & 15 deletions packages/framework/src/agents/resource_planner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { zodResponseFormat } from 'openai/helpers/zod'
import { z } from 'zod'

import { agent, AgentOptions } from '../agent.js'
import { handoff } from '../state.js'
import { handoff, request, response } from '../state.js'

const defaults: AgentOptions = {
run: async (state, context, workflow) => {
const response = await workflow.team[state.agent].provider.completions({
const res = await workflow.team[state.agent].provider.completions({
messages: [
{
role: 'system',
Expand All @@ -22,21 +22,14 @@ const defaults: AgentOptions = {
4. Previous task context if available
`,
},
{
role: 'user',
content: s`
request(s`
Here are the available agents:
<agents>
${Object.entries(workflow.team).map(([name, agent]) =>
agent.description ? `<agent name="${name}">${agent.description}</agent>` : ''
)}
</agents>
`,
},
{
role: 'assistant',
content: 'What is the task?',
},
</agents>`),
response('What is the task?'),
...state.messages,
],
temperature: 0.1,
Expand All @@ -49,12 +42,12 @@ const defaults: AgentOptions = {
),
})

const content = response.choices[0].message.parsed
if (!content) {
const message = res.choices[0].message.parsed
if (!message) {
throw new Error('No content in response')
}

return handoff(state, content.agent, state.messages)
return handoff(state, message.agent, state.messages)
},
}

Expand Down
28 changes: 8 additions & 20 deletions packages/framework/src/agents/supervisor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { z } from 'zod'

import { agent, AgentOptions } from '../agent.js'
import { getSteps } from '../messages.js'
import { delegate } from '../state.js'
import { delegate, request, response } from '../state.js'

const defaults: AgentOptions = {
run: async (state, context, workflow) => {
const [request, ...messages] = state.messages
const [workflowRequest, ...messages] = state.messages

const response = await workflow.team[state.agent].provider.completions({
const res = await workflow.team[state.agent].provider.completions({
messages: [
{
role: 'system',
Expand All @@ -28,15 +28,9 @@ const defaults: AgentOptions = {
5. Use context from completed tasks to inform next steps
`,
},
{
role: 'assistant',
content: 'What is the request?',
},
request,
{
role: 'assistant',
content: 'What has been completed so far?',
},
response('What is the request?'),
workflowRequest,
response('What has been completed so far?'),
...getSteps(messages),
],
temperature: 0.2,
Expand All @@ -56,7 +50,7 @@ const defaults: AgentOptions = {
})

try {
const content = response.choices[0].message.parsed
const content = res.choices[0].message.parsed
if (!content) {
throw new Error('No content in response')
}
Expand All @@ -70,13 +64,7 @@ const defaults: AgentOptions = {

return delegate(
state,
content.tasks.map((item) => [
'resourcePlanner',
{
role: 'user',
content: item.task,
},
])
content.tasks.map((item) => ['resourcePlanner', request(item.task)])
)
} catch (error) {
throw new Error('Failed to determine next task')
Expand Down
7 changes: 2 additions & 5 deletions packages/framework/src/iterate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { childState, finish, WorkflowState } from './state.js'
import { childState, finish, response, WorkflowState } from './state.js'
import { runTools } from './tool_calls.js'
import { Message } from './types.js'
import { Workflow } from './workflow.js'
Expand Down Expand Up @@ -48,10 +48,7 @@ export async function run(
try {
return agent.run(state, context, workflow)
} catch (error) {
return finish(state, {
role: 'assistant',
content: error instanceof Error ? error.message : 'Unknown error',
})
return finish(state, response(error instanceof Error ? error.message : 'Unknown error'))
}
}

Expand Down
27 changes: 19 additions & 8 deletions packages/framework/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,11 @@ export const rootState = (workflow: Workflow): WorkflowState =>
childState({
agent: 'supervisor',
messages: [
{
role: 'user',
content: s`
Here is description of my workflow and expected output:
<workflow>${workflow.description}</workflow>
<output>${workflow.output}</output>
`,
},
request(s`
Here is description of my workflow and expected output:
<workflow>${workflow.description}</workflow>
<output>${workflow.output}</output>
`),
],
})

Expand Down Expand Up @@ -73,3 +70,17 @@ export const handoff = (
messages,
})
}

export const response = (content: string): Message => {
return {
role: 'assistant',
content,
}
}

export const request = (content: string): Message => {
return {
role: 'user',
content,
}
}

0 comments on commit 23e6a5e

Please sign in to comment.