Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation actions scafolding + initial list_files action #8646

Merged
merged 22 commits into from
Nov 15, 2024

Conversation

spolu
Copy link
Contributor

@spolu spolu commented Nov 14, 2024

Description

Introduce a new conversaton_list_files_action which is never stored in DB but emulated as first tool use for the current agent message if there are files present in the conversation.

This is an attempt at a slightly more principled approach to injecting that emulated actions to be compared to a more iterative approach (from viz current state) proposed here: #8643. It does require a bit more code to fully represent the new AgentActionType but it allows the injection of the emulated action directly in the current agentMessage by prepending to any already run actions to properly always inject as first action.

When the flag jit_conversations_actions is enabled we rely on this new emulated action to make the list of files in the conversations available to the agent in the context of visualization.

Risk

N/A behind flag

Deploy Plan

  • deploy front

@@ -362,6 +362,16 @@ async function* runMultiActionsAgent(

const MIN_GENERATION_TOKENS = 2048;

const fakeJITListFiles = makeJITListFilesAction(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would have to be done behind flags + we can generalize to a "injectFakeActions" as this could be used for other things in the future

@spolu spolu force-pushed the spolu-jit_action_scafolding branch from 483c4e2 to cf97767 Compare November 15, 2024 06:17
@spolu spolu changed the title JIT actions scafolding Conversation actions scafolding + initial list_files action Nov 15, 2024
@spolu spolu marked this pull request as ready for review November 15, 2024 07:24
@spolu spolu requested a review from Fraggle November 15, 2024 07:29
contentType: z.string(),
});

const ConversationListFilesActionTypeSchema = BaseActionSchema.extend({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised to see them in the public api types as it should not be needed to return them in the public json of the conversation, does it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice they are never returned but I don't think it's necessarily an issue to have them leak because it's not entirely a lie.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The next ConversationAgentActionType will be returned by the API and will live along this one so we're paving the way for them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The next ones yes, that one no.

Feels like we are mixing apple and oranges here.

isTablesQueryActionType,
} from "@dust-tt/types";

interface JITListFilesActionBlob {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "JIT" codename made sense internally so far because we have shared context but I don't think it's really a name that should exist in our codebase, at least not jsut "JIT" alone. Thinking of all the future engineers this will be hard to grasp IMHO

for (const action of actions) {
const stepIndex = action.step;
for (let stepIndex = 0; stepIndex < actions.length; stepIndex++) {
const action = actions[stepIndex];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so now the action.step do not necessary match the stepIndex ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this one still need a bit of work I was a bit too rapid to change the behavior here

@Fraggle Fraggle self-requested a review November 15, 2024 08:28
@spolu spolu force-pushed the spolu-jit_action_scafolding branch from c6196bf to f7ae369 Compare November 15, 2024 12:27
@spolu
Copy link
Contributor Author

spolu commented Nov 15, 2024

Fully tested locally rendering works as expected
Screenshot from 2024-11-15 13-22-20
Screenshot from 2024-11-15 13-21-41

@spolu spolu requested review from fontanierh and Fraggle November 15, 2024 12:30
Copy link
Contributor

@fontanierh fontanierh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to address the nits or not.

Otherwise looks great 👍

};
}

renderForMultiActionsModel(): FunctionMessageTypeModel {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated to this PR, but we need to rename this

agentMessage: AgentMessageType,
conversation: ConversationType
): ConversationListFilesActionType | null {
const jitFiles: ConversationFileType[] = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "jitFiles" could really just be "files". They aren't really "jit" IMHO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Reminiscence from early versions. Will fix.

}

// We ensure that all emulated actions are injected with step -1.
assert(actions.every((a) => a.step === -1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: IMHO a regular exception with a clear error message is better (for eng runner) than using assert (which looks like something you'd use in a test)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I can add a message to the assert?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but why use a function for that ? Looks like we're just wrapping a basic language construct with a useless function.

// calls). Actions all have a step index which indicates how they should be grouped but some
// actions injected by `getEmulatedAgentMessageActions` have a step index of `-1`. We
// therefore group by index, then order and transform in a 2D array to present to the model.
const stepsByStepIndex = {} as Record<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think naming is getting confusing here. A "step" to me is a list of actions that were taken at this step.
So it should really be stepByIndex no ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep will fix 👍

step: z.number(),
type: z.literal("conversation_list_files_action"),
});
// type ConversationListFIlesActionPublicType = z.infer<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: to cleanup


// We ensure that all emulated actions are injected with step -1.
assert(
actions.every((a) => a.step === -1),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't this also be enforced in type system removing the need for assert ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would mix their type and the fact that they are emulated. One could imagine that a classic action is emulated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair !

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spolu

nit: the -1 index is going to be limiting if we need to order multiple emulated actions, I suggest < 0

@spolu spolu merged commit 0e7714d into main Nov 15, 2024
2 checks passed
@spolu spolu deleted the spolu-jit_action_scafolding branch November 15, 2024 14:06
// calls). Actions all have a step index which indicates how they should be grouped but some
// actions injected by `getEmulatedAgentMessageActions` have a step index of `-1`. We
// therefore group by index, then order and transform in a 2D array to present to the model.
const stepByStepIndex = {} as Record<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'd rather use Map() insead of Record, unless we are serializing as this is not catched by the typechecking system:

const aRecord:Record<string, {"k": string}> = {};

aRecord["ruc"].k

@@ -81,46 +79,55 @@ export async function renderConversationForModelJIT({
const now = Date.now();
const messages: ModelMessageTypeMultiActions[] = [];

// Render loop.
// Render all messages and all actions.
// Render loop: dender all messages and all actions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo (dender => render)


for (const action of actions) {
const stepIndex = action.step;
steps[stepIndex] = steps[stepIndex] || emptyStep();
steps[stepIndex].actions.push({
stepByStepIndex[stepIndex] = stepByStepIndex[stepIndex] || emptyStep();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: i know it's previous code but how can a step be empty ? (a comment would go a long way)

call: action.renderForFunctionCall(),
result: action.renderForMultiActionsModel(),
});
}

for (const content of m.rawContents) {
steps[content.step] = steps[content.step] || emptyStep();
stepByStepIndex[content.step] =
stepByStepIndex[content.step] || emptyStep();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: shorter version stepByStepIndex[content.step] ??= emptyStep(); (same above)

const isJITEnabled = await isJITActionsEnabled(auth);
// If `jit_conversations_actions` is enabled we rely on the `conversations_list_files` emulated
// actions to make the list of files available to the agent.
if (await isJITActionsEnabled(auth)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: i have been told by @flvndvd not to do await in conditions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants