langchain-ai / langchainjs

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

DOC: JS /v0.2/docs/concepts/ broken paragraph #5582

Closed TonyGravagno closed 4 months ago

TonyGravagno commented 4 months ago

Checklist

Issue with current documentation:

https://js.langchain.com/v0.2/docs/concepts/
Note word break in sentence below. Is there more missing content?

LangGraph exposes high level interfaces for creating common types of agents, as well as a low-level API for constructing more contr

dosubot[bot] commented 4 months ago

Hey @TonyGravagno! I'm here to help you with any issues you encounter in the repository. I can assist with bug fixes, answer your questions, and guide you on how to become a contributor.

Yes, there is missing content and a broken paragraph in the LangChain v0.2 concepts page documentation. Here is the fixed and completed content:

# Conceptual guide

This section contains introductions to key parts of LangChain.

## Architecture

LangChain as a framework consists of several pieces. The below diagram shows how they relate.

import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";

<ThemedImage
  alt="Diagram outlining the hierarchical organization of the LangChain framework, displaying the interconnected parts across multiple layers."
  sources={{
    light: useBaseUrl("/svg/langchain_stack.svg"),
    dark: useBaseUrl("/svg/langchain_stack_dark.svg"),
  }}
  title="LangChain Framework Overview"
/>

### `@langchain/core`

This package contains base abstractions of different components and ways to compose them together.
The interfaces for core components like LLMs, vectorstores, retrievers and more are defined here.
No third party integrations are defined here.
The dependencies are kept purposefully very lightweight.

### `@langchain/community`

This package contains third party integrations that are maintained by the LangChain community.
Key partner packages are separated out (see below).
This contains all integrations for various components (LLMs, vectorstores, retrievers).
All dependencies in this package are optional to keep the package as lightweight as possible.

### Partner packages

While the long tail of integrations are in `@langchain/community`, we split popular integrations into their own packages (e.g. `langchain-openai`, `langchain-anthropic`, etc).
This was done in order to improve support for these important integrations.

### `langchain`

The main `langchain` package contains chains, agents, and retrieval strategies that make up an application's cognitive architecture.
These are NOT third party integrations.
All chains, agents, and retrieval strategies here are NOT specific to any one integration, but rather generic across all integrations.

### [LangGraph.js](https://langchain-ai.github.io/langgraphjs/)
LangGraph.js is an extension of `langchain` aimed at building robust and stateful multi-actor applications with LLMs by modeling steps as edges and nodes in a graph.

LangGraph exposes high level interfaces for creating common types of agents, as well as a low-level API for constructing more controlled and customizable agents.

### [LangSmith](https://docs.smith.langchain.com)

A developer platform that lets you debug, test, evaluate, and monitor LLM applications.

## Installation

If you want to work with high level abstractions, you should install the `langchain` package.

