dexaai / dexter

LLM tools used in production at Dexa
https://dexter.dexa.ai
MIT License
69 stars 4 forks source link

Changes while integrating the latest Dexter back into Dexa #10

Closed transitive-bullshit closed 9 months ago

transitive-bullshit commented 10 months ago
vercel[bot] commented 10 months ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
dexter ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 21, 2023 8:48pm
rileytomasek commented 10 months ago

I removed this from the ChatModel because it's not really calling the model any differently, it's just adding more logic before and after the call.

I think we should add a more general solution to /prompt. I have a lot of stashes for this and can't find the best version, but this is relatively close to what I was thinking. Let me know what you think of this direction.

export function createChain<
  Args extends Record<string, any>,
  Result extends any
>(args: {
  model: Model.Chat.IModel;
  prompt: Prompt.Template<Args>;
  functions?: Prompt.AiFunction[];
  validator: Prompt.Validator<Result>;
  retries?: number;
}): Prompt.Chain<Args, Result> {
  return async (promptArgs: Args): Promise<Result> => {
    const { model, prompt, validator, retries = 0 } = args;
    let attempts = 0;
    const messages = await prompt(promptArgs);
    while (attempts <= retries) {
      attempts++;
      const response = await model.run({
        messages,
        functions: args?.functions?.map((func) => func.spec) || undefined,
      });
      const message = response.choices[0].message;
      try {
        if (args.functions && Msg.isFuncCall(message)) {
          const { name, arguments: callArgs } = message.function_call;
          const func = args.functions.find((func) => func.name === name);
          if (!func) {
            throw new Error(`There is no function named "${name}"`);
          }
          return func.parseArgs(callArgs);
          // TODO: validate function
        } else {
          return await validator(response.choices[0].message);
        }
      } catch (error) {
        const VAL_MSG = `There was an error validating the response. Please ready the error message and try again.\nError:\n`;
        const errMessage = getErrorMsg(error);
        messages.push(response.choices[0].message);
        messages.push(Msg.user(`${VAL_MSG}${errMessage}`));
      }
    }
    const lastError = messages[messages.length - 1].content!;
    throw new Error(
      `Validation failed after ${attempts} attempts: ${lastError}`
    );
  };
}
transitive-bullshit commented 9 months ago

@rileytomasek I took your example, sprinkled some sauce, and ended up with createAIChain.

See examples/ai-function.ts using createAIFunction and examples/ai-chain.ts using createAIChain for how much simpler the chain version is.

transitive-bullshit commented 9 months ago

Closing in favor of #13