Skip to content

Commit

Permalink
Agent DbQuery action: improve display of streamed events (#2973)
Browse files Browse the repository at this point in the history
  • Loading branch information
PopDaph authored Dec 20, 2023
1 parent 6240866 commit bc469a0
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 51 deletions.
1 change: 1 addition & 0 deletions front/components/assistant/conversation/AgentMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export function AgentMessage({
case "dust_app_run_params":
case "dust_app_run_block":
case "database_query_params":
case "database_query_output":
setStreamedAgentMessage((m) => {
return { ...m, action: event.action };
});
Expand Down
139 changes: 91 additions & 48 deletions front/components/assistant/conversation/DatabaseQueryAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Chip,
Icon,
Spinner,
Tooltip,
} from "@dust-tt/sparkle";
import { DatabaseQueryActionType } from "@dust-tt/types";
import dynamic from "next/dynamic";
Expand All @@ -20,72 +21,114 @@ export default function DatabaseQueryAction({
}: {
databaseQueryAction: DatabaseQueryActionType;
}) {
const [outputVisible, setOutputVisible] = useState(false);
const [isOutputExpanded, setIsOutputExpanded] = useState(false);

// Extracting question from the params
const params = databaseQueryAction.params;
const question =
typeof params?.question === "string" ? params.question : null;

// Extracting query and result from the output
const output = databaseQueryAction.output;
const query = output?.query;
const query = typeof output?.query === "string" ? output.query : null;
const noQuery = output?.no_query === true;
const results = output?.results;

const isQueryStepCompleted = noQuery || query;
const isOutputStepCompleted = noQuery || (query && results);

const trimText = (text: string, maxLength = 20) => {
const t = text.replaceAll("\n", " ");
return t.length > maxLength ? t.substring(0, maxLength) + "..." : t;
};

return (
<>
<div className="grid grid-cols-[auto,1fr] gap-2">
<div className="grid-cols-auto grid items-center">
{!output ? (
<div>
<Spinner size="sm" />
</div>
) : (
{question && (
<div className="flex flex-row items-center gap-2 pb-2">
<div className="flex flex-col items-start text-xs font-bold text-element-600">
<div className="flex">Question:</div>
</div>
<Tooltip label={question}>
<Chip color="slate" label={trimText(question)} />
</Tooltip>
</div>
)}

{!isQueryStepCompleted && (
<div>
<div className="pb-2 text-xs font-bold text-element-600">
Generating query...
</div>
<Spinner size="sm" />
</div>
)}

{isQueryStepCompleted && (
<div className="grid grid-cols-[auto,1fr] gap-2 pb-2">
<div className="grid-cols-auto grid items-center">
<div className="text-xs font-bold text-element-600">
<span>{query ? "Query Executed:" : "Result: "}</span>
<span>Query:</span>
</div>
)}
</div>
{!!output && (
</div>
<div className="row-span-1 select-none">
<div
className="cursor-pointer"
onClick={() => {
setOutputVisible(!outputVisible);
setIsOutputExpanded(!isOutputExpanded);
}}
>
<Chip color="purple">
{query ? query : "No query generated, expand to see why"}
<Icon
visual={outputVisible ? ChevronDownIcon : ChevronRightIcon}
size="xs"
/>
{query ? query : "No query generated"}
{(noQuery || results) && (
<Icon
visual={
isOutputExpanded ? ChevronDownIcon : ChevronRightIcon
}
size="xs"
/>
)}
</Chip>
</div>
</div>
)}
{outputVisible && (
<div className="col-start-2 row-span-1 max-h-48 overflow-auto rounded-md bg-structure-100">
<SyntaxHighlighter
className="h-full w-full rounded-md text-xs"
style={{
"hljs-number": {
color: amber["500"],
},
"hljs-literal": {
color: amber["500"],
},
"hljs-string": {
color: emerald["600"],
},
hljs: {
display: "block",
overflowX: "auto",
color: slate["700"],
padding: "1em",
},
}}
language={"json"}
PreTag="div"
>
{JSON.stringify(output, null, 2)}
</SyntaxHighlighter>
{isOutputExpanded && (
<div className="col-start-2 row-span-1 max-h-48 overflow-auto rounded-md bg-structure-100">
<SyntaxHighlighter
className="h-full w-full rounded-md text-xs"
style={{
"hljs-number": {
color: amber["500"],
},
"hljs-literal": {
color: amber["500"],
},
"hljs-string": {
color: emerald["600"],
},
hljs: {
display: "block",
overflowX: "auto",
color: slate["700"],
padding: "1em",
},
}}
language={"json"}
PreTag="div"
>
{JSON.stringify(output, null, 2)}
</SyntaxHighlighter>
</div>
)}
</div>
)}
{isQueryStepCompleted && !isOutputStepCompleted && (
<div>
<div className="pb-2 text-xs font-bold text-element-600">
Running query...
</div>
)}
</div>
<Spinner size="sm" />
</div>
)}
</>
);
}
34 changes: 33 additions & 1 deletion front/lib/api/assistant/actions/database_query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ConversationType,
DatabaseQueryActionType,
DatabaseQueryErrorEvent,
DatabaseQueryOutputEvent,
DatabaseQueryParamsEvent,
DatabaseQuerySuccessEvent,
DustProdActionRegistry,
Expand Down Expand Up @@ -119,7 +120,10 @@ export async function* runDatabaseQuery({
userMessage: UserMessageType;
agentMessage: AgentMessageType;
}): AsyncGenerator<
DatabaseQueryErrorEvent | DatabaseQuerySuccessEvent | DatabaseQueryParamsEvent
| DatabaseQueryErrorEvent
| DatabaseQuerySuccessEvent
| DatabaseQueryParamsEvent
| DatabaseQueryOutputEvent
> {
// Checking authorizations
const owner = auth.workspace();
Expand Down Expand Up @@ -282,8 +286,36 @@ export async function* runDatabaseQuery({
return;
}

if (event.content.block_name === "SQL") {
let tmpOutput = null;
if (e.value) {
const sql = e.value as string;
tmpOutput = { query: sql };
} else {
tmpOutput = { no_query: true };
}
yield {
type: "database_query_output",
created: Date.now(),
configurationId: configuration.sId,
messageId: agentMessage.sId,
action: {
id: action.id,
type: "database_query_action",
dataSourceWorkspaceId: action.dataSourceWorkspaceId,
dataSourceId: action.dataSourceId,
databaseId: action.databaseId,
params: action.params,
output: tmpOutput,
},
};
}

if (event.content.block_name === "OUTPUT" && e.value) {
output = JSON.parse(e.value as string);
if (!output.query) {
output.no_query = true;
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions front/lib/api/assistant/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ export async function* runAgent(
for await (const event of eventStream) {
switch (event.type) {
case "database_query_params":
case "database_query_output":
yield event;
break;
case "database_query_error":
Expand Down
2 changes: 2 additions & 0 deletions front/lib/api/assistant/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ async function batchRenderAgentMessages(
dataSourceWorkspaceId: action.dataSourceWorkspaceId,
dataSourceId: action.dataSourceId,
databaseId: action.databaseId,
params: action.params,
output: action.output,
};
});
Expand Down Expand Up @@ -1956,6 +1957,7 @@ async function* streamRunAgentEvents(
case "dust_app_run_params":
case "dust_app_run_block":
case "database_query_params":
case "database_query_output":
yield event;
break;
case "generation_tokens":
Expand Down
2 changes: 2 additions & 0 deletions front/lib/api/assistant/pubsub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ async function handleUserMessageEvents(
case "dust_app_run_params":
case "dust_app_run_block":
case "database_query_params":
case "database_query_output":
case "agent_error":
case "agent_action_success":
case "generation_tokens":
Expand Down Expand Up @@ -282,6 +283,7 @@ export async function retryAgentMessageWithPubSub(
case "dust_app_run_params":
case "dust_app_run_block":
case "database_query_params":
case "database_query_output":
case "agent_error":
case "agent_action_success":
case "generation_tokens":
Expand Down
8 changes: 8 additions & 0 deletions types/src/front/lib/api/assistant/actions/database_query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ export type DatabaseQueryParamsEvent = {
messageId: string;
action: DatabaseQueryActionType;
};

export type DatabaseQueryOutputEvent = {
type: "database_query_output";
created: number;
configurationId: string;
messageId: string;
action: DatabaseQueryActionType;
};
8 changes: 6 additions & 2 deletions types/src/front/lib/api/assistant/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
AgentActionType,
AgentMessageType,
} from "../../../../front/assistant/conversation";
import { DatabaseQueryParamsEvent } from "../../../../front/lib/api/assistant/actions/database_query";
import {
DatabaseQueryOutputEvent,
DatabaseQueryParamsEvent,
} from "../../../../front/lib/api/assistant/actions/database_query";
import {
DustAppRunBlockEvent,
DustAppRunParamsEvent,
Expand Down Expand Up @@ -41,7 +44,8 @@ export type AgentActionEvent =
| RetrievalParamsEvent
| DustAppRunParamsEvent
| DustAppRunBlockEvent
| DatabaseQueryParamsEvent;
| DatabaseQueryParamsEvent
| DatabaseQueryOutputEvent;

// Event sent once the action is completed, we're moving to generating a message if applicable.
export type AgentActionSuccessEvent = {
Expand Down

0 comments on commit bc469a0

Please sign in to comment.