```bash npm2yarn
npm i langchain

If you want to work with specific integrations, you will need to install them separately. See here for a list of integrations and how to install them.

For working with LangSmith, you will need to set up a LangSmith developer account here and get an API key. After that, you can enable it by setting environment variables:

export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=ls__...

LangChain Expression Language

LangChain Expression Language, or LCEL, is a declarative way to easily compose chains together. LCEL was designed from day 1 to support putting prototypes in production, with no code changes, from the simplest “prompt + LLM” chain to the most complex chains (we’ve seen folks successfully run LCEL chains with 100s of steps in production). To highlight a few of the reasons you might want to use LCEL:

First-class streaming support When you build your chains with LCEL you get the best possible time-to-first-token (time elapsed until the first chunk of output comes out). For some chains this means eg. we stream tokens straight from an LLM to a streaming output parser, and you get back parsed, incremental chunks of output at the same rate as the LLM provider outputs the raw tokens.

Optimized parallel execution Whenever your LCEL chains have steps that can be executed in parallel (eg if you fetch documents from multiple retrievers) we automatically do it for the smallest possible latency.

Retries and fallbacks Configure retries and fallbacks for any part of your LCEL chain. This is a great way to make your chains more reliable at scale. We’re currently working on adding streaming support for retries/fallbacks, so you can get the added reliability without any latency cost.

Access intermediate results For more complex chains it’s often very useful to access the results of intermediate steps even before the final output is produced. This can be used to let end-users know something is happening, or even just to debug your chain. You can stream intermediate results, and it’s available on every LangServe server.

Input and output schemas Input and output schemas give every LCEL chain schemas inferred from the structure of your chain. This can be used for validation of inputs and outputs, and is an integral part of LangServe.

Seamless LangSmith tracing As your chains get more and more complex, it becomes increasingly important to understand what exactly is happening at every step. With LCEL, all steps are automatically logged to LangSmith for maximum observability and debuggability.

Interface

To make it as easy as possible to create custom chains, we've implemented a "Runnable" protocol. Many LangChain components implement the Runnable protocol, including chat models, LLMs, output parsers, retrievers, prompt templates, and more. There are also several useful primitives for working with runnables, which you can read about below. This is a standard interface, which makes it easy to define custom chains as well as invoke them in a standard way. The standard interface includes:

The input type and output type varies by component:

Component Input Type Output Type
Prompt Object PromptValue
ChatModel Single string, list of chat messages or a PromptValue ChatMessage
LLM Single string, list of chat messages or a PromptValue String
OutputParser The output of an LLM or ChatModel Depends on the parser
Retriever Single string List of Documents
Tool Single string or object, depending on the tool Depends on the tool

Components

LangChain provides standard, extendable interfaces and external integrations for various components useful for building with LLMs. Some components LangChain implements, some components we rely on third-party integrations for, and others are a mix.

LLMs

Language models that takes a string as input and returns a string. These are traditionally older models (newer models generally are ChatModels, see below).

Although the underlying models are string in, string out, the LangChain wrappers also allow these models to take messages as input. This makes them interchangeable with ChatModels. When messages are passed in as input, they will be formatted into a string under the hood before being passed to the underlying model.

LangChain does not provide any LLMs, rather we rely on third party integrations.

Chat models

Language models that use a sequence of messages as inputs and return chat messages as outputs (as opposed to using plain text). These are traditionally newer models (older models are generally LLMs, see above). Chat models support the assignment of distinct roles to conversation messages, helping to distinguish messages from the AI, users, and instructions such as system messages.

Although the underlying models are messages in, message out, the LangChain wrappers also allow these models to take a string as input. This makes them interchangeable with LLMs (and simpler to use). When a string is passed in as input, it will be converted to a HumanMessage under the hood before being passed to the underlying model.

LangChain does not provide any ChatModels, rather we rely on third party integrations.

We have some standardized parameters when constructing ChatModels:

ChatModels also accept other parameters that are specific to that integration.

Function/Tool Calling

:::info We use the term tool calling interchangeably with function calling. Although function calling is sometimes meant to refer to invocations of a single function, we treat all models as though they can return multiple tool or function calls in each message. :::

Tool calling allows a model to respond to a given prompt by generating output that matches a user-defined schema. While the name implies that the model is performing some action, this is actually not the case! The model is coming up with the arguments to a tool, and actually running the tool (or not) is up to the user - for example, if you want to extract output matching some schema from unstructured text, you could give the model an "extraction" tool that takes parameters matching the desired schema, then treat the generated output as your final result.

A tool call includes a name, arguments object, and an optional identifier. The arguments object is structured { argumentName: argumentValue }.

Many LLM providers, including Anthropic, Cohere, Google, Mistral, OpenAI, and others, support variants of a tool calling feature. These features typically allow requests to the LLM to include available tools and their schemas, and for responses to include calls to these tools. For instance, given a search engine tool, an LLM might handle a query by first issuing a call to the search engine. The system calling the LLM can receive the tool call, execute it, and return the output to the LLM to inform its response. LangChain includes a suite of built-in tools and supports several methods for defining your own custom tools.

There are two main use cases for function/tool calling:

Message types

Some language models take an array of messages as input and return a message. There are a few different types of messages. All messages have a role, content, and response_metadata property.

The role describes WHO is saying the message. LangChain has different message classes for different roles.

The content property describes the content of the message. This can be a few different things:

HumanMessage

This represents a message from the user.

AIMessage

This represents a message from the model. In addition to the content property, these messages also have:

response_metadata The response_metadata property contains additional metadata about the response. The data here is often specific to each model provider. This is where information like log-probs and token usage may be stored.

tool_calls

These represent a decision from an language model to call a tool. They are included as part of an AIMessage output. They can be accessed from there with the .tool_calls property.

This property returns an array of objects. Each object has the following keys:

SystemMessage

This represents a system message, which tells the model how to behave. Not every model provider supports this.

FunctionMessage

This represents the result of a function call. In addition to role and content, this message has a name parameter which conveys the name of the function that was called to produce this result.

ToolMessage

This represents the result of a tool call. This is distinct from a FunctionMessage in order to match OpenAI's function and tool message types. In addition to role and content, this message has a tool_call_id parameter which conveys the id of the call to the tool that was called to produce this result.

Prompt templates

Prompt templates help to translate user input and parameters into instructions for a language model. This can be used to guide a model's response, helping it understand the context and generate relevant and coherent language-based output.

Prompt Templates take as input an object, where each key represents a variable in the prompt template to fill in.

Prompt Templates output a PromptValue. This PromptValue can be passed to an LLM or a ChatModel, and can also be cast to a string or an array of messages. The reason this PromptValue exists is to make it easy to switch between strings and messages.

There are a few different types of prompt templates

String PromptTemplates

These prompt templates are used to format a single string, and generally are used for simpler inputs. For example, a common way to construct and use a PromptTemplate is as follows:

import { PromptTemplate } from "@langchain/core/prompts";

const promptTemplate = PromptTemplate.fromTemplate(
  "Tell me a joke about {topic}"
);

await promptTemplate.invoke({ topic: "cats" });

ChatPromptTemplates

These prompt templates are used to format an array of messages. These "templates" consist of an array of templates themselves. For example, a common way to construct and use a ChatPromptTemplate is as follows:

import { ChatPromptTemplate } from "@langchain/core/prompts";

const promptTemplate = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"],
  ["user", "Tell me a joke about {topic}"],
]);

await promptTemplate.invoke({ topic: "cats" });

In the above example, this ChatPromptTemplate will construct two messages when called. The first is a system message, that has no variables to format. The second is a HumanMessage, and will be formatted by the topic variable the user passes in.

MessagesPlaceholder

This prompt template is responsible for adding an array of messages in a particular place. In the above ChatPromptTemplate, we saw how we could format two messages, each one a string. But what if we wanted the user to pass in an array of messages that we would slot into a particular spot? This is how you use MessagesPlaceholder.

import {
  ChatPromptTemplate,
  MessagesPlaceholder,
} from "@langchain/core/prompts";
import { HumanMessage } from "@langchain/core/messages";

const promptTemplate = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"],
  new MessagesPlaceholder("msgs"),
]);

promptTemplate.invoke({ msgs: [new HumanMessage({ content: "hi!" })] });

This will produce an array of two messages, the first one being a system message, and the second one being the HumanMessage we passed in. If we had passed in 5 messages, then it would have produced 6 messages in total (the system message plus the 5 passed in). This is useful for letting an array of messages be slotted into a particular spot.

An alternative way to accomplish the same thing without using the MessagesPlaceholder class explicitly is:

const promptTemplate = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful assistant"],
  ["placeholder", "{msgs}"], // <-- This is the changed part
]);

Example Selectors

One common prompting technique for achieving better performance is to include examples as part of the prompt. This gives the language model concrete examples of how it should behave. Sometimes these examples are hardcoded into the prompt, but for more advanced situations it may be nice to dynamically select them. Example Selectors are classes responsible for selecting and then formatting examples into prompts.

Output parsers

:::note

The information here refers to parsers that take a text output from a model try to parse it into a more structured representation. More and more models are supporting function (or tool) calling, which handles this automatically. It is recommended to use function/tool calling rather than output parsing. See documentation for that here.

:::

Responsible for taking the output of a model and transforming it to a more suitable format for downstream tasks. Useful when you are using LLMs to generate structured data, or to normalize output from chat models and LLMs.

There are two main methods an output parser must implement:

And then one optional one:

Output parsers accept a string or BaseMessage as input and can return an arbitrary type.

LangChain has many different types of output parsers. This is a list of output parsers LangChain supports. The table below has various pieces of information:

Name: The name of the output parser

Supports Streaming: Whether the output parser supports streaming.

Input Type: Expected input type. Most output parsers work on both strings and messages, but some (like OpenAI Functions) need a message with specific arguments.

Output Type: The output type of the object returned by the parser.

Description: Our commentary on this output parser and when to use it.

Name Supports Streaming Input Type Output Type Description
JSON string | BaseMessage Promise<T> Returns a JSON object as specified. You can specify a Zod schema and it will return JSON for that model.
XML string | BaseMessage Promise<XMLResult> Returns a object of tags. Use when XML output is needed. Use with models that are good at writing XML (like Anthropic's).
[CSV](https://v02.api
#### Details **About Dosu** This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

To continue the conversation, mention @dosu.

jacoblee93 commented 4 months ago

Oh dear, thank you for flagging!