mirror of
https://github.com/hwchase17/langchain.git
synced 2026-02-08 10:09:46 +00:00
Compare commits
1 Commits
langchain-
...
erick/nov1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
796da053c6 |
1
.github/scripts/get_min_versions.py
vendored
1
.github/scripts/get_min_versions.py
vendored
@@ -23,7 +23,6 @@ MIN_VERSION_LIBS = [
|
||||
"langchain-community",
|
||||
"langchain",
|
||||
"langchain-text-splitters",
|
||||
"numpy",
|
||||
"SQLAlchemy",
|
||||
]
|
||||
|
||||
|
||||
32
.github/scripts/prep_api_docs_build.py
vendored
32
.github/scripts/prep_api_docs_build.py
vendored
@@ -23,19 +23,24 @@ def get_target_dir(package_name: str) -> Path:
|
||||
return base_path / "partners" / package_name_short
|
||||
|
||||
|
||||
def clean_target_directories(packages: list) -> None:
|
||||
def clean_target_directories(packages: Dict[str, Any]) -> None:
|
||||
"""Remove old directories that will be replaced."""
|
||||
for package in packages:
|
||||
|
||||
target_dir = get_target_dir(package["name"])
|
||||
if target_dir.exists():
|
||||
print(f"Removing {target_dir}")
|
||||
shutil.rmtree(target_dir)
|
||||
for package in packages["packages"]:
|
||||
if package["repo"] != "langchain-ai/langchain":
|
||||
target_dir = get_target_dir(package["name"])
|
||||
if target_dir.exists():
|
||||
print(f"Removing {target_dir}")
|
||||
shutil.rmtree(target_dir)
|
||||
|
||||
|
||||
def move_libraries(packages: list) -> None:
|
||||
def move_libraries(packages: Dict[str, Any]) -> None:
|
||||
"""Move libraries from their source locations to the target directories."""
|
||||
for package in packages:
|
||||
for package in packages["packages"]:
|
||||
# Skip if it's the main langchain repo or disabled
|
||||
if package["repo"] == "langchain-ai/langchain" or package.get(
|
||||
"disabled", False
|
||||
):
|
||||
continue
|
||||
|
||||
repo_name = package["repo"].split("/")[1]
|
||||
source_path = package["path"]
|
||||
@@ -63,14 +68,7 @@ def main():
|
||||
"""Main function to orchestrate the library sync process."""
|
||||
try:
|
||||
# Load packages configuration
|
||||
package_yaml = load_packages_yaml()
|
||||
packages = [
|
||||
p
|
||||
for p in package_yaml["packages"]
|
||||
if not p.get("disabled", False)
|
||||
and p["repo"].startswith("langchain-ai/")
|
||||
and p["repo"] != "langchain-ai/langchain"
|
||||
]
|
||||
packages = load_packages_yaml()
|
||||
|
||||
# Clean target directories
|
||||
clean_target_directories(packages)
|
||||
|
||||
62
.github/workflows/_release_docker.yml
vendored
Normal file
62
.github/workflows/_release_docker.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: release_docker
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
dockerfile:
|
||||
required: true
|
||||
type: string
|
||||
description: "Path to the Dockerfile to build"
|
||||
image:
|
||||
required: true
|
||||
type: string
|
||||
description: "Name of the image to build"
|
||||
|
||||
env:
|
||||
TEST_TAG: ${{ inputs.image }}:test
|
||||
LATEST_TAG: ${{ inputs.image }}:latest
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Get git tag
|
||||
uses: actions-ecosystem/action-get-latest-tag@v1
|
||||
id: get-latest-tag
|
||||
- name: Set docker tag
|
||||
env:
|
||||
VERSION: ${{ steps.get-latest-tag.outputs.tag }}
|
||||
run: |
|
||||
echo "VERSION_TAG=${{ inputs.image }}:${VERSION#v}" >> $GITHUB_ENV
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build for Test
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.dockerfile }}
|
||||
load: true
|
||||
tags: ${{ env.TEST_TAG }}
|
||||
- name: Test
|
||||
run: |
|
||||
docker run --rm ${{ env.TEST_TAG }} python -c "import langchain"
|
||||
- name: Build and Push to Docker Hub
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.dockerfile }}
|
||||
# We can only build for the intersection of platforms supported by
|
||||
# QEMU and base python image, for now build only for
|
||||
# linux/amd64 and linux/arm64
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ env.LATEST_TAG }},${{ env.VERSION_TAG }}
|
||||
push: true
|
||||
4
.github/workflows/api_doc_build.yml
vendored
4
.github/workflows/api_doc_build.yml
vendored
@@ -37,9 +37,9 @@ jobs:
|
||||
# Get unique repositories
|
||||
REPOS=$(echo "$REPOS_UNSORTED" | sort -u)
|
||||
|
||||
# Checkout each unique repository that is in langchain-ai org
|
||||
# Checkout each unique repository
|
||||
for repo in $REPOS; do
|
||||
if [[ "$repo" != "langchain-ai/langchain" && "$repo" == langchain-ai/* ]]; then
|
||||
if [ "$repo" != "langchain-ai/langchain" ]; then
|
||||
REPO_NAME=$(echo $repo | cut -d'/' -f2)
|
||||
echo "Checking out $repo to $REPO_NAME"
|
||||
git clone --depth 1 https://github.com/$repo.git $REPO_NAME
|
||||
|
||||
14
.github/workflows/langchain_release_docker.yml
vendored
Normal file
14
.github/workflows/langchain_release_docker.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: docker/langchain/langchain Release
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
|
||||
workflow_call: # Allows triggering from another workflow
|
||||
|
||||
jobs:
|
||||
release:
|
||||
uses: ./.github/workflows/_release_docker.yml
|
||||
with:
|
||||
dockerfile: docker/Dockerfile.base
|
||||
image: langchain/langchain
|
||||
secrets: inherit
|
||||
@@ -129,7 +129,7 @@ Please see [here](https://python.langchain.com) for full documentation, which in
|
||||
|
||||
- [🦜🛠️ LangSmith](https://docs.smith.langchain.com/): Trace and evaluate your language model applications and intelligent agents to help you move from prototype to production.
|
||||
- [🦜🕸️ LangGraph](https://langchain-ai.github.io/langgraph/): Create stateful, multi-actor applications with LLMs. Integrates smoothly with LangChain, but can be used without it.
|
||||
- [🦜🕸️ LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/#langgraph-platform): Deploy LLM applications built with LangGraph into production.
|
||||
- [🦜🏓 LangServe](https://python.langchain.com/docs/langserve): Deploy LangChain runnables and chains as REST APIs.
|
||||
|
||||
## 💁 Contributing
|
||||
|
||||
|
||||
3
docker/Dockerfile.base
Normal file
3
docker/Dockerfile.base
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM python:3.11
|
||||
|
||||
RUN pip install langchain
|
||||
12
docker/Makefile
Normal file
12
docker/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
# Makefile
|
||||
|
||||
build_graphdb:
|
||||
docker build --tag graphdb ./graphdb
|
||||
|
||||
start_graphdb:
|
||||
docker-compose up -d graphdb
|
||||
|
||||
down:
|
||||
docker-compose down -v --remove-orphans
|
||||
|
||||
.PHONY: build_graphdb start_graphdb down
|
||||
84
docker/docker-compose.yml
Normal file
84
docker/docker-compose.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
# docker-compose to make it easier to spin up integration tests.
|
||||
# Services should use NON standard ports to avoid collision with
|
||||
# any existing services that might be used for development.
|
||||
# ATTENTION: When adding a service below use a non-standard port
|
||||
# increment by one from the preceding port.
|
||||
# For credentials always use `langchain` and `langchain` for the
|
||||
# username and password.
|
||||
version: "3"
|
||||
name: langchain-tests
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis/redis-stack-server:latest
|
||||
# We use non standard ports since
|
||||
# these instances are used for testing
|
||||
# and users may already have existing
|
||||
# redis instances set up locally
|
||||
# for other projects
|
||||
ports:
|
||||
- "6020:6379"
|
||||
volumes:
|
||||
- ./redis-volume:/data
|
||||
graphdb:
|
||||
image: graphdb
|
||||
ports:
|
||||
- "6021:7200"
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
container_name: mongo_container
|
||||
ports:
|
||||
- "6022:27017"
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: langchain
|
||||
MONGO_INITDB_ROOT_PASSWORD: langchain
|
||||
postgres:
|
||||
image: postgres:16
|
||||
environment:
|
||||
POSTGRES_DB: langchain
|
||||
POSTGRES_USER: langchain
|
||||
POSTGRES_PASSWORD: langchain
|
||||
ports:
|
||||
- "6023:5432"
|
||||
command: |
|
||||
postgres -c log_statement=all
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"psql postgresql://langchain:langchain@localhost/langchain --command 'SELECT 1;' || exit 1",
|
||||
]
|
||||
interval: 5s
|
||||
retries: 60
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
pgvector:
|
||||
# postgres with the pgvector extension
|
||||
image: ankane/pgvector
|
||||
environment:
|
||||
POSTGRES_DB: langchain
|
||||
POSTGRES_USER: langchain
|
||||
POSTGRES_PASSWORD: langchain
|
||||
ports:
|
||||
- "6024:5432"
|
||||
command: |
|
||||
postgres -c log_statement=all
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"psql postgresql://langchain:langchain@localhost/langchain --command 'SELECT 1;' || exit 1",
|
||||
]
|
||||
interval: 5s
|
||||
retries: 60
|
||||
volumes:
|
||||
- postgres_data_pgvector:/var/lib/postgresql/data
|
||||
vdms:
|
||||
image: intellabs/vdms:latest
|
||||
container_name: vdms_container
|
||||
ports:
|
||||
- "6025:55555"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
postgres_data_pgvector:
|
||||
5
docker/graphdb/Dockerfile
Normal file
5
docker/graphdb/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
||||
FROM ontotext/graphdb:10.5.1
|
||||
RUN mkdir -p /opt/graphdb/dist/data/repositories/langchain
|
||||
COPY config.ttl /opt/graphdb/dist/data/repositories/langchain/
|
||||
COPY graphdb_create.sh /run.sh
|
||||
ENTRYPOINT bash /run.sh
|
||||
46
docker/graphdb/config.ttl
Normal file
46
docker/graphdb/config.ttl
Normal file
@@ -0,0 +1,46 @@
|
||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
|
||||
@prefix rep: <http://www.openrdf.org/config/repository#>.
|
||||
@prefix sr: <http://www.openrdf.org/config/repository/sail#>.
|
||||
@prefix sail: <http://www.openrdf.org/config/sail#>.
|
||||
@prefix graphdb: <http://www.ontotext.com/config/graphdb#>.
|
||||
|
||||
[] a rep:Repository ;
|
||||
rep:repositoryID "langchain" ;
|
||||
rdfs:label "" ;
|
||||
rep:repositoryImpl [
|
||||
rep:repositoryType "graphdb:SailRepository" ;
|
||||
sr:sailImpl [
|
||||
sail:sailType "graphdb:Sail" ;
|
||||
|
||||
graphdb:read-only "false" ;
|
||||
|
||||
# Inference and Validation
|
||||
graphdb:ruleset "empty" ;
|
||||
graphdb:disable-sameAs "true" ;
|
||||
graphdb:check-for-inconsistencies "false" ;
|
||||
|
||||
# Indexing
|
||||
graphdb:entity-id-size "32" ;
|
||||
graphdb:enable-context-index "false" ;
|
||||
graphdb:enablePredicateList "true" ;
|
||||
graphdb:enable-fts-index "false" ;
|
||||
graphdb:fts-indexes ("default" "iri") ;
|
||||
graphdb:fts-string-literals-index "default" ;
|
||||
graphdb:fts-iris-index "none" ;
|
||||
|
||||
# Queries and Updates
|
||||
graphdb:query-timeout "0" ;
|
||||
graphdb:throw-QueryEvaluationException-on-timeout "false" ;
|
||||
graphdb:query-limit-results "0" ;
|
||||
|
||||
# Settable in the file but otherwise hidden in the UI and in the RDF4J console
|
||||
graphdb:base-URL "http://example.org/owlim#" ;
|
||||
graphdb:defaultNS "" ;
|
||||
graphdb:imports "" ;
|
||||
graphdb:repository-type "file-repository" ;
|
||||
graphdb:storage-folder "storage" ;
|
||||
graphdb:entity-index-size "10000000" ;
|
||||
graphdb:in-memory-literal-properties "true" ;
|
||||
graphdb:enable-literal-index "true" ;
|
||||
]
|
||||
].
|
||||
28
docker/graphdb/graphdb_create.sh
Normal file
28
docker/graphdb/graphdb_create.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#! /bin/bash
|
||||
REPOSITORY_ID="langchain"
|
||||
GRAPHDB_URI="http://localhost:7200/"
|
||||
|
||||
echo -e "\nUsing GraphDB: ${GRAPHDB_URI}"
|
||||
|
||||
function startGraphDB {
|
||||
echo -e "\nStarting GraphDB..."
|
||||
exec /opt/graphdb/dist/bin/graphdb
|
||||
}
|
||||
|
||||
function waitGraphDBStart {
|
||||
echo -e "\nWaiting GraphDB to start..."
|
||||
for _ in $(seq 1 5); do
|
||||
CHECK_RES=$(curl --silent --write-out '%{http_code}' --output /dev/null ${GRAPHDB_URI}/rest/repositories)
|
||||
if [ "${CHECK_RES}" = '200' ]; then
|
||||
echo -e "\nUp and running"
|
||||
break
|
||||
fi
|
||||
sleep 30s
|
||||
echo "CHECK_RES: ${CHECK_RES}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
startGraphDB &
|
||||
waitGraphDBStart
|
||||
wait
|
||||
@@ -38,7 +38,7 @@ install-py-deps:
|
||||
|
||||
generate-files:
|
||||
mkdir -p $(INTERMEDIATE_DIR)
|
||||
cp -rp $(SOURCE_DIR)/* $(INTERMEDIATE_DIR)
|
||||
cp -r $(SOURCE_DIR)/* $(INTERMEDIATE_DIR)
|
||||
|
||||
$(PYTHON) scripts/tool_feat_table.py $(INTERMEDIATE_DIR)
|
||||
|
||||
|
||||
@@ -495,7 +495,6 @@ def _package_dir(package_name: str = "langchain") -> Path:
|
||||
"core",
|
||||
"cli",
|
||||
"text-splitters",
|
||||
"standard-tests",
|
||||
):
|
||||
return ROOT_DIR / "libs" / package_name / _package_namespace(package_name)
|
||||
else:
|
||||
@@ -650,7 +649,7 @@ def main(dirs: Optional[list] = None) -> None:
|
||||
dirs = [
|
||||
dir_
|
||||
for dir_ in os.listdir(ROOT_DIR / "libs")
|
||||
if dir_ not in ("cli", "partners", "packages.yml")
|
||||
if dir_ not in ("cli", "partners", "standard-tests", "packages.yml")
|
||||
]
|
||||
dirs += [
|
||||
dir_
|
||||
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
1
docs/cassettes/llm_chain_3e82f933.msgpack.zlib
Normal file
1
docs/cassettes/llm_chain_3e82f933.msgpack.zlib
Normal file
@@ -0,0 +1 @@
|
||||
eNptVWtsFFUULpSgEh8VRGOMYboaf5jOdGZfs1Mkpt2Wtva9Wyqr0XX2zt3daWfmTufeaXdbqxEJCVHUkYjvH6XLLja18mgEQYxRVDQIGo2mKBpf8YGvoMSoIXhnu5U2ZZJ93HvO+c7rO2c2FAaghVVkLJpQDQItGRB6wM6GggX7bYjJxrwOSRopuc6OaPeYbanTN6cJMXFNdbVsqhwyoSGrHEB69YBQDdIyqab/TQ0WYXIJpGSn3xr26BBjOQWxp4a5c9gDEHVlEHrwdFuygTWZQIakIZNEmoYGVSPFJC2kMw1GSlNxmqGRIaaZyJoqG54qxmMhDbrGOIsJ1D0jVcw8zLRaOVfLxtDyjNxFb3SkQM29SpmE9bs6Bj0J9BcTC8o6PSRlDUN6QXFNWg1iWy4Gz4kjhTSUFVqrL8oqcmmEiTM5P/+XZAAgxYUGQApNwXkxNaSaVYwCk25+4zRAAxar64z3QWiyNJ0BmJ+xcnbJpqmpQHbl1b0YGROlhFiSNeFC8bibFUtLahBnqoMGUdtc3ZmljTIYgfOHOH5XhsVEVg2NVp7VZBpP3izKD84VmDLooyBsiQROfsZ4cq4Ows6ONhl0ROdByhZIOztkSw/69869t2yDqDp0CuHOhe5KwvPufJwgcOLuecA4awBnR7ER++YZQ2JlWYAohjPK5wFCfSp0pk/H4yAZT+hrYvGMn7PXa7qvPgpU3N0eE02f0M1JdWZPrHGdnkKDTa2dGc5WeFYQvaI/4BVDAVbgeE7gBDbeqpnK2t6ot8enDdWH7Egk3hDpao73IHSH39ZJb3sDJi2wPRkTYk23c1YmkQx2Ndh3iP3pbFOsUU6B2zgx2zPQ0FHXn6j1RmJ6X5NZu5qh0dkDqrKmV2sNCd51sf7WxECgiQ93cX4xjnt9SG/PBH29XRwJ1hMxjKRg85zwBCnE8qUIg7w/xLvP5Cw3NGikSNoZEyRxpwWxSUcOPpinJSM23pCjPIRHjxRKs7e9o+U8hVfm6iknnUNrLbWK8YpMFJqMl/f6GSFQE5Bq/EGmsa17Ilxy031BCu4uzm6S0rBhlvIFkLaNPqiMhy9I9kMu2Wkn3fDpdLIwYyIM2VJUzsR6NjKzdNjm+r0zk8UiKyUb6lDRrXOoyPrBocygAmxFSQ8M6rw05PepCWiD5FTJxLSQ64YGxOrYGQt6xcmSZJZ34zRXSgKe5YVX6OirgI6Zm4yJLMJiCOiaI1lnukqXM+6MrfEJAV+QFn41XUVAsxUYtRP1SKfMxKsZ04IakpUDGZbuC6ipukobU/wurVDs5ALUeP9CBYL6IF22O4ptfW2u3IIuupvCeRC/JEmvXlhpFkiUpKB0YL4OhnMjEbw63r9QoQSQ8/p0PJGZ1WdVxZm+kR7iCb8EkkmJktIrepWkKCdlPiRBRQ4lFN4bkF4Kr2XDMkhDNlpkn1Ooj7XXtjWHX17PzqUR22HOvGAKBsKGmkzmo9CibXHGgYZsha5KC+YpVqQ25kyFgAQSPhiSAAiGkkBk6+gSmkX7n3Q5d88W3zQP5N1mGqm3FoVXPXRxWfEpp59z58hj77e/yVds/C27bO/3V595dOl3myqWL2dClUvqnFPa8ug7fT9vWTL+z69H1GemLuKko98/ffQYd+VisujpsnUtPVt8Hz372dThr0dPPP7VFPvTwcKnT54+u/tjdPzLv/jNl5+4d/TrsVORrm8u3XPT8OvvjSkPv/AHfTtMXv3jmQPll61Mb3/RuuWuttSpv/cMfpxbufTI4UbPxoqDv153cHrx/cyKve92qfySWKXy5g2Vr2/dvOxIBblHvfamG7qVa38ZndxG+t+7ZZv+2O6t+pYfz5z93Rd+4o+pS9as+jNy5/U/fT52qQLMe6wPPhzxHE4Ndg9/suK5wtv9x6Yariu/5mwbf0x8Ax5/av0zK46fvrXjbqZFf+NdztxZ0ANLj2565KRTcV852PrkiZ4fnv/0ZOvJq/799gq3UuVly2L7Oq5fXFb2H5UFMyI=
|
||||
1
docs/cassettes/llm_chain_6bacb837.msgpack.zlib
Normal file
1
docs/cassettes/llm_chain_6bacb837.msgpack.zlib
Normal file
@@ -0,0 +1 @@
|
||||
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
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -46,7 +46,7 @@ Most popular LangChain integrations implement asynchronous support of their APIs
|
||||
When an asynchronous implementation is not available, LangChain tries to provide a default implementation, even if it incurs
|
||||
a **slight** overhead.
|
||||
|
||||
By default, LangChain will delegate the execution of unimplemented asynchronous methods to the synchronous counterparts. LangChain almost always assumes that the synchronous method should be treated as a blocking operation and should be run in a separate thread.
|
||||
By default, LangChain will delegate the execution of a unimplemented asynchronous methods to the synchronous counterparts. LangChain almost always assumes that the synchronous method should be treated as a blocking operation and should be run in a separate thread.
|
||||
This is done using [asyncio.loop.run_in_executor](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor) functionality provided by the `asyncio` library. LangChain uses the default executor provided by the `asyncio` library, which lazily initializes a thread pool executor with a default number of threads that is reused in the given event loop. While this strategy incurs a slight overhead due to context switching between threads, it guarantees that every asynchronous method has a default implementation that works out of the box.
|
||||
|
||||
## Performance
|
||||
|
||||
@@ -22,7 +22,6 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- **[Memory](https://langchain-ai.github.io/langgraph/concepts/memory/)**: Information about a conversation that is persisted so that it can be used in future conversations.
|
||||
- **[Multimodality](/docs/concepts/multimodality)**: The ability to work with data that comes in different forms, such as text, audio, images, and video.
|
||||
- **[Runnable interface](/docs/concepts/runnables)**: The base abstraction that many LangChain components and the LangChain Expression Language are built on.
|
||||
- **[Streaming](/docs/concepts/streaming)**: LangChain streaming APIs for surfacing results as they are generated.
|
||||
- **[LangChain Expression Language (LCEL)](/docs/concepts/lcel)**: A syntax for orchestrating LangChain components. Most useful for simpler applications.
|
||||
- **[Document loaders](/docs/concepts/document_loaders)**: Load a source as a list of documents.
|
||||
- **[Retrieval](/docs/concepts/retrieval)**: Information retrieval systems can retrieve structured or unstructured data from a datasource in response to a query.
|
||||
@@ -40,7 +39,6 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- **[Callbacks](/docs/concepts/callbacks)**: Callbacks enable the execution of custom auxiliary code in built-in components. Callbacks are used to stream outputs from LLMs in LangChain, trace the intermediate steps of an application, and more.
|
||||
- **[Tracing](/docs/concepts/tracing)**: The process of recording the steps that an application takes to go from input to output. Tracing is essential for debugging and diagnosing issues in complex applications.
|
||||
- **[Evaluation](/docs/concepts/evaluation)**: The process of assessing the performance and effectiveness of AI applications. This involves testing the model's responses against a set of predefined criteria or benchmarks to ensure it meets the desired quality standards and fulfills the intended purpose. This process is vital for building reliable applications.
|
||||
- **[Testing](/docs/concepts/testing)**: The process of verifying that a component of an integration or application works as expected. Testing is essential for ensuring that the application behaves correctly and that changes to the codebase do not introduce new bugs.
|
||||
|
||||
## Glossary
|
||||
|
||||
@@ -63,7 +61,6 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- **[InjectedToolArg](/docs/concepts/tools#injectedtoolarg)**: Mechanism to inject arguments into tool functions.
|
||||
- **[input and output types](/docs/concepts/runnables#input-and-output-types)**: Types used for input and output in Runnables.
|
||||
- **[Integration packages](/docs/concepts/architecture/#integration-packages)**: Third-party packages that integrate with LangChain.
|
||||
- **[Integration tests](/docs/concepts/testing#integration-tests)**: Tests that verify the correctness of the interaction between components, usually run with access to the underlying API that powers an integration.
|
||||
- **[invoke](/docs/concepts/runnables)**: A standard method to invoke a Runnable.
|
||||
- **[JSON mode](/docs/concepts/structured_outputs#json-mode)**: Returning responses in JSON format.
|
||||
- **[langchain-community](/docs/concepts/architecture#langchain-community)**: Community-driven components for LangChain.
|
||||
@@ -71,7 +68,6 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- **[langchain](/docs/concepts/architecture#langchain)**: A package for higher level components (e.g., some pre-built chains).
|
||||
- **[langgraph](/docs/concepts/architecture#langgraph)**: Powerful orchestration layer for LangChain. Use to build complex pipelines and workflows.
|
||||
- **[langserve](/docs/concepts/architecture#langserve)**: Use to deploy LangChain Runnables as REST endpoints. Uses FastAPI. Works primarily for LangChain Runnables, does not currently integrate with LangGraph.
|
||||
- **[LLMs (legacy)](/docs/concepts/text_llms)**: Older language models that take a string as input and return a string as output.
|
||||
- **[Managing chat history](/docs/concepts/chat_history#managing-chat-history)**: Techniques to maintain and manage the chat history.
|
||||
- **[OpenAI format](/docs/concepts/messages#openai-format)**: OpenAI's message format for chat models.
|
||||
- **[Propagation of RunnableConfig](/docs/concepts/runnables/#propagation-of-runnableconfig)**: Propagating configuration through Runnables. Read if working with python 3.9, 3.10 and async.
|
||||
@@ -80,7 +76,6 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- **[role](/docs/concepts/messages#role)**: Represents the role (e.g., user, assistant) of a chat message.
|
||||
- **[RunnableConfig](/docs/concepts/runnables/#runnableconfig)**: Use to pass run time information to Runnables (e.g., `run_name`, `run_id`, `tags`, `metadata`, `max_concurrency`, `recursion_limit`, `configurable`).
|
||||
- **[Standard parameters for chat models](/docs/concepts/chat_models#standard-parameters)**: Parameters such as API key, `temperature`, and `max_tokens`,
|
||||
- **[Standard tests](/docs/concepts/testing#standard-tests)**: A defined set of unit and integration tests that all integrations must pass.
|
||||
- **[stream](/docs/concepts/streaming)**: Use to stream output from a Runnable or a graph.
|
||||
- **[Tokenization](/docs/concepts/tokens)**: The process of converting data into tokens and vice versa.
|
||||
- **[Tokens](/docs/concepts/tokens)**: The basic unit that a language model reads, processes, and generates under the hood.
|
||||
@@ -89,7 +84,6 @@ The conceptual guide does not cover step-by-step instructions or specific implem
|
||||
- **[@tool](/docs/concepts/tools/#create-tools-using-the-tool-decorator)**: Decorator for creating tools in LangChain.
|
||||
- **[Toolkits](/docs/concepts/tools#toolkits)**: A collection of tools that can be used together.
|
||||
- **[ToolMessage](/docs/concepts/messages#toolmessage)**: Represents a message that contains the results of a tool execution.
|
||||
- **[Unit tests](/docs/concepts/testing#unit-tests)**: Tests that verify the correctness of individual components, run in isolation without access to the Internet.
|
||||
- **[Vector stores](/docs/concepts/vectorstores)**: Datastores specialized for storing and efficiently searching vector embeddings.
|
||||
- **[with_structured_output](/docs/concepts/structured_outputs/#structured-output-method)**: A helper method for chat models that natively support [tool calling](/docs/concepts/tool_calling) to get structured output matching a given schema specified via Pydantic, JSON schema or a function.
|
||||
- **[with_types](/docs/concepts/runnables#with_types)**: Method to overwrite the input and output types of a runnable. Useful when working with complex LCEL chains and deploying with LangServe.
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Testing
|
||||
<span data-heading-keywords="tests,testing,unit,integration"></span>
|
||||
|
||||
Testing is a critical part of the development process that ensures your code works as expected and meets the desired quality standards.
|
||||
|
||||
In the LangChain ecosystem, we have 2 main types of tests: **unit tests** and **integration tests**.
|
||||
|
||||
For integrations that implement standard LangChain abstractions, we have a set of **standard tests** (both unit and integration) that help maintain compatibility between different components and ensure reliability of high-usage ones.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
**Definition**: Unit tests are designed to validate the smallest parts of your code—individual functions or methods—ensuring they work as expected in isolation. They do not rely on external systems or integrations.
|
||||
|
||||
**Example**: Testing the `convert_langchain_aimessage_to_dict` function to confirm it correctly converts an AI message to a dictionary format:
|
||||
|
||||
```python
|
||||
from langchain_core.messages import AIMessage, ToolCall, convert_to_openai_messages
|
||||
|
||||
def test_convert_to_openai_messages():
|
||||
ai_message = AIMessage(
|
||||
content="Let me call that tool for you!",
|
||||
tool_calls=[
|
||||
ToolCall(name='parrot_multiply_tool', id='1', args={'a': 2, 'b': 3}),
|
||||
]
|
||||
)
|
||||
|
||||
result = convert_to_openai_messages(ai_message)
|
||||
|
||||
expected = {
|
||||
"role": "assistant",
|
||||
"tool_calls": [
|
||||
{
|
||||
"type": "function",
|
||||
"id": "1",
|
||||
"function": {
|
||||
"name": "parrot_multiply_tool",
|
||||
"arguments": '{"a": 2, "b": 3}',
|
||||
},
|
||||
}
|
||||
],
|
||||
"content": "Let me call that tool for you!",
|
||||
}
|
||||
assert result == expected # Ensure conversion matches expected output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration Tests
|
||||
|
||||
**Definition**: Integration tests validate that multiple components or systems work together as expected. For tools or integrations relying on external services, these tests often ensure end-to-end functionality.
|
||||
|
||||
**Example**: Testing `ParrotMultiplyTool` with access to an API service that multiplies two numbers and adds 80:
|
||||
|
||||
```python
|
||||
def test_integration_with_service():
|
||||
tool = ParrotMultiplyTool()
|
||||
result = tool.invoke({"a": 2, "b": 3})
|
||||
assert result == 86
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Standard Tests
|
||||
|
||||
**Definition**: Standard tests are pre-defined tests provided by LangChain to ensure consistency and reliability across all tools and integrations. They include both unit and integration test templates tailored for LangChain components.
|
||||
|
||||
**Example**: Subclassing LangChain's `ToolsUnitTests` or `ToolsIntegrationTests` to automatically run standard tests:
|
||||
|
||||
```python
|
||||
from langchain_tests.unit_tests import ToolsUnitTests
|
||||
|
||||
class TestParrotMultiplyToolUnit(ToolsUnitTests):
|
||||
@property
|
||||
def tool_constructor(self):
|
||||
return ParrotMultiplyTool
|
||||
|
||||
def tool_invoke_params_example(self):
|
||||
return {"a": 2, "b": 3}
|
||||
```
|
||||
|
||||
To learn more, check out our guide on [how to add standard tests to an integration](../../contributing/how_to/integrations/standard_tests).
|
||||
@@ -77,7 +77,7 @@ The central concept to understand is that LangChain provides a standardized inte
|
||||
The `.bind_tools()` method can be used to specify which tools are available for a model to call.
|
||||
|
||||
```python
|
||||
model_with_tools = model.bind_tools(tools_list)
|
||||
model_with_tools = model.bind_tools([tools_list])
|
||||
```
|
||||
|
||||
As a specific example, let's take a function `multiply` and bind it as a tool to a model that supports tool calling.
|
||||
|
||||
@@ -29,7 +29,7 @@ or new agents/chains from outside contributors without an existing GitHub discus
|
||||
|
||||
- New features must come with docs, unit tests, and (if appropriate) integration tests.
|
||||
- New integrations must come with docs, unit tests, and (if appropriate) integration tests.
|
||||
- See [this page](../integrations/index.mdx) for more details on contributing new integrations.
|
||||
- See [this page](../integrations.mdx) for more details on contributing new integrations.
|
||||
- New functionality should not inherit from or use deprecated methods or classes.
|
||||
- We will reject features that are likely to lead to security vulnerabilities or reports.
|
||||
- Do not add any hard dependencies. Integrations may add optional dependencies.
|
||||
|
||||
@@ -2,9 +2,4 @@
|
||||
|
||||
- [**Documentation**](documentation/index.mdx): Help improve our docs, including this one!
|
||||
- [**Code**](code/index.mdx): Help us write code, fix bugs, or improve our infrastructure.
|
||||
|
||||
## Integrations
|
||||
|
||||
- [**Start Here**](integrations/index.mdx): Help us integrate with your favorite vendors and tools.
|
||||
- [**Package**](integrations/package): Publish an integration package to PyPi
|
||||
- [**Standard Tests**](integrations/standard_tests): Ensure your integration passes an expected set of tests.
|
||||
- [**Integrations**](integrations.mdx): Help us integrate with your favorite vendors and tools.
|
||||
203
docs/docs/contributing/how_to/integrations.mdx
Normal file
203
docs/docs/contributing/how_to/integrations.mdx
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Contribute Integrations
|
||||
|
||||
To begin, make sure you have all the dependencies outlined in guide on [Contributing Code](code/index.mdx).
|
||||
|
||||
There are a few different places you can contribute integrations for LangChain:
|
||||
|
||||
- **Community**: For lighter-weight integrations that are primarily maintained by LangChain and the Open Source Community.
|
||||
- **Partner Packages**: For independent packages that are co-maintained by LangChain and a partner.
|
||||
|
||||
For the most part, **new integrations should be added to the Community package**. Partner packages require more maintenance as separate packages, so please confirm with the LangChain team before creating a new partner package.
|
||||
|
||||
In the following sections, we'll walk through how to contribute to each of these packages from a fake company, `Parrot Link AI`.
|
||||
|
||||
## Community package
|
||||
|
||||
The `langchain-community` package is in `libs/community` and contains most integrations.
|
||||
|
||||
It can be installed with `pip install langchain-community`, and exported members can be imported with code like
|
||||
|
||||
```python
|
||||
from langchain_community.chat_models import ChatParrotLink
|
||||
from langchain_community.llms import ParrotLinkLLM
|
||||
from langchain_community.vectorstores import ParrotLinkVectorStore
|
||||
```
|
||||
|
||||
The `community` package relies on manually-installed dependent packages, so you will see errors
|
||||
if you try to import a package that is not installed. In our fake example, if you tried to import `ParrotLinkLLM` without installing `parrot-link-sdk`, you will see an `ImportError` telling you to install it when trying to use it.
|
||||
|
||||
Let's say we wanted to implement a chat model for Parrot Link AI. We would create a new file in `libs/community/langchain_community/chat_models/parrot_link.py` with the following code:
|
||||
|
||||
```python
|
||||
from langchain_core.language_models.chat_models import BaseChatModel
|
||||
|
||||
class ChatParrotLink(BaseChatModel):
|
||||
"""ChatParrotLink chat model.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from langchain_community.chat_models import ChatParrotLink
|
||||
|
||||
model = ChatParrotLink()
|
||||
"""
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
And we would write tests in:
|
||||
|
||||
- Unit tests: `libs/community/tests/unit_tests/chat_models/test_parrot_link.py`
|
||||
- Integration tests: `libs/community/tests/integration_tests/chat_models/test_parrot_link.py`
|
||||
|
||||
And add documentation to:
|
||||
|
||||
- `docs/docs/integrations/chat/parrot_link.ipynb`
|
||||
|
||||
## Partner package in LangChain repo
|
||||
|
||||
:::caution
|
||||
Before starting a **partner** package, please confirm your intent with the LangChain team. Partner packages require more maintenance as separate packages, so we will close PRs that add new partner packages without prior discussion. See the above section for how to add a community integration.
|
||||
:::
|
||||
|
||||
Partner packages can be hosted in the `LangChain` monorepo or in an external repo.
|
||||
|
||||
Partner package in the `LangChain` repo is placed in `libs/partners/{partner}`
|
||||
and the package source code is in `libs/partners/{partner}/langchain_{partner}`.
|
||||
|
||||
A package is
|
||||
installed by users with `pip install langchain-{partner}`, and the package members
|
||||
can be imported with code like:
|
||||
|
||||
```python
|
||||
from langchain_{partner} import X
|
||||
```
|
||||
|
||||
### Set up a new package
|
||||
|
||||
To set up a new partner package, use the latest version of the LangChain CLI. You can install or update it with:
|
||||
|
||||
```bash
|
||||
pip install -U langchain-cli
|
||||
```
|
||||
|
||||
Let's say you want to create a new partner package working for a company called Parrot Link AI.
|
||||
|
||||
Then, run the following command to create a new partner package:
|
||||
|
||||
```bash
|
||||
cd libs/partners
|
||||
langchain-cli integration new
|
||||
> Name: parrot-link
|
||||
> Name of integration in PascalCase [ParrotLink]: ParrotLink
|
||||
```
|
||||
|
||||
This will create a new package in `libs/partners/parrot-link` with the following structure:
|
||||
|
||||
```
|
||||
libs/partners/parrot-link/
|
||||
langchain_parrot_link/ # folder containing your package
|
||||
...
|
||||
tests/
|
||||
...
|
||||
docs/ # bootstrapped docs notebooks, must be moved to /docs in monorepo root
|
||||
...
|
||||
scripts/ # scripts for CI
|
||||
...
|
||||
LICENSE
|
||||
README.md # fill out with information about your package
|
||||
Makefile # default commands for CI
|
||||
pyproject.toml # package metadata, mostly managed by Poetry
|
||||
poetry.lock # package lockfile, managed by Poetry
|
||||
.gitignore
|
||||
```
|
||||
|
||||
### Implement your package
|
||||
|
||||
First, add any dependencies your package needs, such as your company's SDK:
|
||||
|
||||
```bash
|
||||
poetry add parrot-link-sdk
|
||||
```
|
||||
|
||||
If you need separate dependencies for type checking, you can add them to the `typing` group with:
|
||||
|
||||
```bash
|
||||
poetry add --group typing types-parrot-link-sdk
|
||||
```
|
||||
|
||||
Then, implement your package in `libs/partners/parrot-link/langchain_parrot_link`.
|
||||
|
||||
By default, this will include stubs for a Chat Model, an LLM, and/or a Vector Store. You should delete any of the files you won't use and remove them from `__init__.py`.
|
||||
|
||||
### Write Unit and Integration Tests
|
||||
|
||||
Some basic tests are presented in the `tests/` directory. You should add more tests to cover your package's functionality.
|
||||
|
||||
For information on running and implementing tests, see the [Testing guide](testing.mdx).
|
||||
|
||||
### Write documentation
|
||||
|
||||
Documentation is generated from Jupyter notebooks in the `docs/` directory. You should place the notebooks with examples
|
||||
to the relevant `docs/docs/integrations` directory in the monorepo root.
|
||||
|
||||
### (If Necessary) Deprecate community integration
|
||||
|
||||
Note: this is only necessary if you're migrating an existing community integration into
|
||||
a partner package. If the component you're integrating is net-new to LangChain (i.e.
|
||||
not already in the `community` package), you can skip this step.
|
||||
|
||||
Let's pretend we migrated our `ChatParrotLink` chat model from the community package to
|
||||
the partner package. We would need to deprecate the old model in the community package.
|
||||
|
||||
We would do that by adding a `@deprecated` decorator to the old model as follows, in
|
||||
`libs/community/langchain_community/chat_models/parrot_link.py`.
|
||||
|
||||
Before our change, our chat model might look like this:
|
||||
|
||||
```python
|
||||
class ChatParrotLink(BaseChatModel):
|
||||
...
|
||||
```
|
||||
|
||||
After our change, it would look like this:
|
||||
|
||||
```python
|
||||
from langchain_core._api.deprecation import deprecated
|
||||
|
||||
@deprecated(
|
||||
since="0.0.<next community version>",
|
||||
removal="0.2.0",
|
||||
alternative_import="langchain_parrot_link.ChatParrotLink"
|
||||
)
|
||||
class ChatParrotLink(BaseChatModel):
|
||||
...
|
||||
```
|
||||
|
||||
You should do this for *each* component that you're migrating to the partner package.
|
||||
|
||||
### Additional steps
|
||||
|
||||
Contributor steps:
|
||||
|
||||
- [ ] Add secret names to manual integrations workflow in `.github/workflows/_integration_test.yml`
|
||||
- [ ] Add secrets to release workflow (for pre-release testing) in `.github/workflows/_release.yml`
|
||||
|
||||
Maintainer steps (Contributors should **not** do these):
|
||||
|
||||
- [ ] set up pypi and test pypi projects
|
||||
- [ ] add credential secrets to Github Actions
|
||||
- [ ] add package to conda-forge
|
||||
|
||||
## Partner package in external repo
|
||||
|
||||
Partner packages in external repos must be coordinated between the LangChain team and
|
||||
the partner organization to ensure that they are maintained and updated.
|
||||
|
||||
If you're interested in creating a partner package in an external repo, please start
|
||||
with one in the LangChain repo, and then reach out to the LangChain team to discuss
|
||||
how to move it to an external repo.
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
pagination_next: null
|
||||
pagination_prev: null
|
||||
---
|
||||
## How to add a community integration (not recommended)
|
||||
|
||||
:::danger
|
||||
|
||||
We recommend following the [main integration guide](./index.mdx) to add new integrations instead.
|
||||
|
||||
If you follow this guide, there is a high likelihood we will close your PR with the above
|
||||
guide linked without much discussion.
|
||||
|
||||
:::
|
||||
|
||||
The `langchain-community` package is in `libs/community`.
|
||||
|
||||
It can be installed with `pip install langchain-community`, and exported members can be imported with code like
|
||||
|
||||
```python
|
||||
from langchain_community.chat_models import ChatParrotLink
|
||||
from langchain_community.llms import ParrotLinkLLM
|
||||
from langchain_community.vectorstores import ParrotLinkVectorStore
|
||||
```
|
||||
|
||||
The `community` package relies on manually-installed dependent packages, so you will see errors
|
||||
if you try to import a package that is not installed. In our fake example, if you tried to import `ParrotLinkLLM` without installing `parrot-link-sdk`, you will see an `ImportError` telling you to install it when trying to use it.
|
||||
|
||||
Let's say we wanted to implement a chat model for Parrot Link AI. We would create a new file in `libs/community/langchain_community/chat_models/parrot_link.py` with the following code:
|
||||
|
||||
```python
|
||||
from langchain_core.language_models.chat_models import BaseChatModel
|
||||
|
||||
class ChatParrotLink(BaseChatModel):
|
||||
"""ChatParrotLink chat model.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from langchain_community.chat_models import ChatParrotLink
|
||||
|
||||
model = ChatParrotLink()
|
||||
"""
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
And we would write tests in:
|
||||
|
||||
- Unit tests: `libs/community/tests/unit_tests/chat_models/test_parrot_link.py`
|
||||
- Integration tests: `libs/community/tests/integration_tests/chat_models/test_parrot_link.py`
|
||||
|
||||
And add documentation to:
|
||||
|
||||
- `docs/docs/integrations/chat/parrot_link.ipynb`
|
||||
@@ -1,137 +0,0 @@
|
||||
---
|
||||
pagination_next: null
|
||||
pagination_prev: null
|
||||
---
|
||||
|
||||
# How to publish an integration package from a template
|
||||
|
||||
:::danger
|
||||
This guide is a work-in-progress.
|
||||
:::
|
||||
|
||||
First, duplicate this template repository: https://github.com/langchain-ai/integration-repo-template
|
||||
|
||||
In this guide, we will create a `libs/langchain-parrot-link` folder, simulating the creation
|
||||
of a partner package for a fake company, "Parrot Link AI".
|
||||
|
||||
A package is
|
||||
installed by users with `pip install langchain-{partner}`, and the package members
|
||||
can be imported with code like:
|
||||
|
||||
```python
|
||||
from langchain_{partner} import X
|
||||
```
|
||||
|
||||
## Set up a new package
|
||||
|
||||
To set up a new partner package, use the latest version of the LangChain CLI. You can install or update it with:
|
||||
|
||||
```bash
|
||||
pip install -U langchain-cli
|
||||
```
|
||||
|
||||
Let's say you want to create a new partner package working for a company called Parrot Link AI.
|
||||
|
||||
Then, run the following command to create a new partner package:
|
||||
|
||||
```bash
|
||||
mkdir libs
|
||||
cd libs/
|
||||
langchain-cli integration new
|
||||
> Name: parrot-link
|
||||
> Name of integration in PascalCase [ParrotLink]: ParrotLink
|
||||
```
|
||||
|
||||
This will create a new package in `libs/parrot-link` with the following structure:
|
||||
|
||||
```
|
||||
libs/parrot-link/
|
||||
langchain_parrot_link/ # folder containing your package
|
||||
...
|
||||
tests/
|
||||
...
|
||||
docs/ # bootstrapped docs notebooks, must be moved to /docs in monorepo root
|
||||
...
|
||||
scripts/ # scripts for CI
|
||||
...
|
||||
LICENSE
|
||||
README.md # fill out with information about your package
|
||||
Makefile # default commands for CI
|
||||
pyproject.toml # package metadata, mostly managed by Poetry
|
||||
poetry.lock # package lockfile, managed by Poetry
|
||||
.gitignore
|
||||
```
|
||||
|
||||
## Implement your package
|
||||
|
||||
First, add any dependencies your package needs, such as your company's SDK:
|
||||
|
||||
```bash
|
||||
poetry add parrot-link-sdk
|
||||
```
|
||||
|
||||
If you need separate dependencies for type checking, you can add them to the `typing` group with:
|
||||
|
||||
```bash
|
||||
poetry add --group typing types-parrot-link-sdk
|
||||
```
|
||||
|
||||
Then, implement your package in `libs/partners/parrot-link/langchain_parrot_link`.
|
||||
|
||||
By default, this will include stubs for a Chat Model, an LLM, and/or a Vector Store. You should delete any of the files you won't use and remove them from `__init__.py`.
|
||||
|
||||
## Write Unit and Integration Tests
|
||||
|
||||
Some basic tests are presented in the `tests/` directory. You should add more tests to cover your package's functionality.
|
||||
|
||||
For information on running and implementing tests, see the [Testing guide](../testing.mdx).
|
||||
|
||||
## Write documentation
|
||||
|
||||
Documentation is generated from Jupyter notebooks in the `docs/` directory. You should place the notebooks with examples
|
||||
to the relevant `docs/docs/integrations` directory in the monorepo root.
|
||||
|
||||
## (If Necessary) Deprecate community integration
|
||||
|
||||
Note: this is only necessary if you're migrating an existing community integration into
|
||||
a partner package. If the component you're integrating is net-new to LangChain (i.e.
|
||||
not already in the `community` package), you can skip this step.
|
||||
|
||||
Let's pretend we migrated our `ChatParrotLink` chat model from the community package to
|
||||
the partner package. We would need to deprecate the old model in the community package.
|
||||
|
||||
We would do that by adding a `@deprecated` decorator to the old model as follows, in
|
||||
`libs/community/langchain_community/chat_models/parrot_link.py`.
|
||||
|
||||
Before our change, our chat model might look like this:
|
||||
|
||||
```python
|
||||
class ChatParrotLink(BaseChatModel):
|
||||
...
|
||||
```
|
||||
|
||||
After our change, it would look like this:
|
||||
|
||||
```python
|
||||
from langchain_core._api.deprecation import deprecated
|
||||
|
||||
@deprecated(
|
||||
since="0.0.<next community version>",
|
||||
removal="1.0.0",
|
||||
alternative_import="langchain_parrot_link.ChatParrotLink"
|
||||
)
|
||||
class ChatParrotLink(BaseChatModel):
|
||||
...
|
||||
```
|
||||
|
||||
You should do this for *each* component that you're migrating to the partner package.
|
||||
|
||||
## Additional steps
|
||||
|
||||
Contributor steps:
|
||||
|
||||
- [ ] Add secret names to manual integrations workflow in `.github/workflows/_integration_test.yml`
|
||||
- [ ] Add secrets to release workflow (for pre-release testing) in `.github/workflows/_release.yml`
|
||||
- [ ] set up pypi and test pypi projects
|
||||
- [ ] add credential secrets to Github Actions
|
||||
- [ ] add package to conda-forge
|
||||
@@ -1,79 +0,0 @@
|
||||
---
|
||||
pagination_next: contributing/how_to/integrations/package
|
||||
---
|
||||
|
||||
# Contribute Integrations
|
||||
|
||||
LangChain integrations are packages that provide access to language models, vector stores, and other components that can be used in LangChain.
|
||||
|
||||
This guide will walk you through how to contribute new integrations to LangChain, by
|
||||
publishing an integration package to PyPi, and adding documentation for it
|
||||
to the LangChain Monorepo.
|
||||
|
||||
These instructions will evolve over the next few months as we improve our integration
|
||||
processes.
|
||||
|
||||
## Components to Integrate
|
||||
|
||||
:::info
|
||||
|
||||
See the [Conceptual Guide](../../../concepts/index.mdx) for an overview of all components
|
||||
supported in LangChain
|
||||
|
||||
:::
|
||||
|
||||
While any component can be integrated into LangChain, at this time we are only accepting
|
||||
new integrations in the docs of the following kinds:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Integrate these ✅</th>
|
||||
<th>Not these ❌</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li>Chat Models</li>
|
||||
<li>Tools/Toolkits</li>
|
||||
<li>Retrievers</li>
|
||||
<li>Document Loaders</li>
|
||||
<li>Vector Stores</li>
|
||||
<li>Embedding Models</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>LLMs (Text-Completion Models)</li>
|
||||
<li>Key-Value Stores</li>
|
||||
<li>Document Transformers</li>
|
||||
<li>Model Caches</li>
|
||||
<li>Graphs</li>
|
||||
<li>Message Histories</li>
|
||||
<li>Callbacks</li>
|
||||
<li>Chat Loaders</li>
|
||||
<li>Adapters</li>
|
||||
<li>Other abstractions</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## How to contribute an integration
|
||||
|
||||
The only step necessary to "be" a LangChain integration is to add documentation
|
||||
that will render on this site (https://python.langchain.com/).
|
||||
|
||||
As a prerequisite to adding your integration to our documentation, you must:
|
||||
|
||||
1. Confirm that your integration is in the [list of components](#components-to-integrate) we are currently accepting.
|
||||
2. [Publish your package to PyPi](./package.mdx) and make the repo public.
|
||||
3. [Implement the standard tests](/docs/contributing/how_to/integrations/standard_tests) for your integration and successfully run them.
|
||||
3. Write documentation for your integration in the `docs/docs/integrations/<component_type>` directory of the LangChain monorepo.
|
||||
4. Add a provider page for your integration in the `docs/docs/integrations/providers` directory of the LangChain monorepo.
|
||||
|
||||
Once you have completed these steps, you can submit a PR to the LangChain monorepo to add your integration to the documentation.
|
||||
|
||||
## Further Reading
|
||||
|
||||
If you're starting from scratch, you can follow the [Integration Template Guide](./from_template.mdx) to create and publish a new integration package
|
||||
to the above spec.
|
||||
@@ -1,229 +0,0 @@
|
||||
---
|
||||
pagination_next: contributing/how_to/integrations/standard_tests
|
||||
pagination_prev: contributing/how_to/integrations/index
|
||||
---
|
||||
# How to bootstrap a new integration package
|
||||
|
||||
This guide walks through the process of publishing a new LangChain integration
|
||||
package to PyPi.
|
||||
|
||||
Integration packages are just Python packages that can be installed with `pip install <your-package>`,
|
||||
which contain classes that are compatible with LangChain's core interfaces.
|
||||
|
||||
In this guide, we will be using [Poetry](https://python-poetry.org/) for
|
||||
dependency management and packaging, and you're welcome to use any other tools you prefer.
|
||||
|
||||
## **Prerequisites**
|
||||
|
||||
- [GitHub](https://github.com) account
|
||||
- [PyPi](https://pypi.org/) account
|
||||
|
||||
## Boostrapping a new Python package with Poetry
|
||||
|
||||
First, install Poetry:
|
||||
|
||||
```bash
|
||||
pip install poetry
|
||||
```
|
||||
|
||||
Next, come up with a name for your package. For this guide, we'll use `langchain-parrot-link`.
|
||||
You can confirm that the name is available on PyPi by searching for it on the [PyPi website](https://pypi.org/).
|
||||
|
||||
Next, create your new Python package with Poetry:
|
||||
|
||||
```bash
|
||||
poetry new langchain-parrot-link
|
||||
```
|
||||
|
||||
Add main dependencies using Poetry, which will add them to your `pyproject.toml` file:
|
||||
|
||||
```bash
|
||||
poetry add langchain-core
|
||||
```
|
||||
|
||||
We will also add some `test` dependencies in a separate poetry dependency group. If
|
||||
you are not using Poetry, we recommend adding these in a way that won't package them
|
||||
with your published package, or just installing them separately when you run tests.
|
||||
|
||||
`langchain-tests` will provide the [standard tests](../standard_tests) we will use later.
|
||||
We recommended pinning these to the latest version: <img src="https://img.shields.io/pypi/v/langchain-tests" style={{position:"relative",top:4,left:3}} />
|
||||
|
||||
Note: Replace `{latest version}` with the latest version of `langchain-tests` below.
|
||||
|
||||
```bash
|
||||
poetry add --group test pytest pytest-socket langchain-tests=={latest version}
|
||||
```
|
||||
|
||||
You're now ready to start writing your integration package!
|
||||
|
||||
## Writing your integration
|
||||
|
||||
Let's say you're building a simple integration package that provides a `ChatParrotLink`
|
||||
chat model integration for LangChain. Here's a simple example of what your project
|
||||
structure might look like:
|
||||
|
||||
```plaintext
|
||||
langchain-parrot-link/
|
||||
├── langchain_parrot_link/
|
||||
│ ├── __init__.py
|
||||
│ └── chat_models.py
|
||||
├── tests/
|
||||
│ ├── __init__.py
|
||||
│ └── test_chat_models.py
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
```
|
||||
|
||||
All of these files should already exist from step 1, except for
|
||||
`chat_models.py` and `test_chat_models.py`! We will implement `test_chat_models.py`
|
||||
later, following the [standard tests](../standard_tests) guide.
|
||||
|
||||
To implement `chat_models.py`, let's copy the implementation from our
|
||||
[Custom Chat Model Guide](../../../../how_to/custom_chat_model).
|
||||
|
||||
<details>
|
||||
<summary>chat_models.py</summary>
|
||||
```python title="langchain_parrot_link/chat_models.py"
|
||||
from typing import Any, Dict, Iterator, List, Optional
|
||||
|
||||
from langchain_core.callbacks import (
|
||||
CallbackManagerForLLMRun,
|
||||
)
|
||||
from langchain_core.language_models import BaseChatModel
|
||||
from langchain_core.messages import AIMessageChunk, BaseMessage, AIMessage
|
||||
from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult
|
||||
|
||||
|
||||
class CustomChatModelAdvanced(BaseChatModel):
|
||||
"""A custom chat model that echoes the first `n` characters of the input.
|
||||
|
||||
When contributing an implementation to LangChain, carefully document
|
||||
the model including the initialization parameters, include
|
||||
an example of how to initialize the model and include any relevant
|
||||
links to the underlying models documentation or API.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
model = CustomChatModel(n=2)
|
||||
result = model.invoke([HumanMessage(content="hello")])
|
||||
result = model.batch([[HumanMessage(content="hello")],
|
||||
[HumanMessage(content="world")]])
|
||||
"""
|
||||
|
||||
model_name: str
|
||||
"""The name of the model"""
|
||||
n: int
|
||||
"""The number of characters from the last message of the prompt to be echoed."""
|
||||
|
||||
def _generate(
|
||||
self,
|
||||
messages: List[BaseMessage],
|
||||
stop: Optional[List[str]] = None,
|
||||
run_manager: Optional[CallbackManagerForLLMRun] = None,
|
||||
**kwargs: Any,
|
||||
) -> ChatResult:
|
||||
"""Override the _generate method to implement the chat model logic.
|
||||
|
||||
This can be a call to an API, a call to a local model, or any other
|
||||
implementation that generates a response to the input prompt.
|
||||
|
||||
Args:
|
||||
messages: the prompt composed of a list of messages.
|
||||
stop: a list of strings on which the model should stop generating.
|
||||
If generation stops due to a stop token, the stop token itself
|
||||
SHOULD BE INCLUDED as part of the output. This is not enforced
|
||||
across models right now, but it's a good practice to follow since
|
||||
it makes it much easier to parse the output of the model
|
||||
downstream and understand why generation stopped.
|
||||
run_manager: A run manager with callbacks for the LLM.
|
||||
"""
|
||||
# Replace this with actual logic to generate a response from a list
|
||||
# of messages.
|
||||
last_message = messages[-1]
|
||||
tokens = last_message.content[: self.n]
|
||||
message = AIMessage(
|
||||
content=tokens,
|
||||
additional_kwargs={}, # Used to add additional payload (e.g., function calling request)
|
||||
response_metadata={ # Use for response metadata
|
||||
"time_in_seconds": 3,
|
||||
},
|
||||
)
|
||||
##
|
||||
|
||||
generation = ChatGeneration(message=message)
|
||||
return ChatResult(generations=[generation])
|
||||
|
||||
def _stream(
|
||||
self,
|
||||
messages: List[BaseMessage],
|
||||
stop: Optional[List[str]] = None,
|
||||
run_manager: Optional[CallbackManagerForLLMRun] = None,
|
||||
**kwargs: Any,
|
||||
) -> Iterator[ChatGenerationChunk]:
|
||||
"""Stream the output of the model.
|
||||
|
||||
This method should be implemented if the model can generate output
|
||||
in a streaming fashion. If the model does not support streaming,
|
||||
do not implement it. In that case streaming requests will be automatically
|
||||
handled by the _generate method.
|
||||
|
||||
Args:
|
||||
messages: the prompt composed of a list of messages.
|
||||
stop: a list of strings on which the model should stop generating.
|
||||
If generation stops due to a stop token, the stop token itself
|
||||
SHOULD BE INCLUDED as part of the output. This is not enforced
|
||||
across models right now, but it's a good practice to follow since
|
||||
it makes it much easier to parse the output of the model
|
||||
downstream and understand why generation stopped.
|
||||
run_manager: A run manager with callbacks for the LLM.
|
||||
"""
|
||||
last_message = messages[-1]
|
||||
tokens = last_message.content[: self.n]
|
||||
|
||||
for token in tokens:
|
||||
chunk = ChatGenerationChunk(message=AIMessageChunk(content=token))
|
||||
|
||||
if run_manager:
|
||||
# This is optional in newer versions of LangChain
|
||||
# The on_llm_new_token will be called automatically
|
||||
run_manager.on_llm_new_token(token, chunk=chunk)
|
||||
|
||||
yield chunk
|
||||
|
||||
# Let's add some other information (e.g., response metadata)
|
||||
chunk = ChatGenerationChunk(
|
||||
message=AIMessageChunk(content="", response_metadata={"time_in_sec": 3})
|
||||
)
|
||||
if run_manager:
|
||||
# This is optional in newer versions of LangChain
|
||||
# The on_llm_new_token will be called automatically
|
||||
run_manager.on_llm_new_token(token, chunk=chunk)
|
||||
yield chunk
|
||||
|
||||
@property
|
||||
def _llm_type(self) -> str:
|
||||
"""Get the type of language model used by this chat model."""
|
||||
return "echoing-chat-model-advanced"
|
||||
|
||||
@property
|
||||
def _identifying_params(self) -> Dict[str, Any]:
|
||||
"""Return a dictionary of identifying parameters.
|
||||
|
||||
This information is used by the LangChain callback system, which
|
||||
is used for tracing purposes make it possible to monitor LLMs.
|
||||
"""
|
||||
return {
|
||||
# The model name allows users to specify custom token counting
|
||||
# rules in LLM monitoring applications (e.g., in LangSmith users
|
||||
# can provide per token pricing for their model and monitor
|
||||
# costs for the given LLM.)
|
||||
"model_name": self.model_name,
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you've implemented your package, you can move on to [testing your integration](../standard_tests) for your integration and successfully run them.
|
||||
@@ -1,145 +0,0 @@
|
||||
---
|
||||
pagination_prev: contributing/how_to/integrations/standard_tests
|
||||
pagination_next: null
|
||||
---
|
||||
|
||||
# Publishing your package
|
||||
|
||||
Now that your package is implemented and tested, you can:
|
||||
|
||||
1. Publish your package to PyPi
|
||||
2. Add documentation for your package to the LangChain Monorepo
|
||||
|
||||
## Publishing your package to PyPi
|
||||
|
||||
This guide assumes you have already implemented your package and written tests for it. If you haven't done that yet, please refer to the [implementation guide](../package) and the [testing guide](../standard_tests).
|
||||
|
||||
Note that Poetry is not required to publish a package to PyPi, and we're using it in this guide end-to-end for convenience.
|
||||
You are welcome to publish your package using any other method you prefer.
|
||||
|
||||
First, make sure you have a PyPi account and have logged in with Poetry:
|
||||
|
||||
<details>
|
||||
<summary>How to create a PyPi Token</summary>
|
||||
|
||||
1. Go to the [PyPi website](https://pypi.org/) and create an account.
|
||||
2. Go to your account settings and enable 2FA. To generate an API token, you **must** have 2FA enabled currently.
|
||||
3. Go to your account settings and [generate a new API token](https://pypi.org/manage/account/token/).
|
||||
|
||||
</details>
|
||||
|
||||
```bash
|
||||
poetry config pypi-token.pypi <your-pypi-token>
|
||||
```
|
||||
|
||||
Next, build your package:
|
||||
|
||||
```bash
|
||||
poetry build
|
||||
```
|
||||
|
||||
Finally, publish your package to PyPi:
|
||||
|
||||
```bash
|
||||
poetry publish
|
||||
```
|
||||
|
||||
You're all set! Your package is now available on PyPi and can be installed with `pip install langchain-parrot-link`.
|
||||
|
||||
## Adding documentation to the LangChain Monorepo
|
||||
|
||||
To add documentation for your package to the LangChain Monorepo, you will need to:
|
||||
|
||||
1. Fork and clone the LangChain Monorepo
|
||||
2. Make a "Provider Page" at `docs/docs/integrations/providers/<your-package-name>.ipynb`
|
||||
3. Make "Component Pages" at `docs/docs/integrations/<component-type>/<your-package-name>.ipynb`
|
||||
4. Register your package in `libs/packages.yml`
|
||||
5. Submit a PR with **only these changes** to the LangChain Monorepo
|
||||
|
||||
### Fork and clone the LangChain Monorepo
|
||||
|
||||
First, fork the [LangChain Monorepo](https://github.com/langchain-ai/langchain) to your GitHub account.
|
||||
|
||||
Next, clone the repository to your local machine:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/<your-username>/langchain.git
|
||||
```
|
||||
|
||||
You're now ready to make your PR!
|
||||
|
||||
### Bootstrap your documentation pages with the langchain-cli (recommended)
|
||||
|
||||
To make it easier to create the necessary documentation pages, you can use the `langchain-cli` to bootstrap them for you.
|
||||
|
||||
First, install the latest version of the `langchain-cli` package:
|
||||
|
||||
```bash
|
||||
pip install --upgrade langchain-cli
|
||||
```
|
||||
|
||||
To see the available commands to bootstrap your documentation pages, run:
|
||||
|
||||
```bash
|
||||
langchain-cli integration create-doc --help
|
||||
```
|
||||
|
||||
Let's bootstrap a provider page from the root of the monorepo:
|
||||
|
||||
```bash
|
||||
langchain-cli integration create-doc \
|
||||
--component-type Provider \
|
||||
--destination-dir docs/docs/integrations/providers \
|
||||
--name parrot-link \
|
||||
--name-class ParrotLink \
|
||||
```
|
||||
|
||||
And a chat model component page:
|
||||
|
||||
```bash
|
||||
langchain-cli integration create-doc \
|
||||
--component-type ChatModel \
|
||||
--destination-dir docs/docs/integrations/chat \
|
||||
--name parrot-link \
|
||||
--name-class ParrotLink \
|
||||
```
|
||||
|
||||
And a vector store component page:
|
||||
|
||||
```bash
|
||||
langchain-cli integration create-doc \
|
||||
--component-type VectorStore \
|
||||
--destination-dir docs/docs/integrations/vectorstores \
|
||||
--name parrot-link \
|
||||
--name-class ParrotLink \
|
||||
```
|
||||
|
||||
These commands will create the following 3 files, which you should fill out with information about your package:
|
||||
|
||||
- `docs/docs/integrations/providers/parrot-link.ipynb`
|
||||
- `docs/docs/integrations/chat/parrot-link.ipynb`
|
||||
- `docs/docs/integrations/vectorstores/parrot-link.ipynb`
|
||||
|
||||
### Manually create your documentation pages (if you prefer)
|
||||
|
||||
If you prefer to create the documentation pages manually, you can create the same files listed
|
||||
above and fill them out with information about your package.
|
||||
|
||||
You can view the templates that the CLI uses to create these files [here](https://github.com/langchain-ai/langchain/tree/master/libs/cli/langchain_cli/integration_template/docs) if helpful!
|
||||
|
||||
### Register your package in `libs/packages.yml`
|
||||
|
||||
Finally, add your package to the `libs/packages.yml` file in the LangChain Monorepo.
|
||||
|
||||
```yaml
|
||||
packages:
|
||||
- name: langchain-parrot-link
|
||||
repo: <your github handle>/<your repo>
|
||||
path: .
|
||||
```
|
||||
|
||||
For `path`, you can use `.` if your package is in the root of your repository, or specify a subdirectory (e.g. `libs/parrot-link`) if it is in a subdirectory.
|
||||
|
||||
### Submit a PR with your changes
|
||||
|
||||
Once you have completed these steps, you can submit a PR to the LangChain Monorepo with **only these changes**.
|
||||
@@ -1,502 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"pagination_next: contributing/how_to/integrations/publish\n",
|
||||
"pagination_prev: contributing/how_to/integrations/package\n",
|
||||
"---\n",
|
||||
"# How to add standard tests to an integration\n",
|
||||
"\n",
|
||||
"When creating either a custom class for yourself or a new tool to publish in a LangChain integration, it is important to add standard tests to ensure it works as expected. This guide will show you how to add standard tests to a tool, and you can **[Skip to the test templates](#standard-test-templates-per-component)** for implementing tests for each integration.\n",
|
||||
"\n",
|
||||
"## Setup\n",
|
||||
"\n",
|
||||
"First, let's install 2 dependencies:\n",
|
||||
"\n",
|
||||
"- `langchain-core` will define the interfaces we want to import to define our custom tool.\n",
|
||||
"- `langchain-tests` will provide the standard tests we want to use. Recommended to pin to the latest version: <img src=\"https://img.shields.io/pypi/v/langchain-tests\" style={{position:\"relative\",top:4,left:3}} />\n",
|
||||
"\n",
|
||||
":::note\n",
|
||||
"\n",
|
||||
"Because added tests in new versions of `langchain-tests` can break your CI/CD pipelines, we recommend pinning the \n",
|
||||
"version of `langchain-tests` to avoid unexpected changes.\n",
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"import Tabs from '@theme/Tabs';\n",
|
||||
"import TabItem from '@theme/TabItem';\n",
|
||||
"\n",
|
||||
"<Tabs>\n",
|
||||
" <TabItem value=\"poetry\" label=\"Poetry\" default>\n",
|
||||
"If you followed the [previous guide](../package), you should already have these dependencies installed!\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"poetry add langchain-core\n",
|
||||
"poetry add --group test pytest pytest-socket langchain-tests==<latest_version>\n",
|
||||
"```\n",
|
||||
" </TabItem>\n",
|
||||
" <TabItem value=\"pip\" label=\"Pip\">\n",
|
||||
"```bash\n",
|
||||
"pip install -U langchain-core pytest pytest-socket langchain-tests\n",
|
||||
"\n",
|
||||
"# install current package in editable mode\n",
|
||||
"pip install --editable .\n",
|
||||
"```\n",
|
||||
" </TabItem>\n",
|
||||
"</Tabs>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's say we're publishing a package, `langchain_parrot_link`, that exposes a\n",
|
||||
"tool called `ParrotMultiplyTool`:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"langchain_parrot_link/tools.py\"\n",
|
||||
"from langchain_core.tools import BaseTool\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class ParrotMultiplyTool(BaseTool):\n",
|
||||
" name: str = \"ParrotMultiplyTool\"\n",
|
||||
" description: str = (\n",
|
||||
" \"Multiply two numbers like a parrot. Parrots always add \"\n",
|
||||
" \"eighty for their matey.\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" def _run(self, a: int, b: int) -> int:\n",
|
||||
" return a * b + 80"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"And we'll assume you've structured your package the same way as the main LangChain\n",
|
||||
"packages:\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"/\n",
|
||||
"├── langchain_parrot_link/\n",
|
||||
"│ └── tools.py\n",
|
||||
"└── tests/\n",
|
||||
" ├── unit_tests/\n",
|
||||
" │ └── test_tools.py\n",
|
||||
" └── integration_tests/\n",
|
||||
" └── test_tools.py\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"## Add and configure standard tests\n",
|
||||
"\n",
|
||||
"There are 2 namespaces in the `langchain-tests` package: \n",
|
||||
"\n",
|
||||
"- [unit tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.unit_tests`): designed to be used to test the tool in isolation and without access to external services\n",
|
||||
"- [integration tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.integration_tests`): designed to be used to test the tool with access to external services (in particular, the external service that the tool is designed to interact with).\n",
|
||||
"\n",
|
||||
"Both types of tests are implemented as [`pytest` class-based test suites](https://docs.pytest.org/en/7.1.x/getting-started.html#group-multiple-tests-in-a-class).\n",
|
||||
"\n",
|
||||
"By subclassing the base classes for each type of standard test (see below), you get all of the standard tests for that type, and you\n",
|
||||
"can override the properties that the test suite uses to configure the tests.\n",
|
||||
"\n",
|
||||
"### Standard tools tests\n",
|
||||
"\n",
|
||||
"Here's how you would configure the standard unit tests for the custom tool, e.g. in `tests/test_tools.py`:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"title": "tests/test_custom_tool.py"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/unit_tests/test_tools.py\"\n",
|
||||
"from typing import Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.tools import ParrotMultiplyTool\n",
|
||||
"from langchain_tests.unit_tests import ToolsUnitTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestParrotMultiplyToolUnit(ToolsUnitTests):\n",
|
||||
" @property\n",
|
||||
" def tool_constructor(self) -> Type[ParrotMultiplyTool]:\n",
|
||||
" return ParrotMultiplyTool\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_constructor_params(self) -> dict:\n",
|
||||
" # if your tool constructor instead required initialization arguments like\n",
|
||||
" # `def __init__(self, some_arg: int):`, you would return those here\n",
|
||||
" # as a dictionary, e.g.: `return {'some_arg': 42}`\n",
|
||||
" return {}\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_invoke_params_example(self) -> dict:\n",
|
||||
" \"\"\"\n",
|
||||
" Returns a dictionary representing the \"args\" of an example tool call.\n",
|
||||
"\n",
|
||||
" This should NOT be a ToolCall dict - i.e. it should not\n",
|
||||
" have {\"name\", \"id\", \"args\"} keys.\n",
|
||||
" \"\"\"\n",
|
||||
" return {\"a\": 2, \"b\": 3}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/integration_tests/test_tools.py\"\n",
|
||||
"from typing import Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.tools import ParrotMultiplyTool\n",
|
||||
"from langchain_tests.integration_tests import ToolsIntegrationTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestParrotMultiplyToolIntegration(ToolsIntegrationTests):\n",
|
||||
" @property\n",
|
||||
" def tool_constructor(self) -> Type[ParrotMultiplyTool]:\n",
|
||||
" return ParrotMultiplyTool\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_constructor_params(self) -> dict:\n",
|
||||
" # if your tool constructor instead required initialization arguments like\n",
|
||||
" # `def __init__(self, some_arg: int):`, you would return those here\n",
|
||||
" # as a dictionary, e.g.: `return {'some_arg': 42}`\n",
|
||||
" return {}\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_invoke_params_example(self) -> dict:\n",
|
||||
" \"\"\"\n",
|
||||
" Returns a dictionary representing the \"args\" of an example tool call.\n",
|
||||
"\n",
|
||||
" This should NOT be a ToolCall dict - i.e. it should not\n",
|
||||
" have {\"name\", \"id\", \"args\"} keys.\n",
|
||||
" \"\"\"\n",
|
||||
" return {\"a\": 2, \"b\": 3}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"and you would run these with the following commands from your project root\n",
|
||||
"\n",
|
||||
"<Tabs>\n",
|
||||
" <TabItem value=\"poetry\" label=\"Poetry\" default>\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"# run unit tests without network access\n",
|
||||
"poetry run pytest --disable-socket --allow-unix-socket tests/unit_tests\n",
|
||||
"\n",
|
||||
"# run integration tests\n",
|
||||
"poetry run pytest tests/integration_tests\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
" </TabItem>\n",
|
||||
" <TabItem value=\"pip\" label=\"Pip\">\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"# run unit tests without network access\n",
|
||||
"pytest --disable-socket --allow-unix-socket tests/unit_tests\n",
|
||||
"\n",
|
||||
"# run integration tests\n",
|
||||
"pytest tests/integration_tests\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
" </TabItem>\n",
|
||||
"</Tabs>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Standard test templates per component:\n",
|
||||
"\n",
|
||||
"Above, we implement the **unit** and **integration** standard tests for a tool. Below are the templates for implementing the standard tests for each component:\n",
|
||||
"\n",
|
||||
"<details>\n",
|
||||
" <summary>Chat Models</summary>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/unit_tests/test_chat_models.py\"\n",
|
||||
"from typing import Tuple, Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.chat_models import ChatParrotLink\n",
|
||||
"from langchain_tests.unit_tests import ChatModelUnitTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestChatParrotLinkUnit(ChatModelUnitTests):\n",
|
||||
" @property\n",
|
||||
" def chat_model_class(self) -> Type[ChatParrotLink]:\n",
|
||||
" return ChatParrotLink\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def chat_model_params(self) -> dict:\n",
|
||||
" return {\"model\": \"bird-brain-001\", \"temperature\": 0}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/integration_tests/test_chat_models.py\"\n",
|
||||
"from typing import Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.chat_models import ChatParrotLink\n",
|
||||
"from langchain_tests.integration_tests import ChatModelIntegrationTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestChatParrotLinkIntegration(ChatModelIntegrationTests):\n",
|
||||
" @property\n",
|
||||
" def chat_model_class(self) -> Type[ChatParrotLink]:\n",
|
||||
" return ChatParrotLink\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def chat_model_params(self) -> dict:\n",
|
||||
" return {\"model\": \"bird-brain-001\", \"temperature\": 0}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"</details>\n",
|
||||
"<details>\n",
|
||||
" <summary>Embedding Models</summary>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/unit_tests/test_embeddings.py\"\n",
|
||||
"from typing import Tuple, Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.embeddings import ParrotLinkEmbeddings\n",
|
||||
"from langchain_tests.unit_tests import EmbeddingsUnitTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestParrotLinkEmbeddingsUnit(EmbeddingsUnitTests):\n",
|
||||
" @property\n",
|
||||
" def embeddings_class(self) -> Type[ParrotLinkEmbeddings]:\n",
|
||||
" return ParrotLinkEmbeddings\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def embedding_model_params(self) -> dict:\n",
|
||||
" return {\"model\": \"nest-embed-001\", \"temperature\": 0}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/integration_tests/test_embeddings.py\"\n",
|
||||
"from typing import Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.embeddings import ParrotLinkEmbeddings\n",
|
||||
"from langchain_tests.integration_tests import EmbeddingsIntegrationTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestParrotLinkEmbeddingsIntegration(EmbeddingsIntegrationTests):\n",
|
||||
" @property\n",
|
||||
" def embeddings_class(self) -> Type[ParrotLinkEmbeddings]:\n",
|
||||
" return ParrotLinkEmbeddings\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def embedding_model_params(self) -> dict:\n",
|
||||
" return {\"model\": \"nest-embed-001\", \"temperature\": 0}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"</details>\n",
|
||||
"<details>\n",
|
||||
" <summary>Tools/Toolkits</summary>\n",
|
||||
" <p>Note: The standard tests for tools/toolkits are implemented in the example in the main body of this guide too.</p>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/unit_tests/test_tools.py\"\n",
|
||||
"from typing import Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.tools import ParrotMultiplyTool\n",
|
||||
"from langchain_tests.unit_tests import ToolsUnitTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestParrotMultiplyToolUnit(ToolsUnitTests):\n",
|
||||
" @property\n",
|
||||
" def tool_constructor(self) -> Type[ParrotMultiplyTool]:\n",
|
||||
" return ParrotMultiplyTool\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_constructor_params(self) -> dict:\n",
|
||||
" # if your tool constructor instead required initialization arguments like\n",
|
||||
" # `def __init__(self, some_arg: int):`, you would return those here\n",
|
||||
" # as a dictionary, e.g.: `return {'some_arg': 42}`\n",
|
||||
" return {}\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_invoke_params_example(self) -> dict:\n",
|
||||
" \"\"\"\n",
|
||||
" Returns a dictionary representing the \"args\" of an example tool call.\n",
|
||||
"\n",
|
||||
" This should NOT be a ToolCall dict - i.e. it should not\n",
|
||||
" have {\"name\", \"id\", \"args\"} keys.\n",
|
||||
" \"\"\"\n",
|
||||
" return {\"a\": 2, \"b\": 3}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/integration_tests/test_tools.py\"\n",
|
||||
"from typing import Type\n",
|
||||
"\n",
|
||||
"from langchain_parrot_link.tools import ParrotMultiplyTool\n",
|
||||
"from langchain_tests.integration_tests import ToolsIntegrationTests\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestParrotMultiplyToolIntegration(ToolsIntegrationTests):\n",
|
||||
" @property\n",
|
||||
" def tool_constructor(self) -> Type[ParrotMultiplyTool]:\n",
|
||||
" return ParrotMultiplyTool\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_constructor_params(self) -> dict:\n",
|
||||
" # if your tool constructor instead required initialization arguments like\n",
|
||||
" # `def __init__(self, some_arg: int):`, you would return those here\n",
|
||||
" # as a dictionary, e.g.: `return {'some_arg': 42}`\n",
|
||||
" return {}\n",
|
||||
"\n",
|
||||
" @property\n",
|
||||
" def tool_invoke_params_example(self) -> dict:\n",
|
||||
" \"\"\"\n",
|
||||
" Returns a dictionary representing the \"args\" of an example tool call.\n",
|
||||
"\n",
|
||||
" This should NOT be a ToolCall dict - i.e. it should not\n",
|
||||
" have {\"name\", \"id\", \"args\"} keys.\n",
|
||||
" \"\"\"\n",
|
||||
" return {\"a\": 2, \"b\": 3}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"</details>\n",
|
||||
"<details>\n",
|
||||
" <summary>Vector Stores</summary>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# title=\"tests/integration_tests/test_vectorstores_sync.py\"\n",
|
||||
"\n",
|
||||
"from typing import AsyncGenerator, Generator\n",
|
||||
"\n",
|
||||
"import pytest\n",
|
||||
"from langchain_core.vectorstores import VectorStore\n",
|
||||
"from langchain_parrot_link.vectorstores import ParrotVectorStore\n",
|
||||
"from langchain_standard_tests.integration_tests.vectorstores import (\n",
|
||||
" AsyncReadWriteTestSuite,\n",
|
||||
" ReadWriteTestSuite,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestSync(ReadWriteTestSuite):\n",
|
||||
" @pytest.fixture()\n",
|
||||
" def vectorstore(self) -> Generator[VectorStore, None, None]: # type: ignore\n",
|
||||
" \"\"\"Get an empty vectorstore for unit tests.\"\"\"\n",
|
||||
" store = ParrotVectorStore()\n",
|
||||
" # note: store should be EMPTY at this point\n",
|
||||
" # if you need to delete data, you may do so here\n",
|
||||
" try:\n",
|
||||
" yield store\n",
|
||||
" finally:\n",
|
||||
" # cleanup operations, or deleting data\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class TestAsync(AsyncReadWriteTestSuite):\n",
|
||||
" @pytest.fixture()\n",
|
||||
" async def vectorstore(self) -> AsyncGenerator[VectorStore, None]: # type: ignore\n",
|
||||
" \"\"\"Get an empty vectorstore for unit tests.\"\"\"\n",
|
||||
" store = ParrotVectorStore()\n",
|
||||
" # note: store should be EMPTY at this point\n",
|
||||
" # if you need to delete data, you may do so here\n",
|
||||
" try:\n",
|
||||
" yield store\n",
|
||||
" finally:\n",
|
||||
" # cleanup operations, or deleting data\n",
|
||||
" pass"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"</details>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".venv",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -16,8 +16,7 @@ More coming soon! We are working on tutorials to help you make your first contri
|
||||
|
||||
- [**Documentation**](how_to/documentation/index.mdx): Help improve our docs, including this one!
|
||||
- [**Code**](how_to/code/index.mdx): Help us write code, fix bugs, or improve our infrastructure.
|
||||
- [**Integrations**](how_to/integrations/index.mdx): Help us integrate with your favorite vendors and tools.
|
||||
- [**Standard Tests**](how_to/integrations/standard_tests): Ensure your integration passes an expected set of tests.
|
||||
- [**Integrations**](how_to/integrations.mdx): Help us integrate with your favorite vendors and tools.
|
||||
|
||||
## Reference
|
||||
|
||||
|
||||
@@ -61,5 +61,5 @@ The `/libs` directory contains the code for the LangChain packages.
|
||||
To learn more about how to contribute code see the following guidelines:
|
||||
|
||||
- [Code](../how_to/code/index.mdx): Learn how to develop in the LangChain codebase.
|
||||
- [Integrations](../how_to/integrations/index.mdx): Learn how to contribute to third-party integrations to `langchain-community` or to start a new partner package.
|
||||
- [Integrations](../how_to/integrations.mdx): Learn how to contribute to third-party integrations to `langchain-community` or to start a new partner package.
|
||||
- [Testing](../how_to/testing.mdx): Guidelines to learn how to write tests for the packages.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"# How to split by HTML header \n",
|
||||
"## Description and motivation\n",
|
||||
"\n",
|
||||
"[HTMLHeaderTextSplitter](https://python.langchain.com/api_reference/text_splitters/html/langchain_text_splitters.html.HTMLHeaderTextSplitter.html) is a \"structure-aware\" [text splitter](/docs/concepts/text_splitters/) that splits text at the HTML element level and adds metadata for each header \"relevant\" to any given chunk. It can return chunks element by element or combine elements with the same metadata, with the objectives of (a) keeping related text grouped (more or less) semantically and (b) preserving context-rich information encoded in document structures. It can be used with other text splitters as part of a chunking pipeline.\n",
|
||||
"[HTMLHeaderTextSplitter](https://python.langchain.com/api_reference/text_splitters/html/langchain_text_splitters.html.HTMLHeaderTextSplitter.html) is a \"structure-aware\" chunker that splits text at the HTML element level and adds metadata for each header \"relevant\" to any given chunk. It can return chunks element by element or combine elements with the same metadata, with the objectives of (a) keeping related text grouped (more or less) semantically and (b) preserving context-rich information encoded in document structures. It can be used with other text splitters as part of a chunking pipeline.\n",
|
||||
"\n",
|
||||
"It is analogous to the [MarkdownHeaderTextSplitter](/docs/how_to/markdown_header_metadata_splitter) for markdown files.\n",
|
||||
"\n",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"source": [
|
||||
"# How to split by HTML sections\n",
|
||||
"## Description and motivation\n",
|
||||
"Similar in concept to the [HTMLHeaderTextSplitter](/docs/how_to/HTML_header_metadata_splitter), the `HTMLSectionSplitter` is a \"structure-aware\" [text splitter](/docs/concepts/text_splitters/) that splits text at the element level and adds metadata for each header \"relevant\" to any given chunk.\n",
|
||||
"Similar in concept to the [HTMLHeaderTextSplitter](/docs/how_to/HTML_header_metadata_splitter), the `HTMLSectionSplitter` is a \"structure-aware\" chunker that splits text at the element level and adds metadata for each header \"relevant\" to any given chunk.\n",
|
||||
"\n",
|
||||
"It can return chunks element by element or combine elements with the same metadata, with the objectives of (a) keeping related text grouped (more or less) semantically and (b) preserving context-rich information encoded in document structures.\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to use the MultiQueryRetriever\n",
|
||||
"\n",
|
||||
"Distance-based [vector database](/docs/concepts/vectorstores/) retrieval [embeds](/docs/concepts/embedding_models/) (represents) queries in high-dimensional space and finds similar embedded documents based on a distance metric. But, retrieval may produce different results with subtle changes in query wording, or if the embeddings do not capture the semantics of the data well. Prompt engineering / tuning is sometimes done to manually address these problems, but can be tedious.\n",
|
||||
"Distance-based vector database retrieval embeds (represents) queries in high-dimensional space and finds similar embedded documents based on a distance metric. But, retrieval may produce different results with subtle changes in query wording, or if the embeddings do not capture the semantics of the data well. Prompt engineering / tuning is sometimes done to manually address these problems, but can be tedious.\n",
|
||||
"\n",
|
||||
"The [MultiQueryRetriever](https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.multi_query.MultiQueryRetriever.html) automates the process of prompt tuning by using an LLM to generate multiple queries from different perspectives for a given user input query. For each query, it retrieves a set of relevant documents and takes the unique union across all queries to get a larger set of potentially relevant documents. By generating multiple perspectives on the same question, the `MultiQueryRetriever` can mitigate some of the limitations of the distance-based retrieval and get a richer set of results.\n",
|
||||
"\n",
|
||||
@@ -151,7 +151,7 @@
|
||||
"id": "7e170263-facd-4065-bb68-d11fb9123a45",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Note that the underlying queries generated by the [retriever](/docs/concepts/retrievers/) are logged at the `INFO` level."
|
||||
"Note that the underlying queries generated by the retriever are logged at the `INFO` level."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
"source": [
|
||||
"# How to add scores to retriever results\n",
|
||||
"\n",
|
||||
"[Retrievers](/docs/concepts/retrievers/) will return sequences of [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) objects, which by default include no information about the process that retrieved them (e.g., a similarity score against a query). Here we demonstrate how to add retrieval scores to the `.metadata` of documents:\n",
|
||||
"Retrievers will return sequences of [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) objects, which by default include no information about the process that retrieved them (e.g., a similarity score against a query). Here we demonstrate how to add retrieval scores to the `.metadata` of documents:\n",
|
||||
"1. From [vectorstore retrievers](/docs/how_to/vectorstore_retriever);\n",
|
||||
"2. From higher-order LangChain retrievers, such as [SelfQueryRetriever](/docs/how_to/self_query) or [MultiVectorRetriever](/docs/how_to/multi_vector).\n",
|
||||
"\n",
|
||||
"For (1), we will implement a short wrapper function around the corresponding [vector store](/docs/concepts/vectorstores/). For (2), we will update a method of the corresponding class.\n",
|
||||
"For (1), we will implement a short wrapper function around the corresponding vector store. For (2), we will update a method of the corresponding class.\n",
|
||||
"\n",
|
||||
"## Create vector store\n",
|
||||
"\n",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
":::\n",
|
||||
"\n",
|
||||
"By themselves, language models can't take actions - they just output text.\n",
|
||||
"A big use case for LangChain is creating **[agents](/docs/concepts/agents/)**.\n",
|
||||
"A big use case for LangChain is creating **agents**.\n",
|
||||
"Agents are systems that use an LLM as a reasoning engine to determine which actions to take and what the inputs to those actions should be.\n",
|
||||
"The results of those actions can then be fed back into the agent and it determines whether more actions are needed, or whether it is okay to finish.\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# Caching\n",
|
||||
"\n",
|
||||
"[Embeddings](/docs/concepts/embedding_models/) can be stored or temporarily cached to avoid needing to recompute them.\n",
|
||||
"Embeddings can be stored or temporarily cached to avoid needing to recompute them.\n",
|
||||
"\n",
|
||||
"Caching embeddings can be done using a `CacheBackedEmbeddings`. The cache backed embedder is a wrapper around an embedder that caches\n",
|
||||
"embeddings in a key-value store. The text is hashed and the hash is used as the key in the cache.\n",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"source": [
|
||||
"# How to split by character\n",
|
||||
"\n",
|
||||
"This is the simplest method. This [splits](/docs/concepts/text_splitters/) based on a given character sequence, which defaults to `\"\\n\\n\"`. Chunk length is measured by number of characters.\n",
|
||||
"This is the simplest method. This splits based on a given character sequence, which defaults to `\"\\n\\n\"`. Chunk length is measured by number of characters.\n",
|
||||
"\n",
|
||||
"1. How the text is split: by single character separator.\n",
|
||||
"2. How the chunk size is measured: by number of characters.\n",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"LangChain provides an optional caching layer for [chat models](/docs/concepts/chat_models). This is useful for two main reasons:\n",
|
||||
"LangChain provides an optional caching layer for chat models. This is useful for two main reasons:\n",
|
||||
"\n",
|
||||
"- It can save you money by reducing the number of API calls you make to the LLM provider, if you're often requesting the same completion multiple times. This is especially useful during app development.\n",
|
||||
"- It can speed up your application by reducing the number of API calls you make to the LLM provider.\n",
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
"source": [
|
||||
"# How to init any model in one line\n",
|
||||
"\n",
|
||||
"Many LLM applications let end users specify what model provider and model they want the application to be powered by. This requires writing some logic to initialize different [chat models](/docs/concepts/chat_models/) based on some user configuration. The `init_chat_model()` helper method makes it easy to initialize a number of different model integrations without having to worry about import paths and class names.\n",
|
||||
"Many LLM applications let end users specify what model provider and model they want the application to be powered by. This requires writing some logic to initialize different ChatModels based on some user configuration. The `init_chat_model()` helper method makes it easy to initialize a number of different model integrations without having to worry about import paths and class names.\n",
|
||||
"\n",
|
||||
":::tip Supported models\n",
|
||||
"\n",
|
||||
"See the [init_chat_model()](https://python.langchain.com/api_reference/langchain/chat_models/langchain.chat_models.base.init_chat_model.html) API reference for a full list of supported integrations.\n",
|
||||
"\n",
|
||||
"Make sure you have the [integration packages](/docs/integrations/chat/) installed for any model providers you want to support. E.g. you should have `langchain-openai` installed to init an OpenAI model.\n",
|
||||
"Make sure you have the integration packages installed for any model providers you want to support. E.g. you should have `langchain-openai` installed to init an OpenAI model.\n",
|
||||
"\n",
|
||||
":::"
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"Tracking [token](/docs/concepts/tokens/) usage to calculate cost is an important part of putting your app in production. This guide goes over how to obtain this information from your LangChain model calls.\n",
|
||||
"Tracking token usage to calculate cost is an important part of putting your app in production. This guide goes over how to obtain this information from your LangChain model calls.\n",
|
||||
"\n",
|
||||
"This guide requires `langchain-anthropic` and `langchain-openai >= 0.1.9`."
|
||||
]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"source": [
|
||||
"# How to add retrieval to chatbots\n",
|
||||
"\n",
|
||||
"[Retrieval](/docs/concepts/retrieval/) is a common technique chatbots use to augment their responses with data outside a chat model's training data. This section will cover how to implement retrieval in the context of chatbots, but it's worth noting that retrieval is a very subtle and deep topic - we encourage you to explore [other parts of the documentation](/docs/how_to#qa-with-rag) that go into greater depth!\n",
|
||||
"Retrieval is a common technique chatbots use to augment their responses with data outside a chat model's training data. This section will cover how to implement retrieval in the context of chatbots, but it's worth noting that retrieval is a very subtle and deep topic - we encourage you to explore [other parts of the documentation](/docs/how_to#qa-with-rag) that go into greater depth!\n",
|
||||
"\n",
|
||||
"## Setup\n",
|
||||
"\n",
|
||||
@@ -80,7 +80,7 @@
|
||||
"source": [
|
||||
"## Creating a retriever\n",
|
||||
"\n",
|
||||
"We'll use [the LangSmith documentation](https://docs.smith.langchain.com/overview) as source material and store the content in a [vector store](/docs/concepts/vectorstores/) for later retrieval. Note that this example will gloss over some of the specifics around parsing and storing a data source - you can see more [in-depth documentation on creating retrieval systems here](/docs/how_to#qa-with-rag).\n",
|
||||
"We'll use [the LangSmith documentation](https://docs.smith.langchain.com/overview) as source material and store the content in a vectorstore for later retrieval. Note that this example will gloss over some of the specifics around parsing and storing a data source - you can see more [in-depth documentation on creating retrieval systems here](/docs/how_to#qa-with-rag).\n",
|
||||
"\n",
|
||||
"Let's use a document loader to pull text from the docs:"
|
||||
]
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"OpenAI API Key: ········\n",
|
||||
@@ -78,7 +78,7 @@
|
||||
"\n",
|
||||
"Our end goal is to create an agent that can respond conversationally to user questions while looking up information as needed.\n",
|
||||
"\n",
|
||||
"First, let's initialize Tavily and an OpenAI [chat model](/docs/concepts/chat_models/) capable of tool calling:"
|
||||
"First, let's initialize Tavily and an OpenAI chat model capable of tool calling:"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to split code\n",
|
||||
"\n",
|
||||
"[RecursiveCharacterTextSplitter](https://python.langchain.com/api_reference/text_splitters/character/langchain_text_splitters.character.RecursiveCharacterTextSplitter.html) includes pre-built lists of separators that are useful for [splitting text](/docs/concepts/text_splitters/) in a specific programming language.\n",
|
||||
"[RecursiveCharacterTextSplitter](https://python.langchain.com/api_reference/text_splitters/character/langchain_text_splitters.character.RecursiveCharacterTextSplitter.html) includes pre-built lists of separators that are useful for splitting text in a specific programming language.\n",
|
||||
"\n",
|
||||
"Supported languages are stored in the `langchain_text_splitters.Language` enum. They include:\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
"source": [
|
||||
"# How to do retrieval with contextual compression\n",
|
||||
"\n",
|
||||
"One challenge with [retrieval](/docs/concepts/retrieval/) is that usually you don't know the specific queries your document storage system will face when you ingest data into the system. This means that the information most relevant to a query may be buried in a document with a lot of irrelevant text. Passing that full document through your application can lead to more expensive LLM calls and poorer responses.\n",
|
||||
"One challenge with retrieval is that usually you don't know the specific queries your document storage system will face when you ingest data into the system. This means that the information most relevant to a query may be buried in a document with a lot of irrelevant text. Passing that full document through your application can lead to more expensive LLM calls and poorer responses.\n",
|
||||
"\n",
|
||||
"Contextual compression is meant to fix this. The idea is simple: instead of immediately returning retrieved documents as-is, you can compress them using the context of the given query, so that only the relevant information is returned. “Compressing” here refers to both compressing the contents of an individual document and filtering out documents wholesale.\n",
|
||||
"\n",
|
||||
"To use the Contextual Compression Retriever, you'll need:\n",
|
||||
"\n",
|
||||
"- a base [retriever](/docs/concepts/retrievers/)\n",
|
||||
"- a base retriever\n",
|
||||
"- a Document Compressor\n",
|
||||
"\n",
|
||||
"The Contextual Compression Retriever passes queries to the base retriever, takes the initial documents and passes them through the Document Compressor. The Document Compressor takes a list of documents and shortens it by reducing the contents of documents or dropping documents altogether.\n",
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"In this guide, we'll learn how to create a custom [chat model](/docs/concepts/chat_models/) using LangChain abstractions.\n",
|
||||
"In this guide, we'll learn how to create a custom chat model using LangChain abstractions.\n",
|
||||
"\n",
|
||||
"Wrapping your LLM with the standard [`BaseChatModel`](https://python.langchain.com/api_reference/core/language_models/langchain_core.language_models.chat_models.BaseChatModel.html) interface allow you to use your LLM in existing LangChain programs with minimal code modifications!\n",
|
||||
"\n",
|
||||
"As an bonus, your LLM will automatically become a LangChain [Runnable](/docs/concepts/runnables/) and will benefit from some optimizations out of the box (e.g., batch via a threadpool), async support, the `astream_events` API, etc.\n",
|
||||
"As an bonus, your LLM will automatically become a LangChain `Runnable` and will benefit from some optimizations out of the box (e.g., batch via a threadpool), async support, the `astream_events` API, etc.\n",
|
||||
"\n",
|
||||
"## Inputs and outputs\n",
|
||||
"\n",
|
||||
"First, we need to talk about **[messages](/docs/concepts/messages/)**, which are the inputs and outputs of chat models.\n",
|
||||
"First, we need to talk about **messages**, which are the inputs and outputs of chat models.\n",
|
||||
"\n",
|
||||
"### Messages\n",
|
||||
"\n",
|
||||
@@ -162,21 +162,23 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 4,
|
||||
"id": "25ba32e5-5a6d-49f4-bb68-911827b84d61",
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from typing import Any, Dict, Iterator, List, Optional\n",
|
||||
"from typing import Any, AsyncIterator, Dict, Iterator, List, Optional\n",
|
||||
"\n",
|
||||
"from langchain_core.callbacks import (\n",
|
||||
" AsyncCallbackManagerForLLMRun,\n",
|
||||
" CallbackManagerForLLMRun,\n",
|
||||
")\n",
|
||||
"from langchain_core.language_models import BaseChatModel\n",
|
||||
"from langchain_core.language_models import BaseChatModel, SimpleChatModel\n",
|
||||
"from langchain_core.messages import AIMessageChunk, BaseMessage, HumanMessage\n",
|
||||
"from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult\n",
|
||||
"from langchain_core.runnables import run_in_executor\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class CustomChatModelAdvanced(BaseChatModel):\n",
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
"\n",
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"Many LLM applications involve retrieving information from external data sources using a [Retriever](/docs/concepts/retrievers/). \n",
|
||||
"Many LLM applications involve retrieving information from external data sources using a `Retriever`. \n",
|
||||
"\n",
|
||||
"A retriever is responsible for retrieving a list of relevant [Documents](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) to a given user `query`.\n",
|
||||
"A retriever is responsible for retrieving a list of relevant `Documents` to a given user `query`.\n",
|
||||
"\n",
|
||||
"The retrieved documents are often formatted into prompts that are fed into an LLM, allowing the LLM to use the information in the to generate an appropriate response (e.g., answering a user question based on a knowledge base).\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to create tools\n",
|
||||
"\n",
|
||||
"When constructing an [agent](/docs/concepts/agents/), you will need to provide it with a list of [Tools](/docs/concepts/tools/) that it can use. Besides the actual function that is called, the Tool consists of several components:\n",
|
||||
"When constructing an agent, you will need to provide it with a list of `Tool`s that it can use. Besides the actual function that is called, the Tool consists of several components:\n",
|
||||
"\n",
|
||||
"| Attribute | Type | Description |\n",
|
||||
"|---------------|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"`Document` objects are often formatted into prompts that are fed into an LLM, allowing the LLM to use the information in the `Document` to generate a desired response (e.g., summarizing the document).\n",
|
||||
"`Documents` can be either used immediately or indexed into a vectorstore for future retrieval and use.\n",
|
||||
"\n",
|
||||
"The main abstractions for [Document Loading](/docs/concepts/document_loaders/) are:\n",
|
||||
"The main abstractions for Document Loading are:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"| Component | Description |\n",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"\n",
|
||||
"[Portable Document Format (PDF)](https://en.wikipedia.org/wiki/PDF), standardized as ISO 32000, is a file format developed by Adobe in 1992 to present documents, including text formatting and images, in a manner independent of application software, hardware, and operating systems.\n",
|
||||
"\n",
|
||||
"This guide covers how to [load](/docs/concepts/document_loaders/) `PDF` documents into the LangChain [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) format that we use downstream.\n",
|
||||
"This guide covers how to load `PDF` documents into the LangChain [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) format that we use downstream.\n",
|
||||
"\n",
|
||||
"Text in PDFs is typically represented via text boxes. They may also contain images. A PDF parser might do some combination of the following:\n",
|
||||
"\n",
|
||||
@@ -250,7 +250,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Unstructured API Key: ········\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to load web pages\n",
|
||||
"\n",
|
||||
"This guide covers how to [load](/docs/concepts/document_loaders/) web pages into the LangChain [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) format that we use downstream. Web pages contain text, images, and other multimedia elements, and are typically represented with HTML. They may include links to other pages or resources.\n",
|
||||
"This guide covers how to load web pages into the LangChain [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) format that we use downstream. Web pages contain text, images, and other multimedia elements, and are typically represented with HTML. They may include links to other pages or resources.\n",
|
||||
"\n",
|
||||
"LangChain integrates with a host of parsers that are appropriate for web pages. The right parser will depend on your needs. Below we demonstrate two possibilities:\n",
|
||||
"\n",
|
||||
|
||||
@@ -15,9 +15,87 @@ The base Embeddings class in LangChain provides two methods: one for embedding d
|
||||
|
||||
### Setup
|
||||
|
||||
import EmbeddingTabs from "@theme/EmbeddingTabs";
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<EmbeddingTabs customVarName="embeddings_model" />
|
||||
<Tabs>
|
||||
<TabItem value="openai" label="OpenAI" default>
|
||||
To start we'll need to install the OpenAI partner package:
|
||||
|
||||
```bash
|
||||
pip install langchain-openai
|
||||
```
|
||||
|
||||
Accessing the API requires an API key, which you can get by creating an account and heading [here](https://platform.openai.com/account/api-keys). Once we have a key we'll want to set it as an environment variable by running:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="..."
|
||||
```
|
||||
|
||||
If you'd prefer not to set an environment variable you can pass the key in directly via the `api_key` named parameter when initiating the OpenAI LLM class:
|
||||
|
||||
```python
|
||||
from langchain_openai import OpenAIEmbeddings
|
||||
|
||||
embeddings_model = OpenAIEmbeddings(api_key="...")
|
||||
```
|
||||
|
||||
Otherwise you can initialize without any params:
|
||||
```python
|
||||
from langchain_openai import OpenAIEmbeddings
|
||||
|
||||
embeddings_model = OpenAIEmbeddings()
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="cohere" label="Cohere">
|
||||
|
||||
To start we'll need to install the Cohere SDK package:
|
||||
|
||||
```bash
|
||||
pip install langchain-cohere
|
||||
```
|
||||
|
||||
Accessing the API requires an API key, which you can get by creating an account and heading [here](https://dashboard.cohere.com/api-keys). Once we have a key we'll want to set it as an environment variable by running:
|
||||
|
||||
```shell
|
||||
export COHERE_API_KEY="..."
|
||||
```
|
||||
|
||||
If you'd prefer not to set an environment variable you can pass the key in directly via the `cohere_api_key` named parameter when initiating the Cohere LLM class:
|
||||
|
||||
```python
|
||||
from langchain_cohere import CohereEmbeddings
|
||||
|
||||
embeddings_model = CohereEmbeddings(cohere_api_key="...", model='embed-english-v3.0')
|
||||
```
|
||||
|
||||
Otherwise you can initialize simply as shown below:
|
||||
```python
|
||||
from langchain_cohere import CohereEmbeddings
|
||||
|
||||
embeddings_model = CohereEmbeddings(model='embed-english-v3.0')
|
||||
```
|
||||
Do note that it is mandatory to pass the model parameter while initializing the CohereEmbeddings class.
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="huggingface" label="Hugging Face">
|
||||
|
||||
To start we'll need to install the Hugging Face partner package:
|
||||
|
||||
```bash
|
||||
pip install langchain-huggingface
|
||||
```
|
||||
|
||||
You can then load any [Sentence Transformers model](https://huggingface.co/models?library=sentence-transformers) from the Hugging Face Hub.
|
||||
|
||||
```python
|
||||
from langchain_huggingface import HuggingFaceEmbeddings
|
||||
|
||||
embeddings_model = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### `embed_documents`
|
||||
#### Embed list of texts
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"source": [
|
||||
"# How to combine results from multiple retrievers\n",
|
||||
"\n",
|
||||
"The [EnsembleRetriever](https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.ensemble.EnsembleRetriever.html) supports ensembling of results from multiple [retrievers](/docs/concepts/retrievers/). It is initialized with a list of [BaseRetriever](https://python.langchain.com/api_reference/core/retrievers/langchain_core.retrievers.BaseRetriever.html) objects. EnsembleRetrievers rerank the results of the constituent retrievers based on the [Reciprocal Rank Fusion](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) algorithm.\n",
|
||||
"The [EnsembleRetriever](https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.ensemble.EnsembleRetriever.html) supports ensembling of results from multiple retrievers. It is initialized with a list of [BaseRetriever](https://python.langchain.com/api_reference/core/retrievers/langchain_core.retrievers.BaseRetriever.html) objects. EnsembleRetrievers rerank the results of the constituent retrievers based on the [Reciprocal Rank Fusion](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) algorithm.\n",
|
||||
"\n",
|
||||
"By leveraging the strengths of different algorithms, the `EnsembleRetriever` can achieve better performance than any single algorithm. \n",
|
||||
"\n",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"source": [
|
||||
"# How to use example selectors\n",
|
||||
"\n",
|
||||
"If you have a large number of examples, you may need to select which ones to include in the prompt. The [Example Selector](/docs/concepts/example_selectors/) is the class responsible for doing so.\n",
|
||||
"If you have a large number of examples, you may need to select which ones to include in the prompt. The Example Selector is the class responsible for doing so.\n",
|
||||
"\n",
|
||||
"The base interface is defined as below:\n",
|
||||
"\n",
|
||||
@@ -36,7 +36,7 @@
|
||||
"\n",
|
||||
"The only method it needs to define is a ``select_examples`` method. This takes in the input variables and then returns a list of examples. It is up to each specific implementation as to how those examples are selected.\n",
|
||||
"\n",
|
||||
"LangChain has a few different types of example selectors. For an overview of all these types, see the [below table](#example-selector-types).\n",
|
||||
"LangChain has a few different types of example selectors. For an overview of all these types, see the below table.\n",
|
||||
"\n",
|
||||
"In this guide, we will walk through creating a custom example selector."
|
||||
]
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"]} />\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"[LangSmith](https://docs.smith.langchain.com/) datasets have built-in support for similarity search, making them a great tool for building and querying few-shot examples.\n",
|
||||
"LangSmith datasets have built-in support for similarity search, making them a great tool for building and querying few-shot examples.\n",
|
||||
"\n",
|
||||
"In this guide we'll see how to use an indexed LangSmith dataset as a few-shot example selector.\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to select examples by length\n",
|
||||
"\n",
|
||||
"This [example selector](/docs/concepts/example_selectors/) selects which examples to use based on length. This is useful when you are worried about constructing a prompt that will go over the length of the context window. For longer inputs, it will select fewer examples to include, while for shorter inputs it will select more."
|
||||
"This example selector selects which examples to use based on length. This is useful when you are worried about constructing a prompt that will go over the length of the context window. For longer inputs, it will select fewer examples to include, while for shorter inputs it will select more."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to select examples by maximal marginal relevance (MMR)\n",
|
||||
"\n",
|
||||
"The `MaxMarginalRelevanceExampleSelector` selects [examples](/docs/concepts/example_selectors/) based on a combination of which examples are most similar to the inputs, while also optimizing for diversity. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs, and then iteratively adding them while penalizing them for closeness to already selected examples.\n"
|
||||
"The `MaxMarginalRelevanceExampleSelector` selects examples based on a combination of which examples are most similar to the inputs, while also optimizing for diversity. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs, and then iteratively adding them while penalizing them for closeness to already selected examples.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"\n",
|
||||
"The `NGramOverlapExampleSelector` selects and orders examples based on which examples are most similar to the input, according to an ngram overlap score. The ngram overlap score is a float between 0.0 and 1.0, inclusive. \n",
|
||||
"\n",
|
||||
"The [selector](/docs/concepts/example_selectors/) allows for a threshold score to be set. Examples with an ngram overlap score less than or equal to the threshold are excluded. The threshold is set to -1.0, by default, so will not exclude any examples, only reorder them. Setting the threshold to 0.0 will exclude examples that have no ngram overlaps with the input.\n"
|
||||
"The selector allows for a threshold score to be set. Examples with an ngram overlap score less than or equal to the threshold are excluded. The threshold is set to -1.0, by default, so will not exclude any examples, only reorder them. Setting the threshold to 0.0 will exclude examples that have no ngram overlaps with the input.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to select examples by similarity\n",
|
||||
"\n",
|
||||
"This object selects [examples](/docs/concepts/example_selectors/) based on similarity to the inputs. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs.\n"
|
||||
"This object selects examples based on similarity to the inputs. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"\n",
|
||||
"The quality of extractions can often be improved by providing reference examples to the LLM.\n",
|
||||
"\n",
|
||||
"Data extraction attempts to generate [structured representations](/docs/concepts/structured_outputs/) of information found in text and other unstructured or semi-structured formats. [Tool-calling](/docs/concepts/tool_calling) LLM features are often used in this context. This guide demonstrates how to build few-shot examples of tool calls to help steer the behavior of extraction and similar applications.\n",
|
||||
"Data extraction attempts to generate structured representations of information found in text and other unstructured or semi-structured formats. [Tool-calling](/docs/concepts/tool_calling) LLM features are often used in this context. This guide demonstrates how to build few-shot examples of tool calls to help steer the behavior of extraction and similar applications.\n",
|
||||
"\n",
|
||||
":::tip\n",
|
||||
"While this guide focuses how to use examples with a tool calling model, this technique is generally applicable, and will work\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to use prompting alone (no tool calling) to do extraction\n",
|
||||
"\n",
|
||||
"[Tool calling](/docs/concepts/tool_calling/) features are not required for generating structured output from LLMs. LLMs that are able to follow prompt instructions well can be tasked with outputting information in a given format.\n",
|
||||
"Tool calling features are not required for generating structured output from LLMs. LLMs that are able to follow prompt instructions well can be tasked with outputting information in a given format.\n",
|
||||
"\n",
|
||||
"This approach relies on designing good prompts and then parsing the output of the LLMs to make them extract information well.\n",
|
||||
"\n",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"In this guide, we'll learn how to create a simple prompt template that provides the model with example inputs and outputs when generating. Providing the LLM with a few such examples is called [few-shotting](/docs/concepts/few_shot_prompting/), and is a simple yet powerful way to guide generation and in some cases drastically improve model performance.\n",
|
||||
"In this guide, we'll learn how to create a simple prompt template that provides the model with example inputs and outputs when generating. Providing the LLM with a few such examples is called few-shotting, and is a simple yet powerful way to guide generation and in some cases drastically improve model performance.\n",
|
||||
"\n",
|
||||
"A few-shot prompt template can be constructed from either a set of examples, or from an [Example Selector](https://python.langchain.com/api_reference/core/example_selectors/langchain_core.example_selectors.base.BaseExampleSelector.html) class responsible for choosing a subset of examples from the defined set.\n",
|
||||
"\n",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"This guide covers how to prompt a chat model with example inputs and outputs. Providing the model with a few such examples is called [few-shotting](/docs/concepts/few_shot_prompting/), and is a simple yet powerful way to guide generation and in some cases drastically improve model performance.\n",
|
||||
"This guide covers how to prompt a chat model with example inputs and outputs. Providing the model with a few such examples is called few-shotting, and is a simple yet powerful way to guide generation and in some cases drastically improve model performance.\n",
|
||||
"\n",
|
||||
"There does not appear to be solid consensus on how best to do few-shot prompting, and the optimal prompt compilation will likely vary by model. Because of this, we provide few-shot prompt templates like the [FewShotChatMessagePromptTemplate](https://python.langchain.com/api_reference/core/prompts/langchain_core.prompts.few_shot.FewShotChatMessagePromptTemplate.html?highlight=fewshot#langchain_core.prompts.few_shot.FewShotChatMessagePromptTemplate) as a flexible starting point, and you can modify or replace them as you see fit.\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to filter messages\n",
|
||||
"\n",
|
||||
"In more complex chains and agents we might track state with a list of [messages](/docs/concepts/messages/). This list can start to accumulate messages from multiple different models, speakers, sub-chains, etc., and we may only want to pass subsets of this full list of messages to each model call in the chain/agent.\n",
|
||||
"In more complex chains and agents we might track state with a list of messages. This list can start to accumulate messages from multiple different models, speakers, sub-chains, etc., and we may only want to pass subsets of this full list of messages to each model call in the chain/agent.\n",
|
||||
"\n",
|
||||
"The `filter_messages` utility makes it easy to filter messages by type, id, or name.\n",
|
||||
"\n",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"source": [
|
||||
"# How to construct knowledge graphs\n",
|
||||
"\n",
|
||||
"In this guide we'll go over the basic ways of constructing a knowledge graph based on unstructured text. The constructured graph can then be used as knowledge base in a [RAG](/docs/concepts/rag/) application.\n",
|
||||
"In this guide we'll go over the basic ways of constructing a knowledge graph based on unstructured text. The constructured graph can then be used as knowledge base in a RAG application.\n",
|
||||
"\n",
|
||||
"## ⚠️ Security note ⚠️\n",
|
||||
"\n",
|
||||
@@ -68,7 +68,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" ········\n"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"source": [
|
||||
"# Hybrid Search\n",
|
||||
"\n",
|
||||
"The standard search in LangChain is done by vector similarity. However, a number of [vector store](/docs/integrations/vectorstores/) implementations (Astra DB, ElasticSearch, Neo4J, AzureSearch, Qdrant...) also support more advanced search combining vector similarity search and other search techniques (full-text, BM25, and so on). This is generally referred to as \"Hybrid\" search.\n",
|
||||
"The standard search in LangChain is done by vector similarity. However, a number of vectorstores implementations (Astra DB, ElasticSearch, Neo4J, AzureSearch, Qdrant...) also support more advanced search combining vector similarity search and other search techniques (full-text, BM25, and so on). This is generally referred to as \"Hybrid\" search.\n",
|
||||
"\n",
|
||||
"**Step 1: Make sure the vectorstore you are using supports hybrid search**\n",
|
||||
"\n",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"\n",
|
||||
"Here, we will look at a basic indexing workflow using the LangChain indexing API. \n",
|
||||
"\n",
|
||||
"The indexing API lets you load and keep in sync documents from any source into a [vector store](/docs/concepts/vectorstores/). Specifically, it helps:\n",
|
||||
"The indexing API lets you load and keep in sync documents from any source into a vector store. Specifically, it helps:\n",
|
||||
"\n",
|
||||
"* Avoid writing duplicated content into the vector store\n",
|
||||
"* Avoid re-writing unchanged content\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# LangChain Expression Language Cheatsheet\n",
|
||||
"\n",
|
||||
"This is a quick reference for all the most important [LCEL](/docs/concepts/lcel/) primitives. For more advanced usage see the [LCEL how-to guides](/docs/how_to/#langchain-expression-language-lcel) and the [full API reference](https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.base.Runnable.html).\n",
|
||||
"This is a quick reference for all the most important LCEL primitives. For more advanced usage see the [LCEL how-to guides](/docs/how_to/#langchain-expression-language-lcel) and the [full API reference](https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.base.Runnable.html).\n",
|
||||
"\n",
|
||||
"### Invoke a runnable\n",
|
||||
"#### [Runnable.invoke()](https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.base.Runnable.html#langchain_core.runnables.base.Runnable.invoke) / [Runnable.ainvoke()](https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.base.Runnable.html#langchain_core.runnables.base.Runnable.ainvoke)"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to cache LLM responses\n",
|
||||
"\n",
|
||||
"LangChain provides an optional [caching](/docs/concepts/chat_models/#caching) layer for LLMs. This is useful for two reasons:\n",
|
||||
"LangChain provides an optional caching layer for LLMs. This is useful for two reasons:\n",
|
||||
"\n",
|
||||
"It can save you money by reducing the number of API calls you make to the LLM provider, if you're often requesting the same completion multiple times.\n",
|
||||
"It can speed up your application by reducing the number of API calls you make to the LLM provider.\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to track token usage for LLMs\n",
|
||||
"\n",
|
||||
"Tracking [token](/docs/concepts/tokens/) usage to calculate cost is an important part of putting your app in production. This guide goes over how to obtain this information from your LangChain model calls.\n",
|
||||
"Tracking token usage to calculate cost is an important part of putting your app in production. This guide goes over how to obtain this information from your LangChain model calls.\n",
|
||||
"\n",
|
||||
":::info Prerequisites\n",
|
||||
"\n",
|
||||
|
||||
@@ -11,11 +11,10 @@
|
||||
"\n",
|
||||
"This guide assumes familiarity with the following concepts:\n",
|
||||
"- [Chat models](/docs/concepts/chat_models)\n",
|
||||
"- [Tokens](/docs/concepts/tokens)\n",
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"Certain [chat models](/docs/concepts/chat_models/) can be configured to return token-level log probabilities representing the likelihood of a given token. This guide walks through how to get this information in LangChain."
|
||||
"Certain chat models can be configured to return token-level log probabilities representing the likelihood of a given token. This guide walks through how to get this information in LangChain."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to merge consecutive messages of the same type\n",
|
||||
"\n",
|
||||
"Certain models do not support passing in consecutive [messages](/docs/concepts/messages/) of the same type (a.k.a. \"runs\" of the same message type).\n",
|
||||
"Certain models do not support passing in consecutive messages of the same type (a.k.a. \"runs\" of the same message type).\n",
|
||||
"\n",
|
||||
"The `merge_message_runs` utility makes it easy to merge consecutive messages of the same type.\n",
|
||||
"\n",
|
||||
|
||||
@@ -331,7 +331,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can also pass in an arbitrary function. This function should take in a list of messages and output a list of messages.\n",
|
||||
"We can do all types of arbitrary formatting of messages here. In this case, let's just add a SystemMessage to the start of the list of messages."
|
||||
"We can do all types of arbitrary formatting of messages here. In this cases, let's just add a SystemMessage to the start of the list of messages."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to retrieve using multiple vectors per document\n",
|
||||
"\n",
|
||||
"It can often be useful to store multiple [vectors](/docs/concepts/vectorstores/) per document. There are multiple use cases where this is beneficial. For example, we can [embed](/docs/concepts/embedding_models/) multiple chunks of a document and associate those embeddings with the parent document, allowing [retriever](/docs/concepts/retrievers/) hits on the chunks to return the larger document.\n",
|
||||
"It can often be useful to store multiple vectors per document. There are multiple use cases where this is beneficial. For example, we can embed multiple chunks of a document and associate those embeddings with the parent document, allowing retriever hits on the chunks to return the larger document.\n",
|
||||
"\n",
|
||||
"LangChain implements a base [MultiVectorRetriever](https://python.langchain.com/api_reference/langchain/retrievers/langchain.retrievers.multi_vector.MultiVectorRetriever.html), which simplifies this process. Much of the complexity lies in how to create the multiple vectors per document. This notebook covers some of the common ways to create those vectors and use the `MultiVectorRetriever`.\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
"source": [
|
||||
"# How to pass multimodal data directly to models\n",
|
||||
"\n",
|
||||
"Here we demonstrate how to pass [multimodal](/docs/concepts/multimodality/) input directly to models. \n",
|
||||
"Here we demonstrate how to pass multimodal input directly to models. \n",
|
||||
"We currently expect all input to be passed in the same format as [OpenAI expects](https://platform.openai.com/docs/guides/vision).\n",
|
||||
"For other model providers that support multimodal input, we have added logic inside the class to convert to the expected format.\n",
|
||||
"\n",
|
||||
"In this example we will ask a [model](/docs/concepts/chat_models/#multimodality) to describe an image."
|
||||
"In this example we will ask a model to describe an image."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
"source": [
|
||||
"# How to use multimodal prompts\n",
|
||||
"\n",
|
||||
"Here we demonstrate how to use prompt templates to format [multimodal](/docs/concepts/multimodality/) inputs to models. \n",
|
||||
"Here we demonstrate how to use prompt templates to format multimodal inputs to models. \n",
|
||||
"\n",
|
||||
"In this example we will ask a [model](/docs/concepts/chat_models/#multimodality) to describe an image."
|
||||
"In this example we will ask a model to describe an image."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
"source": [
|
||||
"# How to create a custom Output Parser\n",
|
||||
"\n",
|
||||
"In some situations you may want to implement a custom [parser](/docs/concepts/output_parsers/) to structure the model output into a custom format.\n",
|
||||
"In some situations you may want to implement a custom parser to structure the model output into a custom format.\n",
|
||||
"\n",
|
||||
"There are two ways to implement a custom parser:\n",
|
||||
"\n",
|
||||
"1. Using `RunnableLambda` or `RunnableGenerator` in [LCEL](/docs/concepts/lcel/) -- we strongly recommend this for most use cases\n",
|
||||
"1. Using `RunnableLambda` or `RunnableGenerator` in LCEL -- we strongly recommend this for most use cases\n",
|
||||
"2. By inherting from one of the base classes for out parsing -- this is the hard way of doing things\n",
|
||||
"\n",
|
||||
"The difference between the two approaches are mostly superficial and are mainly in terms of which callbacks are triggered (e.g., `on_chain_start` vs. `on_parser_start`), and how a runnable lambda vs. a parser might be visualized in a tracing platform like LangSmith."
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to use the output-fixing parser\n",
|
||||
"\n",
|
||||
"This [output parser](/docs/concepts/output_parsers/) wraps another output parser, and in the event that the first one fails it calls out to another LLM to fix any errors.\n",
|
||||
"This output parser wraps another output parser, and in the event that the first one fails it calls out to another LLM to fix any errors.\n",
|
||||
"\n",
|
||||
"But we can do other things besides throw errors. Specifically, we can pass the misformatted output, along with the formatted instructions, to the model and ask it to fix it.\n",
|
||||
"\n",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"\n",
|
||||
"Language models output text. But there are times where you want to get more structured information than just text back. While some model providers support [built-in ways to return structured output](/docs/how_to/structured_output), not all do.\n",
|
||||
"\n",
|
||||
"[Output parsers](/docs/concepts/output_parsers/) are classes that help structure language model responses. There are two main methods an output parser must implement:\n",
|
||||
"Output parsers are classes that help structure language model responses. There are two main methods an output parser must implement:\n",
|
||||
"\n",
|
||||
"- \"Get format instructions\": A method which returns a string containing instructions for how the output of a language model should be formatted.\n",
|
||||
"- \"Parse\": A method which takes in a string (assumed to be the response from a language model) and parses it into some structure.\n",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"\n",
|
||||
"LLMs from different providers often have different strengths depending on the specific data they are trained on. This also means that some may be \"better\" and more reliable at generating output in formats other than JSON.\n",
|
||||
"\n",
|
||||
"This guide shows you how to use the [`XMLOutputParser`](https://python.langchain.com/api_reference/core/output_parsers/langchain_core.output_parsers.xml.XMLOutputParser.html) to prompt models for XML output, then and [parse](/docs/concepts/output_parsers/) that output into a usable format.\n",
|
||||
"This guide shows you how to use the [`XMLOutputParser`](https://python.langchain.com/api_reference/core/output_parsers/langchain_core.output_parsers.xml.XMLOutputParser.html) to prompt models for XML output, then and parse that output into a usable format.\n",
|
||||
"\n",
|
||||
":::note\n",
|
||||
"Keep in mind that large language models are leaky abstractions! You'll have to use an LLM with sufficient capacity to generate well-formed XML.\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to use the Parent Document Retriever\n",
|
||||
"\n",
|
||||
"When splitting documents for [retrieval](/docs/concepts/retrieval/), there are often conflicting desires:\n",
|
||||
"When splitting documents for retrieval, there are often conflicting desires:\n",
|
||||
"\n",
|
||||
"1. You may want to have small documents, so that their embeddings can most\n",
|
||||
" accurately reflect their meaning. If too long, then the embeddings can\n",
|
||||
@@ -72,7 +72,7 @@
|
||||
"source": [
|
||||
"## Retrieving full documents\n",
|
||||
"\n",
|
||||
"In this mode, we want to retrieve the full documents. Therefore, we only specify a child [splitter](/docs/concepts/text_splitters/)."
|
||||
"In this mode, we want to retrieve the full documents. Therefore, we only specify a child splitter."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"LangChain provides a user friendly interface for composing different parts of [prompts](/docs/concepts/prompt_templates/) together. You can do this with either string prompts or chat prompts. Constructing prompts this way allows for easy reuse of components."
|
||||
"LangChain provides a user friendly interface for composing different parts of prompts together. You can do this with either string prompts or chat prompts. Constructing prompts this way allows for easy reuse of components."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"Like partially binding arguments to a function, it can make sense to \"partial\" a [prompt template](/docs/concepts/prompt_templates/) - e.g. pass in a subset of the required values, as to create a new prompt template which expects only the remaining subset of values.\n",
|
||||
"Like partially binding arguments to a function, it can make sense to \"partial\" a prompt template - e.g. pass in a subset of the required values, as to create a new prompt template which expects only the remaining subset of values.\n",
|
||||
"\n",
|
||||
"LangChain supports this in two ways:\n",
|
||||
"\n",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
":::\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"In many [Q&A applications](/docs/concepts/rag/) we want to allow the user to have a back-and-forth conversation, meaning the application needs some sort of \"memory\" of past questions and answers, and some logic for incorporating those into its current thinking.\n",
|
||||
"In many Q&A applications we want to allow the user to have a back-and-forth conversation, meaning the application needs some sort of \"memory\" of past questions and answers, and some logic for incorporating those into its current thinking.\n",
|
||||
"\n",
|
||||
"In this guide we focus on **adding logic for incorporating historical messages.**\n",
|
||||
"\n",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"\n",
|
||||
"We generally suggest using the first item of the list that works for your use-case. That is, if your model supports tool-calling, try methods 1 or 2; otherwise, or if those fail, advance down the list.\n",
|
||||
"\n",
|
||||
"Let's first create a simple [RAG](/docs/concepts/rag/) chain. To start we'll just retrieve from Wikipedia using the [WikipediaRetriever](https://python.langchain.com/api_reference/community/retrievers/langchain_community.retrievers.wikipedia.WikipediaRetriever.html)."
|
||||
"Let's first create a simple RAG chain. To start we'll just retrieve from Wikipedia using the [WikipediaRetriever](https://python.langchain.com/api_reference/community/retrievers/langchain_community.retrievers.wikipedia.WikipediaRetriever.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -140,7 +140,7 @@
|
||||
"id": "c89e2045-9244-43e6-bf3f-59af22658529",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now that we've got a [model](/docs/concepts/chat_models/), [retriver](/docs/concepts/retrievers/) and [prompt](/docs/concepts/prompt_templates/), let's chain them all together. We'll need to add some logic for formatting our retrieved Documents to a string that can be passed to our prompt. Following the how-to guide on [adding citations](/docs/how_to/qa_citations) to a RAG application, we'll make it so our chain returns both the answer and the retrieved Documents."
|
||||
"Now that we've got a model, retriver and prompt, let's chain them all together. We'll need to add some logic for formatting our retrieved Documents to a string that can be passed to our prompt. Following the how-to guide on [adding citations](/docs/how_to/qa_citations) to a RAG application, we'll make it so our chain returns both the answer and the retrieved Documents."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
"source": [
|
||||
"# How to do per-user retrieval\n",
|
||||
"\n",
|
||||
"This guide demonstrates how to configure runtime properties of a retrieval chain. An example application is to limit the documents available to a [retriever](/docs/concepts/retrievers/) based on the user.\n",
|
||||
"This guide demonstrates how to configure runtime properties of a retrieval chain. An example application is to limit the documents available to a retriever based on the user.\n",
|
||||
"\n",
|
||||
"When building a [retrieval app](/docs/concepts/rag/), you often have to build it with multiple users in mind. This means that you may be storing data not just for one user, but for many different users, and they should not be able to see eachother's data. This means that you need to be able to configure your retrieval chain to only retrieve certain information. This generally involves two steps.\n",
|
||||
"When building a retrieval app, you often have to build it with multiple users in mind. This means that you may be storing data not just for one user, but for many different users, and they should not be able to see eachother's data. This means that you need to be able to configure your retrieval chain to only retrieve certain information. This generally involves two steps.\n",
|
||||
"\n",
|
||||
"**Step 1: Make sure the retriever you are using supports multiple users**\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to get your RAG application to return sources\n",
|
||||
"\n",
|
||||
"Often in [Q&A](/docs/concepts/rag/) applications it's important to show users the sources that were used to generate the answer. The simplest way to do this is for the chain to return the Documents that were retrieved in each generation.\n",
|
||||
"Often in Q&A applications it's important to show users the sources that were used to generate the answer. The simplest way to do this is for the chain to return the Documents that were retrieved in each generation.\n",
|
||||
"\n",
|
||||
"We'll work off of the Q&A app we built over the [LLM Powered Autonomous Agents](https://lilianweng.github.io/posts/2023-06-23-agent/) blog post by Lilian Weng in the [RAG tutorial](/docs/tutorials/rag).\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to stream results from your RAG application\n",
|
||||
"\n",
|
||||
"This guide explains how to stream results from a [RAG](/docs/concepts/rag/) application. It covers streaming tokens from the final output as well as intermediate steps of a chain (e.g., from query re-writing).\n",
|
||||
"This guide explains how to stream results from a RAG application. It covers streaming tokens from the final output as well as intermediate steps of a chain (e.g., from query re-writing).\n",
|
||||
"\n",
|
||||
"We'll work off of the Q&A app with sources we built over the [LLM Powered Autonomous Agents](https://lilianweng.github.io/posts/2023-06-23-agent/) blog post by Lilian Weng in the [RAG tutorial](/docs/tutorials/rag)."
|
||||
]
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"source": [
|
||||
"# How to add examples to the prompt for query analysis\n",
|
||||
"\n",
|
||||
"As our query analysis becomes more complex, the LLM may struggle to understand how exactly it should respond in certain scenarios. In order to improve performance here, we can [add examples](/docs/concepts/few_shot_prompting/) to the prompt to guide the LLM.\n",
|
||||
"As our query analysis becomes more complex, the LLM may struggle to understand how exactly it should respond in certain scenarios. In order to improve performance here, we can add examples to the prompt to guide the LLM.\n",
|
||||
"\n",
|
||||
"Let's take a look at how we can add examples for the LangChain YouTube video query analyzer we built in the [Quickstart](/docs/tutorials/query_analysis)."
|
||||
]
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"source": [
|
||||
"# How to handle multiple retrievers when doing query analysis\n",
|
||||
"\n",
|
||||
"Sometimes, a query analysis technique may allow for selection of which [retriever](/docs/concepts/retrievers/) to use. To use this, you will need to add some logic to select the retriever to do. We will show a simple example (using mock data) of how to do that."
|
||||
"Sometimes, a query analysis technique may allow for selection of which retriever to use. To use this, you will need to add some logic to select the retriever to do. We will show a simple example (using mock data) of how to do that."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to split JSON data\n",
|
||||
"\n",
|
||||
"This json splitter [splits](/docs/concepts/text_splitters/) json data while allowing control over chunk sizes. It traverses json data depth first and builds smaller json chunks. It attempts to keep nested json objects whole but will split them if needed to keep chunks between a min_chunk_size and the max_chunk_size.\n",
|
||||
"This json splitter splits json data while allowing control over chunk sizes. It traverses json data depth first and builds smaller json chunks. It attempts to keep nested json objects whole but will split them if needed to keep chunks between a min_chunk_size and the max_chunk_size.\n",
|
||||
"\n",
|
||||
"If the value is not a nested json, but rather a very large string the string will not be split. If you need a hard cap on the chunk size consider composing this with a Recursive Text splitter on those chunks. There is an optional pre-processing step to split lists, by first converting them to json (dict) and then splitting them as such.\n",
|
||||
"\n",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"source": [
|
||||
"# How to recursively split text by characters\n",
|
||||
"\n",
|
||||
"This [text splitter](/docs/concepts/text_splitters/) is the recommended one for generic text. It is parameterized by a list of characters. It tries to split on them in order until the chunks are small enough. The default list is `[\"\\n\\n\", \"\\n\", \" \", \"\"]`. This has the effect of trying to keep all paragraphs (and then sentences, and then words) together as long as possible, as those would generically seem to be the strongest semantically related pieces of text.\n",
|
||||
"This text splitter is the recommended one for generic text. It is parameterized by a list of characters. It tries to split on them in order until the chunks are small enough. The default list is `[\"\\n\\n\", \"\\n\", \" \", \"\"]`. This has the effect of trying to keep all paragraphs (and then sentences, and then words) together as long as possible, as those would generically seem to be the strongest semantically related pieces of text.\n",
|
||||
"\n",
|
||||
"1. How the text is split: by list of characters.\n",
|
||||
"2. How the chunk size is measured: by number of characters.\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# Response metadata\n",
|
||||
"\n",
|
||||
"Many model providers include some metadata in their chat generation [responses](/docs/concepts/messages/#aimessage). This metadata can be accessed via the `AIMessage.response_metadata: Dict` attribute. Depending on the model provider and model configuration, this can contain information like [token counts](/docs/how_to/chat_token_usage_tracking), [logprobs](/docs/how_to/logprobs), and more.\n",
|
||||
"Many model providers include some metadata in their chat generation responses. This metadata can be accessed via the `AIMessage.response_metadata: Dict` attribute. Depending on the model provider and model configuration, this can contain information like [token counts](/docs/how_to/chat_token_usage_tracking), [logprobs](/docs/how_to/logprobs), and more.\n",
|
||||
"\n",
|
||||
"Here's what the response metadata looks like for a few different providers:\n",
|
||||
"\n",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"We can pass in secrets to our [runnables](/docs/concepts/runnables/) at runtime using the `RunnableConfig`. Specifically we can pass in secrets with a `__` prefix to the `configurable` field. This will ensure that these secrets aren't traced as part of the invocation:"
|
||||
"We can pass in secrets to our runnables at runtime using the `RunnableConfig`. Specifically we can pass in secrets with a `__` prefix to the `configurable` field. This will ensure that these secrets aren't traced as part of the invocation:"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"A self-querying [retriever](/docs/concepts/retrievers/) is one that, as the name suggests, has the ability to query itself. Specifically, given any natural language query, the retriever uses a query-constructing LLM chain to write a structured query and then applies that structured query to its underlying [vector store](/docs/concepts/vectorstores/). This allows the retriever to not only use the user-input query for semantic similarity comparison with the contents of stored documents but to also extract filters from the user query on the metadata of stored documents and to execute those filters.\n",
|
||||
"A self-querying retriever is one that, as the name suggests, has the ability to query itself. Specifically, given any natural language query, the retriever uses a query-constructing LLM chain to write a structured query and then applies that structured query to its underlying VectorStore. This allows the retriever to not only use the user-input query for semantic similarity comparison with the contents of stored documents but to also extract filters from the user query on the metadata of stored documents and to execute those filters.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
@@ -95,7 +95,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.chains.query_constructor.schema import AttributeInfo\n",
|
||||
"from langchain.chains.query_constructor.base import AttributeInfo\n",
|
||||
"from langchain.retrievers.self_query.base import SelfQueryRetriever\n",
|
||||
"from langchain_openai import ChatOpenAI\n",
|
||||
"\n",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"source": [
|
||||
"# How to split text by tokens \n",
|
||||
"\n",
|
||||
"Language models have a [token](/docs/concepts/tokens/) limit. You should not exceed the token limit. When you [split your text](/docs/concepts/text_splitters/) into chunks it is therefore a good idea to count the number of tokens. There are many tokenizers. When you count tokens in your text you should use the same tokenizer as used in the language model. "
|
||||
"Language models have a token limit. You should not exceed the token limit. When you split your text into chunks it is therefore a good idea to count the number of tokens. There are many tokenizers. When you count tokens in your text you should use the same tokenizer as used in the language model. "
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user