From dccc20b402f32133e70414a99dde9d46b61fb211 Mon Sep 17 00:00:00 2001
From: Bagatur <22008038+baskaryan@users.noreply.github.com>
Date: Fri, 22 Sep 2023 01:10:27 -0700
Subject: [PATCH] add model feat table (#10921)
---
.github/workflows/doc_lint.yml | 2 +-
docs/_scripts/model_feat_table.py | 145 ++++++++++++++++++
docs/api_reference/create_api_rst.py | 1 -
docs/docs_skeleton/sidebars.js | 4 +-
docs/extras/integrations/chat/index.mdx | 36 +++++
docs/extras/integrations/llms/index.mdx | 91 +++++++++++
.../langchain/chat_models/bedrock.py | 25 +--
.../langchain/langchain/utilities/vertexai.py | 4 +-
8 files changed, 278 insertions(+), 30 deletions(-)
create mode 100644 docs/_scripts/model_feat_table.py
create mode 100644 docs/extras/integrations/chat/index.mdx
create mode 100644 docs/extras/integrations/llms/index.mdx
diff --git a/.github/workflows/doc_lint.yml b/.github/workflows/doc_lint.yml
index 1c50a18e19f21..b2734b28e6614 100644
--- a/.github/workflows/doc_lint.yml
+++ b/.github/workflows/doc_lint.yml
@@ -19,4 +19,4 @@ jobs:
run: |
# We should not encourage imports directly from main init file
# Expect for hub
- git grep 'from langchain import' docs | grep -vE 'from langchain import (hub)' && exit 1 || exit 0
+ git grep 'from langchain import' docs/{extras,docs_skeleton,snippets} | grep -vE 'from langchain import (hub)' && exit 1 || exit 0
diff --git a/docs/_scripts/model_feat_table.py b/docs/_scripts/model_feat_table.py
new file mode 100644
index 0000000000000..61e18091140c6
--- /dev/null
+++ b/docs/_scripts/model_feat_table.py
@@ -0,0 +1,145 @@
+import os
+from pathlib import Path
+
+from langchain import chat_models, llms
+from langchain.chat_models.base import BaseChatModel, SimpleChatModel
+from langchain.llms.base import BaseLLM, LLM
+
+INTEGRATIONS_DIR = (
+ Path(os.path.abspath(__file__)).parents[1] / "extras" / "integrations"
+)
+LLM_IGNORE = ("FakeListLLM", "OpenAIChat", "PromptLayerOpenAIChat")
+LLM_FEAT_TABLE_CORRECTION = {
+ "TextGen": {"_astream": False, "_agenerate": False},
+ "Ollama": {
+ "_stream": False,
+ },
+ "PromptLayerOpenAI": {"batch_generate": False, "batch_agenerate": False},
+}
+CHAT_MODEL_IGNORE = ("FakeListChatModel", "HumanInputChatModel")
+CHAT_MODEL_FEAT_TABLE_CORRECTION = {
+ "ChatMLflowAIGateway": {"_agenerate": False},
+ "PromptLayerChatOpenAI": {"_stream": False, "_astream": False},
+ "ChatKonko": {"_astream": False, "_agenerate": False},
+}
+
+LLM_TEMPLATE = """\
+---
+sidebar_position: 0
+sidebar_class_name: hidden
+---
+
+# LLMs
+
+import DocCardList from "@theme/DocCardList";
+
+## Features (natively supported)
+All `LLM`s implement the LCEL `Runnable` interface, meaning they all expose functioning `invoke`, `ainvoke`, `batch`, `abatch`, `stream`, and `astream` methods.
+*That is, they all have functioning sync, async, streaming, and batch generation methods.*
+
+This table highlights specifically those integrations that **natively support** batching, streaming, and asynchronous generation (meaning these features are built into the 3rd-party integration).
+
+{table}
+
+
+"""
+
+CHAT_MODEL_TEMPLATE = """\
+---
+sidebar_position: 1
+sidebar_class_name: hidden
+---
+
+# Chat models
+
+import DocCardList from "@theme/DocCardList";
+
+## Features (natively supported)
+All `ChatModel`s implement the LCEL `Runnable` interface, meaning they all expose functioning `invoke`, `ainvoke`, `stream`, and `astream` (and `batch`, `abatch`) methods.
+*That is, they all have functioning sync, async and streaming generation methods.*
+
+This table highlights specifically those integrations that **natively support** streaming and asynchronous generation (meaning these features are built into the 3rd-party integration).
+
+{table}
+
+
+"""
+
+
+def get_llm_table():
+ llm_feat_table = {}
+ for cm in llms.__all__:
+ llm_feat_table[cm] = {}
+ cls = getattr(llms, cm)
+ if issubclass(cls, LLM):
+ for feat in ("_stream", "_astream", ("_acall", "_agenerate")):
+ if isinstance(feat, tuple):
+ feat, name = feat
+ else:
+ feat, name = feat, feat
+ llm_feat_table[cm][name] = getattr(cls, feat) != getattr(LLM, feat)
+ else:
+ for feat in [
+ "_stream",
+ "_astream",
+ ("_generate", "batch_generate"),
+ "_agenerate",
+ ("_agenerate", "batch_agenerate"),
+ ]:
+ if isinstance(feat, tuple):
+ feat, name = feat
+ else:
+ feat, name = feat, feat
+ llm_feat_table[cm][name] = getattr(cls, feat) != getattr(BaseLLM, feat)
+ final_feats = {
+ k: v
+ for k, v in {**llm_feat_table, **LLM_FEAT_TABLE_CORRECTION}.items()
+ if k not in LLM_IGNORE
+ }
+
+ header = [
+ "model",
+ "_agenerate",
+ "_stream",
+ "_astream",
+ "batch_generate",
+ "batch_agenerate",
+ ]
+ title = ["Model", "Generate", "Async generate", "Stream", "Async stream", "Batch", "Async batch"]
+ rows = [title, [":-"] + [":-:"] * (len(title) - 1)]
+ for llm, feats in sorted(final_feats.items()):
+ rows += [[llm, "✅"] + ["✅" if feats.get(h) else "❌" for h in header[1:]]]
+ return "\n".join(["|".join(row) for row in rows])
+
+
+def get_chat_model_table():
+ feat_table = {}
+ for cm in chat_models.__all__:
+ feat_table[cm] = {}
+ cls = getattr(chat_models, cm)
+ if issubclass(cls, SimpleChatModel):
+ comparison_cls = SimpleChatModel
+ else:
+ comparison_cls = BaseChatModel
+ for feat in ("_stream", "_astream", "_agenerate"):
+ feat_table[cm][feat] = getattr(cls, feat) != getattr(comparison_cls, feat)
+ final_feats = {
+ k: v
+ for k, v in {**feat_table, **CHAT_MODEL_FEAT_TABLE_CORRECTION}.items()
+ if k not in CHAT_MODEL_IGNORE
+ }
+ header = ["model", "_agenerate", "_stream", "_astream"]
+ title = ["Model", "Generate", "Async generate", "Stream", "Async stream"]
+ rows = [title, [":-"] + [":-:"] * (len(title) - 1)]
+ for llm, feats in sorted(final_feats.items()):
+ rows += [[llm, "✅"] + ["✅" if feats.get(h) else "❌" for h in header[1:]]]
+ return "\n".join(["|".join(row) for row in rows])
+
+
+if __name__ == "__main__":
+ llm_page = LLM_TEMPLATE.format(table=get_llm_table())
+ with open(INTEGRATIONS_DIR / "llms" / "index.mdx", "w") as f:
+ f.write(llm_page)
+ chat_model_page = CHAT_MODEL_TEMPLATE.format(table=get_chat_model_table())
+ with open(INTEGRATIONS_DIR / "chat" / "index.mdx", "w") as f:
+ f.write(chat_model_page)
diff --git a/docs/api_reference/create_api_rst.py b/docs/api_reference/create_api_rst.py
index 5cfe1bba1d3b5..dbe7f4b7577f9 100644
--- a/docs/api_reference/create_api_rst.py
+++ b/docs/api_reference/create_api_rst.py
@@ -1,7 +1,6 @@
"""Script for auto-generating api_reference.rst."""
import importlib
import inspect
-import os
import typing
from pathlib import Path
from typing import TypedDict, Sequence, List, Dict, Literal, Union, Optional
diff --git a/docs/docs_skeleton/sidebars.js b/docs/docs_skeleton/sidebars.js
index ad423cce54057..fde670dd44463 100644
--- a/docs/docs_skeleton/sidebars.js
+++ b/docs/docs_skeleton/sidebars.js
@@ -99,8 +99,8 @@ module.exports = {
label: "Components",
collapsible: false,
items: [
- { type: "category", label: "LLMs", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/llms" }], link: {type: "generated-index", slug: "integrations/llms" }},
- { type: "category", label: "Chat models", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/chat" }], link: {type: "generated-index", slug: "integrations/chat" }},
+ { type: "category", label: "LLMs", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/llms" }], link: { type: 'doc', id: "integrations/llms/index"}},
+ { type: "category", label: "Chat models", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/chat" }], link: { type: 'doc', id: "integrations/chat/index"}},
{ type: "category", label: "Document loaders", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/document_loaders" }], link: {type: "generated-index", slug: "integrations/document_loaders" }},
{ type: "category", label: "Document transformers", collapsed: true, items: [{type: "autogenerated", dirName: "integrations/document_transformers" }], link: {type: "generated-index", slug: "integrations/document_transformers" }},
{ type: "category", label: "Text embedding models", collapsed: true, items: [{type: "autogenerated", dirName: "integrations/text_embedding" }], link: {type: "generated-index", slug: "integrations/text_embedding" }},
diff --git a/docs/extras/integrations/chat/index.mdx b/docs/extras/integrations/chat/index.mdx
new file mode 100644
index 0000000000000..82c5f76169fcb
--- /dev/null
+++ b/docs/extras/integrations/chat/index.mdx
@@ -0,0 +1,36 @@
+---
+sidebar_position: 1
+sidebar_class_name: hidden
+---
+
+# Chat models
+
+import DocCardList from "@theme/DocCardList";
+
+## Features (natively supported)
+All `ChatModel`s implement the LCEL `Runnable` interface, meaning they all expose functioning `invoke`, `ainvoke`, `stream`, and `astream` (and `batch`, `abatch`) methods.
+*That is, they all have functioning sync, async and streaming generation methods.*
+
+This table highlights specifically those integrations that **natively support** streaming and asynchronous generation (meaning these features are built into the 3rd-party integration).
+
+Model|Generate|Async generate|Stream|Async stream
+:-|:-:|:-:|:-:|:-:
+AzureChatOpenAI|✅|✅|✅|✅
+BedrockChat|✅|❌|✅|❌
+ChatAnthropic|✅|✅|✅|✅
+ChatAnyscale|✅|✅|✅|✅
+ChatGooglePalm|✅|✅|❌|❌
+ChatJavelinAIGateway|✅|✅|❌|❌
+ChatKonko|✅|❌|❌|❌
+ChatLiteLLM|✅|✅|✅|✅
+ChatMLflowAIGateway|✅|❌|❌|❌
+ChatOllama|✅|❌|✅|❌
+ChatOpenAI|✅|✅|✅|✅
+ChatVertexAI|✅|❌|✅|❌
+ErnieBotChat|✅|❌|❌|❌
+JinaChat|✅|✅|✅|✅
+MiniMaxChat|✅|✅|❌|❌
+PromptLayerChatOpenAI|✅|❌|❌|❌
+QianfanChatEndpoint|✅|✅|✅|✅
+
+
diff --git a/docs/extras/integrations/llms/index.mdx b/docs/extras/integrations/llms/index.mdx
new file mode 100644
index 0000000000000..c76e92a0a3773
--- /dev/null
+++ b/docs/extras/integrations/llms/index.mdx
@@ -0,0 +1,91 @@
+---
+sidebar_position: 0
+sidebar_class_name: hidden
+---
+
+# LLMs
+
+import DocCardList from "@theme/DocCardList";
+
+## Features (natively supported)
+All `LLM`s implement the LCEL `Runnable` interface, meaning they all expose functioning `invoke`, `ainvoke`, `batch`, `abatch`, `stream`, and `astream` methods.
+*That is, they all have functioning sync, async, streaming, and batch generation methods.*
+
+This table highlights specifically those integrations that **natively support** batching, streaming, and asynchronous generation (meaning these features are built into the 3rd-party integration).
+
+Model|Generate|Async generate|Stream|Async stream|Batch|Async batch
+:-|:-:|:-:|:-:|:-:|:-:|:-:
+AI21|✅|❌|❌|❌|❌|❌
+AlephAlpha|✅|❌|❌|❌|❌|❌
+AmazonAPIGateway|✅|❌|❌|❌|❌|❌
+Anthropic|✅|✅|✅|✅|❌|❌
+Anyscale|✅|❌|❌|❌|❌|❌
+Aviary|✅|❌|❌|❌|❌|❌
+AzureMLOnlineEndpoint|✅|❌|❌|❌|❌|❌
+AzureOpenAI|✅|✅|✅|✅|✅|✅
+Banana|✅|❌|❌|❌|❌|❌
+Baseten|✅|❌|❌|❌|❌|❌
+Beam|✅|❌|❌|❌|❌|❌
+Bedrock|✅|❌|✅|❌|❌|❌
+CTransformers|✅|✅|❌|❌|❌|❌
+CTranslate2|✅|❌|❌|❌|✅|❌
+CerebriumAI|✅|❌|❌|❌|❌|❌
+ChatGLM|✅|❌|❌|❌|❌|❌
+Clarifai|✅|❌|❌|❌|❌|❌
+Cohere|✅|✅|❌|❌|❌|❌
+Databricks|✅|❌|❌|❌|❌|❌
+DeepInfra|✅|❌|❌|❌|❌|❌
+DeepSparse|✅|❌|❌|❌|❌|❌
+EdenAI|✅|✅|❌|❌|❌|❌
+Fireworks|✅|✅|❌|❌|✅|✅
+FireworksChat|✅|✅|❌|❌|✅|✅
+ForefrontAI|✅|❌|❌|❌|❌|❌
+GPT4All|✅|❌|❌|❌|❌|❌
+GooglePalm|✅|❌|❌|❌|✅|❌
+GooseAI|✅|❌|❌|❌|❌|❌
+GradientLLM|✅|✅|❌|❌|❌|❌
+HuggingFaceEndpoint|✅|❌|❌|❌|❌|❌
+HuggingFaceHub|✅|❌|❌|❌|❌|❌
+HuggingFacePipeline|✅|❌|❌|❌|❌|❌
+HuggingFaceTextGenInference|✅|✅|✅|✅|❌|❌
+HumanInputLLM|✅|❌|❌|❌|❌|❌
+JavelinAIGateway|✅|✅|❌|❌|❌|❌
+KoboldApiLLM|✅|❌|❌|❌|❌|❌
+LlamaCpp|✅|❌|✅|❌|❌|❌
+ManifestWrapper|✅|❌|❌|❌|❌|❌
+Minimax|✅|❌|❌|❌|❌|❌
+MlflowAIGateway|✅|❌|❌|❌|❌|❌
+Modal|✅|❌|❌|❌|❌|❌
+MosaicML|✅|❌|❌|❌|❌|❌
+NIBittensorLLM|✅|❌|❌|❌|❌|❌
+NLPCloud|✅|❌|❌|❌|❌|❌
+Nebula|✅|❌|❌|❌|❌|❌
+OctoAIEndpoint|✅|❌|❌|❌|❌|❌
+Ollama|✅|❌|❌|❌|❌|❌
+OpaquePrompts|✅|❌|❌|❌|❌|❌
+OpenAI|✅|✅|✅|✅|✅|✅
+OpenLLM|✅|✅|❌|❌|❌|❌
+OpenLM|✅|✅|✅|✅|✅|✅
+Petals|✅|❌|❌|❌|❌|❌
+PipelineAI|✅|❌|❌|❌|❌|❌
+Predibase|✅|❌|❌|❌|❌|❌
+PredictionGuard|✅|❌|❌|❌|❌|❌
+PromptLayerOpenAI|✅|❌|❌|❌|❌|❌
+QianfanLLMEndpoint|✅|✅|✅|✅|❌|❌
+RWKV|✅|❌|❌|❌|❌|❌
+Replicate|✅|❌|✅|❌|❌|❌
+SagemakerEndpoint|✅|❌|❌|❌|❌|❌
+SelfHostedHuggingFaceLLM|✅|❌|❌|❌|❌|❌
+SelfHostedPipeline|✅|❌|❌|❌|❌|❌
+StochasticAI|✅|❌|❌|❌|❌|❌
+TextGen|✅|❌|❌|❌|❌|❌
+TitanTakeoff|✅|❌|✅|❌|❌|❌
+Tongyi|✅|❌|❌|❌|❌|❌
+VLLM|✅|❌|❌|❌|✅|❌
+VLLMOpenAI|✅|✅|✅|✅|✅|✅
+VertexAI|✅|✅|❌|❌|❌|❌
+VertexAIModelGarden|✅|✅|❌|❌|❌|❌
+Writer|✅|❌|❌|❌|❌|❌
+Xinference|✅|❌|❌|❌|❌|❌
+
+
diff --git a/libs/langchain/langchain/chat_models/bedrock.py b/libs/langchain/langchain/chat_models/bedrock.py
index 139f1f55b8dc5..7ba186bb22206 100644
--- a/libs/langchain/langchain/chat_models/bedrock.py
+++ b/libs/langchain/langchain/chat_models/bedrock.py
@@ -1,7 +1,6 @@
-from typing import Any, AsyncIterator, Dict, Iterator, List, Optional
+from typing import Any, Dict, Iterator, List, Optional
from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
CallbackManagerForLLMRun,
)
from langchain.chat_models.anthropic import convert_messages_to_prompt_anthropic
@@ -59,17 +58,6 @@ def _stream(
delta = chunk.text
yield ChatGenerationChunk(message=AIMessageChunk(content=delta))
- def _astream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- raise NotImplementedError(
- """Bedrock doesn't support async requests at the moment."""
- )
-
def _generate(
self,
messages: List[BaseMessage],
@@ -98,14 +86,3 @@ def _generate(
message = AIMessage(content=completion)
return ChatResult(generations=[ChatGeneration(message=message)])
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- raise NotImplementedError(
- """Bedrock doesn't support async stream requests at the moment."""
- )
diff --git a/libs/langchain/langchain/utilities/vertexai.py b/libs/langchain/langchain/utilities/vertexai.py
index 95c493585a8ff..23f6d0011929a 100644
--- a/libs/langchain/langchain/utilities/vertexai.py
+++ b/libs/langchain/langchain/utilities/vertexai.py
@@ -30,8 +30,8 @@ def init_vertexai(
project: The default GCP project to use when making Vertex API calls.
location: The default location to use when making API calls.
credentials: The default custom
- credentials to use when making API calls. If not provided credentials
- will be ascertained from the environment.
+ credentials to use when making API calls. If not provided credentials
+ will be ascertained from the environment.
Raises:
ImportError: If importing vertexai SDK did not succeed.