|
1 | | -import { computed, inject } from '@angular/core' |
2 | | -import { END, START, StateGraph, StateGraphArgs } from '@langchain/langgraph/web' |
3 | | -import { CreateGraphOptions } from '@metad/copilot' |
4 | | -import { Plan, injectAgentFewShotTemplate } from '../../../../@core/copilot/' |
| 1 | +import { computed, inject, Signal } from '@angular/core' |
| 2 | +import { ToolMessage } from '@langchain/core/messages' |
| 3 | +import { RunnableLambda } from '@langchain/core/runnables' |
| 4 | +import { DynamicStructuredTool } from '@langchain/core/tools' |
| 5 | +import { ToolNode } from '@langchain/langgraph/prebuilt' |
| 6 | +import { START, StateGraph, StateGraphArgs } from '@langchain/langgraph/web' |
| 7 | +import { ChatOpenAI } from '@langchain/openai' |
| 8 | +import { Indicator } from '@metad/cloud/state' |
| 9 | +import { CreateGraphOptions, Team } from '@metad/copilot' |
| 10 | +import { injectDimensionMemberTool } from '@metad/core' |
5 | 11 | import { ProjectService } from '../../project.service' |
6 | 12 | import { injectRunIndicatorAgent } from '../indicator/graph' |
7 | | -import { createPlannerAgent } from './agent-planner' |
8 | | -import { createReplannerAgent } from './agent-replanner' |
9 | | -import { |
10 | | - INDICATOR_AGENT_NAME, |
11 | | - IndicatorArchitectCommandName, |
12 | | - IndicatorArchitectState, |
13 | | - PLANNER_NAME, |
14 | | - REPLANNER_NAME |
15 | | -} from './types' |
16 | | - |
17 | | -const superState: StateGraphArgs<IndicatorArchitectState>['channels'] = Plan.createState() |
| 13 | +import { promptIndicatorCode } from '../prompt' |
| 14 | +import { INDICATOR_AGENT_NAME, IndicatorArchitectState, markdownIndicators } from './types' |
| 15 | + |
| 16 | +const superState: StateGraphArgs<IndicatorArchitectState>['channels'] = Team.createState() |
18 | 17 |
|
19 | 18 | export function injectCreateIndicatorArchitect() { |
20 | | - const fewShotTemplate = injectAgentFewShotTemplate(IndicatorArchitectCommandName, { k: 1, vectorStore: null }) |
21 | 19 | const projectService = inject(ProjectService) |
| 20 | + const memberRetrieverTool = injectDimensionMemberTool() |
22 | 21 | const createIndicatorGraph = injectRunIndicatorAgent() |
23 | 22 |
|
24 | 23 | const indicators = computed(() => projectService.indicators() ?? []) |
25 | 24 |
|
26 | | - return async ({ llm, checkpointer, interruptBefore, interruptAfter}: CreateGraphOptions) => { |
| 25 | + return async ({ llm, checkpointer, interruptBefore, interruptAfter }: CreateGraphOptions) => { |
27 | 26 | const indicatorWorker = await createIndicatorGraph({ llm }) |
28 | 27 |
|
29 | | - const planner = await createPlannerAgent({ llm, fewShotTemplate, indicators }) |
30 | | - const replanner = await createReplannerAgent({ llm }) |
| 28 | + // const planner = await createPlannerAgent({ llm, fewShotTemplate, indicators }) |
| 29 | + // const replanner = await createReplannerAgent({ llm }) |
| 30 | + const tools = [memberRetrieverTool] |
| 31 | + const supervisorAgent = await createSupervisorAgent({ llm, indicators, tools: [] }) |
31 | 32 |
|
32 | 33 | async function executeStep(state: IndicatorArchitectState): Promise<any> { |
33 | | - const task = state.plan[0] |
34 | | - |
35 | 34 | const { messages } = await indicatorWorker.invoke({ |
36 | 35 | messages: [], |
37 | 36 | role: state.role, |
38 | 37 | context: state.context, |
39 | | - input: task |
| 38 | + input: state.instructions, |
40 | 39 | }) |
41 | 40 |
|
42 | 41 | return { |
43 | | - pastSteps: [[task, messages[messages.length - 1].content.toString()]], |
44 | | - plan: state.plan.slice(1), |
45 | | - messages: [messages[messages.length - 1]] |
| 42 | + tool_call_id: null, |
| 43 | + messages: [ |
| 44 | + new ToolMessage({ |
| 45 | + tool_call_id: state.tool_call_id, |
| 46 | + content: messages[messages.length - 1].content |
| 47 | + }) |
| 48 | + ] |
46 | 49 | } |
47 | 50 | } |
48 | 51 |
|
49 | | - function shouldEnd(state: IndicatorArchitectState) { |
50 | | - return state.response ? 'true' : 'false' |
51 | | - } |
52 | | - |
53 | 52 | const superGraph = new StateGraph({ channels: superState }) |
54 | 53 | // Add steps nodes |
55 | | - .addNode(PLANNER_NAME, planner) |
| 54 | + .addNode(Team.SUPERVISOR_NAME, supervisorAgent.withConfig({ runName: Team.SUPERVISOR_NAME })) |
| 55 | + .addNode(Team.TOOLS_NAME, new ToolNode<IndicatorArchitectState>(tools)) |
56 | 56 | .addNode(INDICATOR_AGENT_NAME, executeStep) |
57 | | - .addNode(REPLANNER_NAME, replanner) |
58 | | - .addEdge(START, PLANNER_NAME) |
59 | | - .addEdge(PLANNER_NAME, INDICATOR_AGENT_NAME) |
60 | | - .addEdge(INDICATOR_AGENT_NAME, REPLANNER_NAME) |
61 | | - .addConditionalEdges(REPLANNER_NAME, shouldEnd, { |
62 | | - true: END, |
63 | | - false: INDICATOR_AGENT_NAME |
64 | | - }) |
| 57 | + .addEdge(START, Team.SUPERVISOR_NAME) |
| 58 | + .addConditionalEdges(Team.SUPERVISOR_NAME, Team.supervisorRouter) |
| 59 | + .addEdge(INDICATOR_AGENT_NAME, Team.SUPERVISOR_NAME) |
| 60 | + .addEdge(Team.TOOLS_NAME, Team.SUPERVISOR_NAME) |
65 | 61 |
|
66 | | - return superGraph.compile({ checkpointer, interruptBefore, interruptAfter}) |
| 62 | + return superGraph.compile({ checkpointer, interruptBefore, interruptAfter }) |
67 | 63 | } |
68 | 64 | } |
| 65 | + |
| 66 | +export async function createSupervisorAgent({ |
| 67 | + llm, |
| 68 | + indicators, |
| 69 | + tools |
| 70 | +}: { |
| 71 | + llm: ChatOpenAI |
| 72 | + indicators: Signal<Indicator[]> |
| 73 | + tools: DynamicStructuredTool[] |
| 74 | +}) { |
| 75 | + const agent = await Team.createSupervisorAgent( |
| 76 | + llm, |
| 77 | + [ |
| 78 | + { |
| 79 | + name: INDICATOR_AGENT_NAME, |
| 80 | + description: 'Create an indicator, only one at a time' |
| 81 | + } |
| 82 | + ], |
| 83 | + tools, |
| 84 | + `As a indicator system architect specializing in data analysis, your task is to develop a set of indicators specifically for business data analysis based on multidimensional cube information and user prompts, and align with your business role. |
| 85 | +Each indicator gives a concise business requirement and name, and the indicators are sorted in the order of creation dependencies. |
| 86 | +
|
| 87 | +{role} |
| 88 | +
|
| 89 | +{language} |
| 90 | +
|
| 91 | +{context} |
| 92 | +
|
| 93 | +Methods for indicator design: |
| 94 | +- Directly use the basic measures defined in the model, which are measurement data extracted directly from the data source, such as sales amount, inventory quantity, etc. |
| 95 | +- Design indicators with calculation formulas, which are indicators calculated based on basic measures, such as year-on-year growth rate, average inventory turnover rate, etc. |
| 96 | +- Use Restricted filters to limit measurement data according to specific conditions or dimensions, such as sales in a specific time period, inventory in a certain area, etc. |
| 97 | +
|
| 98 | +1. Do not create duplicate indicators that already exist: |
| 99 | +{indicators} |
| 100 | +
|
| 101 | +2. ${promptIndicatorCode(`{indicatorCodes}`)} |
| 102 | +3. Please plan the indicator system first, and then decide to call route to create it one by one. |
| 103 | +` |
| 104 | + ) |
| 105 | + |
| 106 | + return RunnableLambda.from(async (state: IndicatorArchitectState) => { |
| 107 | + return { |
| 108 | + ...state, |
| 109 | + indicators: markdownIndicators(indicators()), |
| 110 | + indicatorCodes: indicators() |
| 111 | + .map((indicator) => indicator.code) |
| 112 | + .join(', '), |
| 113 | + } |
| 114 | + }).pipe(agent) |
| 115 | +} |
0 commit comments