langchain-ai / langchainjs

🦜🔗 Build context-aware reasoning applications 🦜🔗
https://js.langchain.com/docs/
MIT License
12.16k stars 2.05k forks source link

Not taking advantage of typescript template literals #34

Closed BLamy closed 11 months ago

BLamy commented 1 year ago

Typescript has extremely powerful template literals. https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html.

I'd imagine one of the goals of langchainjs is to keep a similar API to the python version so you could keep your API similar but infer what the arguments are suppose to be from the string.

https://www.typescriptlang.org/play?#code/C4TwDgpgBAymA2BLYAeGUIA9gQHYBMBnKQ4AJ0VwHMAaKAEQ2zyJPMqoD4oBeNi6kxwFiMAFBQoAfn4cA2gF0JUAFywhLYgHItymYuVr0WYawAGAEgDelAGYQyUACoBfa-Tc3c9xwFUXZnpQck50AHQRcEiovnT0nEqSanIwCgDcYmKgkFAAothkAIYAxsBOEAC2CIU4AAqFRRWEKE71wAAWGiKy1Nx8VspyANJQlLAIyC1t7XRaVlZanHK4AK4VAEYOClCFxCMmmlCWXj5QtS4X1qQCVAHKkjK196pQuBAAbltq1xwZLhliYoAe1wpCgODBfC05Xg8CgFWghSg8wAVkCANYQJzgCAXKBozFhLQA2wrXClRAgqBUPAOGoQFpdVg-XoACmUYDIQKqwDUoQ5DUKTTU+XIJTKlWqdUFTRanDEAEpkS5MjS3kUcKyIcA6FZwRBSGotKTcLgQFooC4FRk1XTNdrdfiMVicUaTWaLVaMkA

image
type Split<S extends string, D extends string> = string extends S
  ? string[]
  : S extends ''
  ? []
  : S extends `${infer T}${D}${infer U}`
  ? [T, ...Split<U, D>]
  : [S];

type ExtractTemplateParams<TPath extends string> = {
  [K in Split<TPath, '{{'>[number] as K extends `${infer P}}}${string}`
    ? P
    : never]: string;
};

function createPromptTemplate<T extends string>(
  prompt: T,
  params: ExtractTemplateParams<T>
) {}

const prompt = 'Tell me a {{jokeType}} joke.';
createPromptTemplate(prompt, { jokeType: "test" })

createPromptTemplate(prompt, { test: 'asf' }); // <- Will throw a type error

This next example is easier to understand but is more of a departure from how python does things. It has a typed generate function that auto completes prompts and will throw an error if you pass in a prompt that isn't valid. The prompt creation helper functions also have autocomplete for their args and the possible options for those args. https://www.typescriptlang.org/play?#code/MYewdgzgLgBA3jAwuAZgSwOYFcBOBDKNcAGhgHkAHAUzAEEBJWitGAXxgF4YcqBHLNDwAUAchDUweNCICUAbgBQC0JFgr02fIXCcYYKgHckqTLgJEwQuApgw8zANJUAngC4YFHCGBUIEAHQ0AG7+ZAAKAKIAcgwA+rRh9LEOEQCaxAqs8srg0DDiNFK6+kaUNAxMaELqploW2QpQztQwYSBUALa0OBgQughQ4mjA7iIANiBBVCIwAD4wIig4aDQAJhAAFmgUM-OLEwZUOBAzrIoqecA8BFRtnWFeHRSwXFYwg8zAbO53XT0QMk4AD4bDAAAYAdWWUCodg87Q6dgARiAsLAACRwD7DVj+MF2PoXKCKJotX4PEBPKAAFU6FDGN10ACUqFBcGBqc0qAAeUlUEAoGBXKg3cmPZ5AxSNLkwABSIAA1lRur1+jAAFaKqic6ijFBYMBgZy7BarLAdJEmkSrPCrU7nXJqa4w+VKilU3RvTVKnWw1juV3K-6Ajgg2xg2ljMYwDqwvAwTHe7Vc9hJvEEoWOkkywPu560p4MmHM1ns328rkCoXOqi58VQSVKfVgYDaMAwDA0I43ISeSnPH4IvM0ulF2HzOv9keFm6A6y2HhsnDtgqSND+YU3ZCF1kWKyg2wdECrKhjUYwgAeUAAtDagmgW2hrwAGZ8AZhEGQPMAA9D+YBskxHPkUw4B49ZUKs7wgDAEBULCUAbAhXIQN+fZUhkthZIorAKEAA

