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.