image
sullivan-sean commented 1 year ago

This is really smart 👍

BLamy commented 1 year ago

This approach really shines when you validate user input with zod.

https://stackblitz.com/edit/node-ycgnwj?file=app.ts

image
nfcampos commented 1 year ago

This is great, now a challenge would be how to make it work with prompts loaded from langchainhub 🤔

sullivan-sean commented 1 year ago

This is a great point -- when deserializing from (or serializing to) LangchainHub we'll need access to the input names so that things are compatible with any other languages that may load from LangchainHub

BLamy commented 1 year ago

Not currently possible to infer a string imported from json as const. https://github.com/microsoft/TypeScript/issues/32063

As a workaround you could probably create a CI pipeline that copies the json file to a .ts file and then prepends the file with export default adds as const; at the end.

For node projects I think langchain hub would have to be published as packages on npm and installed using a package manager.

However, I think a runtime like deno could give developers the experience you are looking for by mirrioring langchain hub on deno.land you can import type safe prompts with something like

import { serve } from "https://deno.land/std@0.91.0/http/server.ts";
import { z } from "https://deno.land/x/zod/mod.ts";
import { OpenAI } from 'https://deno.land/x/openai/mod.ts';

import { loadFromHub } from "https://deno.land/x/langchainjs/util/hub.ts";
import qaWithSources from "https://deno.land/x/langchain-hub/prompts/qa_with_sources/refine/basic.ts";

const instance = new OpenAI('YOUR_API_KEY');

const s = serve({ port: 8080 });

console.log("http://localhost:8080/");

for await (const req of s) {
  const prompt = loadFromHub(qaWithSources).format({
    // should be typesafe
  });
  req.respond({ body: await instance.createCompletion(prompt) });
}
Necmttn commented 1 year ago

Before I noticed this whole library existed, I was hacking my way to create typesafe prompt templates. image https://github.com/Necmttn/langflow/blob/wip/packages/prompt/src/index.ts here's the implementation.

and some test cases I have created https://github.com/Necmttn/langflow/blob/wip/packages/prompt/src/index.test.ts

BLamy commented 1 year ago

Been working on an improved API. This is what I've come up with so far. https://blamy.gitbook.io/prompt-builder

Demo: https://stackblitz.com/edit/stackblitz-starters-5jzdje?file=src%2FApp.tsx

dosubot[bot] commented 1 year ago

Hi, @BLamy! I'm Dosu, and I'm here to help the LangChain team manage their backlog. I wanted to let you know that we are marking this issue as stale.

From what I understand, you opened this issue suggesting that langchainjs should take advantage of TypeScript template literals to infer arguments from strings, while keeping a similar API to the Python version. You provided examples and code snippets to support your suggestion. sullivan-sean and nfcampos expressed their support for the idea, with sullivan-sean mentioning the need for compatibility with other languages that may load from LangchainHub. You also shared some workarounds and improvements you have been working on, including a new API and a demo.

Before we proceed, we would like to confirm if this issue is still relevant to the latest version of the LangChain repository. If it is, please let us know by commenting on the issue. Otherwise, feel free to close the issue yourself, or the issue will be automatically closed in 7 days.

Thank you for your contribution, and we appreciate your understanding as we work to manage our backlog effectively. If you have any further questions or concerns, please don't hesitate to reach out.