Compare commits

..

127 Commits

Author SHA1 Message Date
Chester Curme
e10a316957 x 2025-08-11 12:42:48 -04:00
ccurme
45a067509f fix(core): fix tracing for PDFs in v1 messages (#32434) 2025-08-11 12:18:32 -04:00
Mason Daugherty
23c3fa65d4 feat(docs): enhance ResponseMetadata documentation with provider field usage notes (#32472) 2025-08-11 09:16:16 -04:00
Mason Daugherty
13d67cf37e fix(ollama): reasoning should come before text content (#32476) 2025-08-08 19:34:36 -04:00
Mason Daugherty
7f989d3c3b feat(docs): clarify ToolMessage contentfield usage 2025-08-08 13:02:59 -04:00
Mason Daugherty
b7968c2b7d feat(docs): add link to artifact usage in ToolMessage 2025-08-08 12:51:15 -04:00
Mason Daugherty
2f0c6421a1 Merge branch 'master' into wip-v0.4 2025-08-08 10:21:44 -04:00
Mason Daugherty
c31236264e chore: formatting across codebase (#32466) 2025-08-08 10:20:10 -04:00
Chester Curme
cfe13f673a Merge branch 'master' into wip-v0.4
# Conflicts:
#	libs/core/langchain_core/version.py
#	libs/core/pyproject.toml
#	libs/core/uv.lock
#	libs/partners/openai/tests/integration_tests/chat_models/test_responses_api.py
#	libs/partners/openai/uv.lock
2025-08-08 09:04:57 -04:00
ccurme
02001212b0 fix(openai): revert some changes (#32462)
Keep coverage on `output_version="v0"` (increasing coverage is being
managed in v0.4 branch).
2025-08-08 08:51:18 -04:00
Mason Daugherty
00244122bd feat(openai): minimal and verbosity (#32455) 2025-08-08 02:24:21 +00:00
Mason Daugherty
5599c59d4a chore: formatting across codebase (#32456)
To prevent polluting future PRs
2025-08-07 22:09:26 -04:00
ccurme
6727d6e8c8 release(core): 0.3.74 (#32454) 2025-08-07 16:39:01 -04:00
Michael Matloka
5036bd7adb fix(openai): don't crash get_num_tokens_from_messages on gpt-5 (#32451) 2025-08-07 16:33:19 -04:00
ccurme
ec2b34a02d feat(openai): custom tools (#32449) 2025-08-07 16:30:01 -04:00
Mason Daugherty
11d68a0b9e bump locks 2025-08-07 15:51:36 -04:00
Mason Daugherty
566774a893 Merge branch 'wip-v0.4' of github.com:langchain-ai/langchain into wip-v0.4 2025-08-07 15:50:40 -04:00
Mason Daugherty
255a6d668a feat: allow bypassing CI using PR label 2025-08-07 15:50:15 -04:00
Mason Daugherty
cbf4c0e565 Merge branch 'master' into wip-v0.4 2025-08-07 15:33:12 -04:00
Mason Daugherty
145d38f7dd test(openai): add tests for prompt_cache_key parameter and update docs (#32363)
Introduce tests to validate the behavior and inclusion of the
`prompt_cache_key` parameter in request payloads for the `ChatOpenAI`
model.
2025-08-07 15:29:47 -04:00
ccurme
68c70da33e fix(openai): add in output_text (#32450)
This property was deleted in `openai==1.99.2`.
2025-08-07 15:23:56 -04:00
Eugene Yurtsev
754528d23f feat(langchain): add stuff and map reduce chains (#32333)
* Add stuff and map reduce chains
* We'll need to rename and add unit tests to the chains prior to
official release
2025-08-07 15:20:05 -04:00
Mason Daugherty
dc66737f03 fix: docs and formatting (#32448) 2025-08-07 15:17:25 -04:00
Christophe Bornet
499dc35cfb chore(core): bump mypy version to 1.17 (#32390)
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-08-07 13:26:29 -04:00
Mason Daugherty
42c1159991 feat: add TextAccessor, deprecate .text() as method (#32441)
Adds backward compat for `.text()` on messages while keeping `.text`
access

_The kicker:_

Any previous use of `.text()` will now need a `# type: ignore[operator]`
to silence type checkers. However, it will still behave as expected at
runtime. Deprecating in v0.4.0, to be removed in v2.0.0.
2025-08-07 12:16:31 -04:00
CLOVA Studio 개발
ac706c77d4 docs(docs): update v0.1.1 chatModel document on langchain-naver. (#32445)
## **Description:** 
This PR was requested after the `langchain-naver` partner-managed
packages were released
[v0.1.1](https://pypi.org/project/langchain-naver/0.1.1/).
So we've updated some our documents with the additional changed
features.

## **Dependencies:** 
https://github.com/langchain-ai/langchain/pull/30956

---------

Co-authored-by: 김필환[AI Studio Dev1] <pilhwan.kim@navercorp.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-08-07 15:45:50 +00:00
Tianyu Chen
8493887b6f docs: update Docker image name for jaguardb setup (#32438)
**Description**
Updated the quick setup instructions for JaguarDB in the documentation.
Replaced the outdated Docker image `jaguardb/jaguardb_with_http` with
the current recommended image `jaguardb/jaguardb` for pulling and
running the server.
2025-08-07 11:23:29 -04:00
Christophe Bornet
a647073b26 feat(standard-tests): add a property to set the name of the parameter for the number of results to return (#32443)
Not all retrievers use `k` as param name to set the number of results to
return. Even in LangChain itself. Eg:
bc4251b9e0/libs/core/langchain_core/indexing/in_memory.py (L31)

So it's helpful to be able to change it for a given retriever.
The change also adds hints to disable the tests if the retriever doesn't
support setting the param in the constructor or in the invoke method
(for instance, the `InMemoryDocumentIndex` in the link supports in the
constructor but not in the invoke method).

This change is backward compatible.

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-07 11:22:24 -04:00
ccurme
e120604774 fix(infra): exclude pre-releases from previous version testing (#32447) 2025-08-07 10:18:59 -04:00
ccurme
06d8754b0b release(core): 0.3.73 (#32446) 2025-08-07 09:03:53 -04:00
ccurme
6e108c1cb4 feat(core): zero-out token costs for cache hits (#32437) 2025-08-07 08:49:34 -04:00
Mason Daugherty
cc6139860c fix: docs typing issues 2025-08-06 23:50:33 -04:00
Mason Daugherty
ae8f58ac6f fix(settings): update Python terminal settings and default interpreter path 2025-08-06 23:37:40 -04:00
Mason Daugherty
346731544b Merge branch 'master' into wip-v0.4 2025-08-06 18:24:10 -04:00
Mason Daugherty
c1b86cc929 feat: minor core work, v1 standard tests & (most of) v1 ollama (#32315)
Resolves #32215

---------

Co-authored-by: Chester Curme <chester.curme@gmail.com>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Nuno Campos <nuno@langchain.dev>
2025-08-06 18:22:02 -04:00
Mason Daugherty
376f70be96 sync wip with master (#32436)
Co-authored-by: Kanav Bansal <13186335+bansalkanav@users.noreply.github.com>
Co-authored-by: Pranav Bhartiya <124018094+pranauww@users.noreply.github.com>
Co-authored-by: Nelson Sproul <nelson.sproul@gmail.com>
Co-authored-by: John Bledsoe <jmbledsoe@gmail.com>
2025-08-06 17:57:05 -04:00
John Bledsoe
bc4251b9e0 fix(core): fix index checking when merging lists (#32431)
**Description:** fix an issue I discovered when attempting to merge
messages in which one message has an `index` key in its content
dictionary and another does not.
2025-08-06 12:47:33 -04:00
Nelson Sproul
2543007436 docs(langchain): complete PDF embedding example for OpenAI, also some minor doc fixes (#32426)
For OpenAI PDF attaching, note the needed metadata.

Also some minor doc updates.
2025-08-06 12:16:16 -04:00
ccurme
ac2de920b1 chore: increment versions for 0.4 branch (#32419) 2025-08-05 15:39:37 -04:00
ccurme
e02eed5489 feat: standard outputs (#32287)
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Nuno Campos <nuno@langchain.dev>
2025-08-05 15:17:32 -04:00
Mason Daugherty
ba83f58141 release(groq): 0.3.7 (#32417) 2025-08-05 15:13:08 -04:00
Mason Daugherty
fb490b0c39 feat(groq): losen restrictions on reasoning_effort, inject effort in meta, update tests (#32415) 2025-08-05 15:03:38 -04:00
Mason Daugherty
419c173225 feat(groq): openai-oss (#32411)
use new openai-oss for integration tests, set module-level testing model
names and improve robustness of tool tests
2025-08-05 14:18:56 -04:00
Pranav Bhartiya
4011257c25 docs: add Windows-specific setup instructions (#32399)
**Description:** This PR improves the contribution setup guide by adding
comprehensive Windows-specific instructions. The changes address a
common pain point for Windows contributors who don't have `make`
installed by default, making the LangChain contribution process more
accessible across different operating systems.
The main improvements include:

- Added a dedicated "Windows Users" section with multiple installation
options for `make` (Chocolatey, Scoop, WSL)
- Provided direct `uv` commands as alternatives to all `make` commands
throughout the setup guide
- Included Windows-specific instructions for testing, formatting,
linting, and spellchecking
- Enhanced the documentation to be more inclusive for Windows developers

This change makes it easier for Windows users to contribute to LangChain
without requiring additional tool installation, while maintaining the
existing workflow for users who already have `make` available.

**Issue:** This addresses the common barrier Windows users face when
trying to contribute to LangChain due to missing `make` commands.

**Dependencies:** None required - this is purely a documentation
improvement.

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-08-05 15:00:03 +00:00
Kanav Bansal
9de0892a77 fix(docs): update package names across multiple integration docs (#32393)
## **Description:** 
Updated incorrect package names across multiple integration docs by
replacing underscores with hyphens to reflect their actual names on
PyPI. This aligns with the actual PyPI package names and prevents
potential confusion or installation issues.
## **Issue:** N/A
## **Dependencies:** None
## **Twitter handle:** N/A

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-08-04 17:38:29 +00:00
Chester Curme
5414527236 Merge branch 'master' into wip-v0.4 2025-08-04 11:55:14 -04:00
Narasimha Badrinath
dd9f5d7cde feat(docs): add langchain-gradientai as provider (#32202)
langchain-gradientai is Digitalocean's integration with Langchain. It
will help users to build langchain applications using Digitalocean's
GradientAI platform.

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-08-04 14:57:59 +00:00
Ammar Younas
d348cfe968 docs: fix minor typos in image generation description (#32375)
Description:
Fixed minor typos in the `google_imagen.ipynb` integration notebook
related to image generation prompt formatting. No functional changes
were made — just a documentation correction to improve clarity.
2025-08-04 10:52:05 -04:00
Kanav Bansal
84c5048cb8 fix(docs): correct package names in FeatureTables.js (#32377)
## **Description:** 
Updated incorrect package names in `FeatureTables.js` by replacing
underscores with hyphens to reflect their actual names on PyPI. This
aligns with the actual PyPI package names and prevents potential
confusion or installation issues.

The following package names were corrected:
- `langchain_aws` ➝ `langchain-aws`
- `langchain_community` ➝ `langchain-community`
- `langchain_elasticsearch` ➝ `langchain-elasticsearch`
- `langchain_google_community` ➝ `langchain-google-community`

 
## **Issue:** N/A
## **Dependencies:** None
## **Twitter handle:** N/A
2025-08-04 10:51:32 -04:00
garciasces
d318c655b6 fix(docs): inconsistent docs for Google Vertex AI (#32381)
Description: Documentation is inconsistent with API docs.

Current documentation implies that to use the integration you must have
credentials configured AND store the path to a service account JSON
file.

API docs explain that you must only complete EITHER of the steps
regarding credentials.

I have updated the docs to make them consistent with the API wording.
2025-08-04 10:50:50 -04:00
Kanav Bansal
df4eed0cea fix(docs): update package names, class links and package links across kv_store_feat_table.py (#32353)
## **Description:** 
Refactored multiple entries in `kv_store_feat_table.py` to ensure that
all vector store metadata is accurate, consistent, and aligned with
LangChain's latest documentation structure and PyPI naming standards.

**Key improvements across all updated entries:**
- Updated `class` links to point to their respective **docs-based
integration pages** (e.g., `/docs/integrations/stores/...`) instead of
raw API reference URLs.
- Corrected `package` display names to use **hyphenated PyPI-compliant
names** (e.g., `langchain-astradb` instead of `langchain_astradb`).
- Updated `package` links to point to the **specific class-level API
references** (e.g., `/api_reference/.../storage/...ClassName.html`) for
precision.

These improvements enhance:
- Navigation experience for users
- Alignment with PyPI and docs naming conventions
- Clarity across LangChain’s integrations documentation


 
## **Issue:** N/A
## **Dependencies:** None
## **Twitter handle:** N/A
2025-08-04 09:46:54 -04:00
Dhanesh Gujrathi
a25e196fe9 docs(docs): add link for ALPHAVANTAGE_API_KEY generation in integration notebook (#32364)
docs(alpha_vantage): add link for ALPHAVANTAGE_API_KEY generation in
integration notebook

**Description:**

This PR updates the `docs/docs/integrations/tools/alpha_vantage.ipynb`
integration notebook to help users locate the API key registration page
for Alpha Vantage. The following markdown line was added:

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-08-03 19:49:44 +00:00
Ethan Knights
3137d49bd9 docs: minor agent tools markdown improvement (#32367)
Minor sharpening of agent tool doc.
2025-08-03 15:42:19 -04:00
Raphaël
9a2f49df1f fix(docs): add missing space (#32349) 2025-07-31 09:28:51 -04:00
Mason Daugherty
32e5040a42 chore: add CLAUDE.md (#32334) 2025-07-30 23:04:45 +00:00
Chester Curme
881c6534a6 Merge branch 'master' into wip-v0.4
# Conflicts:
#	.github/workflows/_integration_test.yml
#	.github/workflows/_release.yml
#	.github/workflows/api_doc_build.yml
#	.github/workflows/people.yml
#	.github/workflows/run_notebooks.yml
#	.github/workflows/scheduled_test.yml
#	SECURITY.md
#	docs/docs/integrations/vectorstores/pgvectorstore.ipynb
#	libs/langchain_v1/langchain/chat_models/base.py
#	libs/langchain_v1/tests/integration_tests/chat_models/test_base.py
#	libs/langchain_v1/tests/unit_tests/chat_models/test_chat_models.py
2025-07-30 13:16:17 -04:00
ccurme
a9e52ca605 chore(openai): bump openai sdk (#32322) 2025-07-30 10:58:18 -04:00
Kanav Bansal
e2bc8f19c0 docs(docs): update RAG tutorials link across multiple vector store docs (AstraDB, DatabricksVectorSearch, FAISS, Redis, etc.) (#32301)
## **Description:** 
This PR updates the internal documentation link for the RAG tutorials to
reflect the updated path. Previously, the link pointed to the root
`/docs/tutorials/`, which was generic. It now correctly routes to the
RAG-specific tutorial page for the following vector store docs.

1. AstraDBVectorStore
2. Clickhouse
3. CouchbaseSearchVectorStore
4. DatabricksVectorSearch
5. ElasticsearchStore
6. FAISS
7. Milvus
8. MongoDBAtlasVectorSearch
9. openGauss
10. PGVector
11. PGVectorStore
12. PineconeVectorStore
13. QdrantVectorStore
14. Redis
15. SQLServer

## **Issue:** N/A
## **Dependencies:** None
## **Twitter handle:** N/A
2025-07-30 09:46:01 -04:00
Mason Daugherty
fbd5a238d8 fix(core): revert "fix: tool call streaming bug with inconsistent indices from Qwen3" (#32307)
Reverts langchain-ai/langchain#32160

Original issue stems from using `ChatOpenAI` to interact with a `qwen`
model. Recommended to use
[langchain-qwq](https://python.langchain.com/docs/integrations/chat/qwq/)
which is built for Qwen
2025-07-29 10:26:38 -04:00
HerrDings
fc2f66ca80 docs: fixed link to docs of unstructured (#32306)
In the section [How to load documents from a
directory](https://python.langchain.com/docs/how_to/document_loader_directory/)
there is a link to the docs of *unstructured*. When you click this link,
it tells you that it has moved. Accordingly this PR fixes this link in
LangChain docs directly

from: `https://unstructured-io.github.io/unstructured/#`
to: `https://docs.unstructured.io/`
2025-07-29 10:12:22 -04:00
Mason Daugherty
0e287763cd fix: lint 2025-07-28 18:49:43 -04:00
Copilot
0b56c1bc4b fix: tool call streaming bug with inconsistent indices from Qwen3 (#32160)
Fixes a streaming bug where models like Qwen3 (using OpenAI interface)
send tool call chunks with inconsistent indices, resulting in
duplicate/erroneous tool calls instead of a single merged tool call.

## Problem

When Qwen3 streams tool calls, it sends chunks with inconsistent `index`
values:
- First chunk: `index=1` with tool name and partial arguments  
- Subsequent chunks: `index=0` with `name=None`, `id=None` and argument
continuation

The existing `merge_lists` function only merges chunks when their
`index` values match exactly, causing these logically related chunks to
remain separate, resulting in multiple incomplete tool calls instead of
one complete tool call.

```python
# Before fix: Results in 1 valid + 1 invalid tool call
chunk1 = AIMessageChunk(tool_call_chunks=[
    {"name": "search", "args": '{"query":', "id": "call_123", "index": 1}
])
chunk2 = AIMessageChunk(tool_call_chunks=[
    {"name": None, "args": ' "test"}', "id": None, "index": 0}  
])
merged = chunk1 + chunk2  # Creates 2 separate tool calls

# After fix: Results in 1 complete tool call
merged = chunk1 + chunk2  # Creates 1 merged tool call: search({"query": "test"})
```

## Solution

Enhanced the `merge_lists` function in `langchain_core/utils/_merge.py`
with intelligent tool call chunk merging:

1. **Preserves existing behavior**: Same-index chunks still merge as
before
2. **Adds special handling**: Tool call chunks with
`name=None`/`id=None` that don't match any existing index are now merged
with the most recent complete tool call chunk
3. **Maintains backward compatibility**: All existing functionality
works unchanged
4. **Targeted fix**: Only affects tool call chunks, doesn't change
behavior for other list items

The fix specifically handles the pattern where:
- A continuation chunk has `name=None` and `id=None` (indicating it's
part of an ongoing tool call)
- No matching index is found in existing chunks
- There exists a recent tool call chunk with a valid name or ID to merge
with

## Testing

Added comprehensive test coverage including:
-  Qwen3-style chunks with different indices now merge correctly
-  Existing same-index behavior preserved  
-  Multiple distinct tool calls remain separate
-  Edge cases handled (empty chunks, orphaned continuations)
-  Backward compatibility maintained

Fixes #31511.

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 Share your feedback on Copilot coding agent for the chance to win a
$200 gift card! Click
[here](https://survey.alchemer.com/s3/8343779/Copilot-Coding-agent) to
start the survey.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mdrxy <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-07-28 22:31:41 +00:00
Copilot
ad88e5aaec fix(core): resolve cache validation error by safely converting Generation to ChatGeneration objects (#32156)
## Problem

ChatLiteLLM encounters a `ValidationError` when using cache on
subsequent calls, causing the following error:

```
ValidationError(model='ChatResult', errors=[{'loc': ('generations', 0, 'type'), 'msg': "unexpected value; permitted: 'ChatGeneration'", 'type': 'value_error.const', 'ctx': {'given': 'Generation', 'permitted': ('ChatGeneration',)}}])
```

This occurs because:
1. The cache stores `Generation` objects (with `type="Generation"`)
2. But `ChatResult` expects `ChatGeneration` objects (with
`type="ChatGeneration"` and a required `message` field)
3. When cached values are retrieved, validation fails due to the type
mismatch

## Solution

Added graceful handling in both sync (`_generate_with_cache`) and async
(`_agenerate_with_cache`) cache methods to:

1. **Detect** when cached values contain `Generation` objects instead of
expected `ChatGeneration` objects
2. **Convert** them to `ChatGeneration` objects by wrapping the text
content in an `AIMessage`
3. **Preserve** all original metadata (`generation_info`)
4. **Allow** `ChatResult` creation to succeed without validation errors

## Example

```python
# Before: This would fail with ValidationError
from langchain_community.chat_models import ChatLiteLLM
from langchain_community.cache import SQLiteCache
from langchain.globals import set_llm_cache

set_llm_cache(SQLiteCache(database_path="cache.db"))
llm = ChatLiteLLM(model_name="openai/gpt-4o", cache=True, temperature=0)

print(llm.predict("test"))  # Works fine (cache empty)
print(llm.predict("test"))  # Now works instead of ValidationError

# After: Seamlessly handles both Generation and ChatGeneration objects
```

## Changes

- **`libs/core/langchain_core/language_models/chat_models.py`**: 
  - Added `Generation` import from `langchain_core.outputs`
- Enhanced cache retrieval logic in `_generate_with_cache` and
`_agenerate_with_cache` methods
- Added conversion from `Generation` to `ChatGeneration` objects when
needed

-
**`libs/core/tests/unit_tests/language_models/chat_models/test_cache.py`**:
- Added test case to validate the conversion logic handles mixed object
types

## Impact

- **Backward Compatible**: Existing code continues to work unchanged
- **Minimal Change**: Only affects cache retrieval path, no API changes
- **Robust**: Handles both legacy cached `Generation` objects and new
`ChatGeneration` objects
- **Preserves Data**: All original content and metadata is maintained
during conversion

Fixes #22389.

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mdrxy <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-28 22:28:16 +00:00
Mason Daugherty
30e3ed6a19 fix: add space in run-name for better readability 2025-07-28 17:46:27 -04:00
Mason Daugherty
8641a95c43 fix: update run-name in scheduled_test.yml to include dynamic inputs 2025-07-28 17:45:05 -04:00
Mason Daugherty
df70c5c186 chore: update actions run-names and add default inputs (#32293) 2025-07-28 17:33:27 -04:00
Mason Daugherty
d5ca77e065 fix: remove erreneous rocket emoji in run-name 2025-07-28 17:11:14 -04:00
Mason Daugherty
b7e4797e8b release(anthropic): 0.3.18 (#32292) 2025-07-28 17:07:11 -04:00
Mason Daugherty
3a487bf720 refactor(anthropic): AnthropicLLM to use Messages API (#32290)
re: #32189
2025-07-28 16:22:58 -04:00
Mason Daugherty
e5fd67024c fix: update link text for reporting security vulnerabilities in SECURITY.md 2025-07-28 15:05:31 -04:00
Mason Daugherty
b86841ac40 fix: update alt attribute for GitHub Codespace badge in README 2025-07-28 15:04:57 -04:00
Mason Daugherty
8db16b5633 fix: use new Google model names in examples (#32288) 2025-07-28 19:03:42 +00:00
Mason Daugherty
6f10160a45 fix: scripts/ errors 2025-07-28 15:03:25 -04:00
Mason Daugherty
e79e0bd6b4 fix(openai): add max_retries parameter to ChatOpenAI for handling 503 capacity errors (#32286)
Some integration tests were failing
2025-07-28 13:58:23 -04:00
ccurme
c55294ecb0 chore(core): add test for nested pydantic fields in schemas (#32285) 2025-07-28 17:27:24 +00:00
Mason Daugherty
7a26c3d233 fix: update bar_model to use the correct model version claude-3-7-sonnet-20250219 (#32284) 2025-07-28 12:57:40 -04:00
Mason Daugherty
c6ffac3ce0 refactor: mdx lint (#32282) 2025-07-28 12:56:22 -04:00
Mason Daugherty
a07d2c5016 refactor: remove references to unsupported model claude-3-sonnet-20240229 (#32281)
Addresses some (but not all) test issues brought about in #32280
2025-07-28 11:57:43 -04:00
Aleksandr Filippov
f0b6baa0ef fix(core): track within-batch deduplication in indexing num_skipped count (#32273)
**Description:** Fixes incorrect `num_skipped` count in the LangChain
indexing API. The current implementation only counts documents that
already exist in RecordManager (cross-batch duplicates) but fails to
count documents removed during within-batch deduplication via
`_deduplicate_in_order()`.

This PR adds tracking of the original batch size before deduplication
and includes the difference in `num_skipped`, ensuring that `num_added +
num_skipped` equals the total number of input documents.

**Issue:** Fixes incorrect document count reporting in indexing
statistics

**Dependencies:** None

Fixes #32272

---------

Co-authored-by: Alex Feel <afilippov@spotware.com>
2025-07-28 09:58:51 -04:00
Mason Daugherty
12c0e9b7d8 fix(docs): local API reference documentation build (#32271)
ensure all relevant packages are correctly processed - cli wasn't
included, also fix ValueError
2025-07-28 00:50:20 -04:00
Mason Daugherty
ed682ae62d fix: explicitly tell uv to copy when using devcontainer (#32267) 2025-07-28 00:01:06 -04:00
Mason Daugherty
caf1919217 fix: devcontainer to use volume to store the workspace (#32266)
should resolve the file sharing issue for users on macOS.
2025-07-27 23:43:06 -04:00
Mason Daugherty
904066f1ec feat: add VSCode configuration files for Python development (#32263) 2025-07-27 23:37:59 -04:00
Mason Daugherty
96cbd90cba fix: formatting issues in docstrings (#32265)
Ensures proper reStructuredText formatting by adding the required blank
line before closing docstring quotes, which resolves the "Block quote
ends without a blank line; unexpected unindent" warning.
2025-07-27 23:37:47 -04:00
Mason Daugherty
a8a2cff129 Merge branch 'master' of github.com:langchain-ai/langchain 2025-07-27 23:34:59 -04:00
Mason Daugherty
f4ff4514ef fix: update workspace folder path in devcontainer configuration 2025-07-27 23:34:57 -04:00
Mason Daugherty
d1679cec91 chore: add .editorconfig for consistent coding styles across files (#32261)
Following existing codebase conventions
2025-07-27 23:25:30 -04:00
Mason Daugherty
5295f2add0 fix: update dev container name to match service name 2025-07-27 22:30:16 -04:00
Mason Daugherty
5f5b87e9a3 fix: update service name in devcontainer configuration 2025-07-27 22:28:47 -04:00
Mason Daugherty
e0ef98dac0 feat: add markdownlint configuration file (#32264) 2025-07-27 22:24:58 -04:00
Mason Daugherty
62212c7ee2 fix: update links in SECURITY.md to use markdown format 2025-07-27 21:54:25 -04:00
Mason Daugherty
9d38f170ce refactor: enhance workflow names and descriptions for clarity (#32262) 2025-07-27 21:31:59 -04:00
Mason Daugherty
c6cb1fae61 fix: devcontainer (#32260) 2025-07-27 20:24:16 -04:00
Kanav Bansal
e42b1d23dc docs(docs): update RAG tutorials link to point to correct path (#32256)
- **Description:** This PR updates the internal documentation link for
the RAG tutorials to reflect the updated path. Previously, the link
pointed to the root `/docs/tutorials/`, which was generic. It now
correctly routes to the RAG-specific tutorial page.
  - **Issue:** N/A
  - **Dependencies:** None
  - **Twitter handle:** N/A
2025-07-27 20:00:41 -04:00
Mason Daugherty
53d0bfe9cd refactor: markdownlint (#32259) 2025-07-27 20:00:16 -04:00
Mason Daugherty
eafab52483 refactor: markdownlint SECURITY.md (#32258) 2025-07-27 19:55:25 -04:00
Christophe Bornet
efdfa00d10 chore(langchain): add ruff rules ARG (#32110)
See https://docs.astral.sh/ruff/rules/#flake8-unused-arguments-arg

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-07-26 18:32:34 -04:00
Christophe Bornet
a2ad5aca41 chore(langchain): add ruff rules TC (#31921)
See https://docs.astral.sh/ruff/rules/#flake8-type-checking-tc
2025-07-26 18:27:26 -04:00
Mason Daugherty
5ecbb5f277 fix(docs): temporary workaround until the underlying dependency issues in the AI21 package ecosystem are resolved. (#32248) 2025-07-25 15:12:44 -04:00
Mason Daugherty
c1028171af fix(docs): update protobuf version constraint to <5.0 in vercel_overrides.txt (#32247) 2025-07-25 15:08:44 -04:00
ccurme
f6236d9f12 fix(infra): add pypdf to vercel overrides (#32242)
>   × No solution found when resolving dependencies:
  ╰─▶ Because only langchain-neo4j==0.5.0 is available and
langchain-neo4j==0.5.0 depends on neo4j-graphrag>=1.9.0, we can conclude
that all versions of langchain-neo4j depend on neo4j-graphrag>=1.9.0.
      And because only neo4j-graphrag<=1.9.0 is available and
neo4j-graphrag==1.9.0 depends on pypdf>=5.1.0,<6.0.0, we can conclude
that all versions of langchain-neo4j depend on pypdf>=5.1.0,<6.0.0.
And because langchain-upstage==0.6.0 depends on pypdf>=4.2.0,<5.0.0
and only langchain-upstage==0.6.0 is available, we can conclude that
all versions of langchain-neo4j and all versions of langchain-upstage
      are incompatible.
And because you require langchain-neo4j and langchain-upstage, we can
      conclude that your requirements are unsatisfiable.

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-07-25 15:05:21 -04:00
Mason Daugherty
df20f111a8 fix(docs): add validation for repository format and name in API docs build workflow (#32246)
for build
2025-07-25 15:05:06 -04:00
Eugene Yurtsev
db22311094 ci(infra): no need for . in the regexp (#32245)
No need for allowing `.`
2025-07-25 15:02:02 -04:00
Mason Daugherty
f624ad489a feat(docs): improve devx, fix Makefile targets (#32237)
**TL;DR much of the provided `Makefile` targets were broken, and any
time I wanted to preview changes locally I either had to refer to a
command Chester gave me or try waiting on a Vercel preview deployment.
With this PR, everything should behave like normal.**

Significant updates to the `Makefile` and documentation files, focusing
on improving usability, adding clear messaging, and fixing/enhancing
documentation workflows.

### Updates to `Makefile`:

#### Enhanced build and cleaning processes:
- Added informative messages (e.g., "📚 Building LangChain
documentation...") to makefile targets like `docs_build`, `docs_clean`,
and `api_docs_build` for better user feedback during execution.
- Introduced a `clean-cache` target to the `docs` `Makefile` to clear
cached dependencies and ensure clean builds.

#### Improved dependency handling:
- Modified `install-py-deps` to create a `.venv/deps_installed` marker,
preventing redundant/duplicate dependency installations and improving
efficiency.

#### Streamlined file generation and infrastructure setup:
- Added caching for the LangServe README download and parallelized
feature table generation
- Added user-friendly completion messages for targets like `copy-infra`
and `render`.

#### Documentation server updates:
- Enhanced the `start` target with messages indicating server start and
URL for local documentation viewing.

---

### Documentation Improvements:

#### Content clarity and consistency:
- Standardized section titles for consistency across documentation
files.
[[1]](diffhunk://#diff-9b1a85ea8a9dcf79f58246c88692cd7a36316665d7e05a69141cfdc50794c82aL1-R1)
[[2]](diffhunk://#diff-944008ad3a79d8a312183618401fcfa71da0e69c75803eff09b779fc8e03183dL1-R1)
- Refined phrasing and formatting in sections like "Dependency
management" and "Formatting and linting" for better readability.
[[1]](diffhunk://#diff-2069d4f956ab606ae6d51b191439283798adaf3a6648542c409d258131617059L6-R6)
[[2]](diffhunk://#diff-2069d4f956ab606ae6d51b191439283798adaf3a6648542c409d258131617059L84-R82)

#### Enhanced workflows:
- Updated instructions for building and viewing documentation locally,
including tips for specifying server ports and handling API reference
previews.
[[1]](diffhunk://#diff-048deddcfd44b242e5b23aed9f2e9ec73afc672244ce14df2a0a316d95840c87L60-R94)
[[2]](diffhunk://#diff-048deddcfd44b242e5b23aed9f2e9ec73afc672244ce14df2a0a316d95840c87L82-R126)
- Expanded guidance on cleaning documentation artifacts and using
linting tools effectively.
[[1]](diffhunk://#diff-048deddcfd44b242e5b23aed9f2e9ec73afc672244ce14df2a0a316d95840c87L82-R126)
[[2]](diffhunk://#diff-048deddcfd44b242e5b23aed9f2e9ec73afc672244ce14df2a0a316d95840c87L107-R142)

#### API reference documentation:
- Improved instructions for generating and formatting in-code
documentation, highlighting best practices for docstring writing.
[[1]](diffhunk://#diff-048deddcfd44b242e5b23aed9f2e9ec73afc672244ce14df2a0a316d95840c87L107-R142)
[[2]](diffhunk://#diff-048deddcfd44b242e5b23aed9f2e9ec73afc672244ce14df2a0a316d95840c87L144-R186)

---

### Minor Changes:
- Added support for a new package name (`langchain_v1`) in the API
documentation generation script.
- Fixed minor capitalization and formatting issues in documentation
files.
[[1]](diffhunk://#diff-2069d4f956ab606ae6d51b191439283798adaf3a6648542c409d258131617059L40-R40)
[[2]](diffhunk://#diff-2069d4f956ab606ae6d51b191439283798adaf3a6648542c409d258131617059L166-R160)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-25 14:49:03 -04:00
Eugene Yurtsev
549ecd3e78 chore(infra): harden api docs build workflow (#32243)
Harden permissions for api docs build workflow
2025-07-25 14:40:20 -04:00
dishaprakash
a0671676ae feat(docs): add PGVectorStore (#30950)
Thank you for contributing to LangChain!

-  **Adding documentation for PGVectorStore**: 
docs: Adding documentation for the new PGVectorStore as a part of
langchain-postgres

- **Add docs**: The notebook for PGVectorStore is now added to the
directory `docs/docs/integrations`.
As a part of this change, we've also updated the VectorStore features
table and VectorStoreTabs

---------

Co-authored-by: Chester Curme <chester.curme@gmail.com>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-07-25 13:22:58 -04:00
Christophe Bornet
12ae42c5e9 chore(langchain): add ruff rules D1 (except D100 and D104) (#32123) 2025-07-25 11:59:48 -04:00
Christophe Bornet
e1238b8085 chore(langchain): add ruff rules SLF (#32112)
See https://docs.astral.sh/ruff/rules/private-member-access/
2025-07-25 11:56:40 -04:00
Chaitanya varma
8f5ec20ccf chore(langchain): strip_ansi fucntion to remove ANSI escape sequences (#32200)
**Description:** 
Fixes a bug in the file callback test where ANSI escape codes were
causing test failures. The improved test now properly handles ANSI
escape sequences by:
- Using exact string comparison instead of substring checking
- Applying the `strip_ansi` function consistently to all file contents
- Adding descriptive assertion messages
- Maintaining test coverage and backward compatibility

The changes ensure tests pass reliably even when terminal control
sequences are present in the output

**Issue:** Fixes #32150

**Dependencies:** None required - uses existing dependencies only.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-07-25 15:53:19 +00:00
niceg
0d6f915442 fix: LLM mimicking Unicode responses due to forced Unicode conversion of non-ASCII characters. (#32222)
fix: Fix LLM mimicking Unicode responses due to forced Unicode
conversion of non-ASCII characters.

- **Description:** This PR fixes an issue where the LLM would mimic
Unicode responses due to forced Unicode conversion of non-ASCII
characters in tool calls. The fix involves disabling the `ensure_ascii`
flag in `json.dumps()` when converting tool calls to OpenAI format.
- **Issue:** Fixes ↓↓↓
input:
```json
{'role': 'assistant', 'tool_calls': [{'type': 'function', 'id': 'call_nv9trcehdpihr21zj9po19vq', 'function': {'name': 'create_customer', 'arguments': '{"customer_name": "你好啊集团"}'}}]}
```
output:
```json
{'role': 'assistant', 'tool_calls': [{'type': 'function', 'id': 'call_nv9trcehdpihr21zj9po19vq', 'function': {'name': 'create_customer', 'arguments': '{"customer_name": "\\u4f60\\u597d\\u554a\\u96c6\\u56e2"}'}}]}
```
then:
llm will mimic outputting unicode. Unicode's vast number of symbols can
lengthen LLM responses, leading to slower performance.
<img width="686" height="277" alt="image"
src="https://github.com/user-attachments/assets/28f3b007-3964-4455-bee2-68f86ac1906d"
/>

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-07-24 17:01:31 -04:00
Mason Daugherty
d53ebf367e fix(docs): capitalization, codeblock formatting, and hyperlinks, note blocks (#32235)
widespread cleanup attempt
2025-07-24 16:55:04 -04:00
Copilot
54542b9385 docs(openai): add comprehensive documentation and examples for extra_body + others (#32149)
This PR addresses the common issue where users struggle to pass custom
parameters to OpenAI-compatible APIs like LM Studio, vLLM, and others.
The problem occurs when users try to use `model_kwargs` for custom
parameters, which causes API errors.

## Problem

Users attempting to pass custom parameters (like LM Studio's `ttl`
parameter) were getting errors:

```python
#  This approach fails
llm = ChatOpenAI(
    base_url="http://localhost:1234/v1",
    model="mlx-community/QwQ-32B-4bit",
    model_kwargs={"ttl": 5}  # Causes TypeError: unexpected keyword argument 'ttl'
)
```

## Solution

The `extra_body` parameter is the correct way to pass custom parameters
to OpenAI-compatible APIs:

```python
#  This approach works correctly
llm = ChatOpenAI(
    base_url="http://localhost:1234/v1",
    model="mlx-community/QwQ-32B-4bit",
    extra_body={"ttl": 5}  # Custom parameters go in extra_body
)
```

## Changes Made

1. **Enhanced Documentation**: Updated the `extra_body` parameter
docstring with comprehensive examples for LM Studio, vLLM, and other
providers

2. **Added Documentation Section**: Created a new "OpenAI-compatible
APIs" section in the main class docstring with practical examples

3. **Unit Tests**: Added tests to verify `extra_body` functionality
works correctly:
- `test_extra_body_parameter()`: Verifies custom parameters are included
in request payload
- `test_extra_body_with_model_kwargs()`: Ensures `extra_body` and
`model_kwargs` work together

4. **Clear Guidance**: Documented when to use `extra_body` vs
`model_kwargs`

## Examples Added

**LM Studio with TTL (auto-eviction):**
```python
ChatOpenAI(
    base_url="http://localhost:1234/v1",
    api_key="lm-studio",
    model="mlx-community/QwQ-32B-4bit",
    extra_body={"ttl": 300}  # Auto-evict after 5 minutes
)
```

**vLLM with custom sampling:**
```python
ChatOpenAI(
    base_url="http://localhost:8000/v1",
    api_key="EMPTY",
    model="meta-llama/Llama-2-7b-chat-hf",
    extra_body={
        "use_beam_search": True,
        "best_of": 4
    }
)
```

## Why This Works

- `model_kwargs` parameters are passed directly to the OpenAI client's
`create()` method, causing errors for non-standard parameters
- `extra_body` parameters are included in the HTTP request body, which
is exactly what OpenAI-compatible APIs expect for custom parameters

Fixes #32115.

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 Share your feedback on Copilot coding agent for the chance to win a
$200 gift card! Click
[here](https://survey.alchemer.com/s3/8343779/Copilot-Coding-agent) to
start the survey.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mdrxy <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-07-24 16:43:16 -04:00
Mason Daugherty
7d2a13f519 fix: various typos (#32231) 2025-07-24 12:35:08 -04:00
Christophe Bornet
0b34be4ce5 refactor(langchain): refactor unit test stub classes (#32209)
See
https://github.com/langchain-ai/langchain/pull/32098#discussion_r2225961563
2025-07-24 11:05:56 -04:00
Mason Daugherty
6f3169eb49 chore: update copilot development guidelines for clarity and structure (#32230) 2025-07-24 15:05:09 +00:00
Eugene Yurtsev
7995c719c5 chore(langchain_v1): clean anything uncertain (#32228)
Further clean up of namespace:

- Removed prompts (we'll re-add in a separate commit)
- Remove LocalFileStore until we can review whether all the
implementation details are necessary
- Remove message processing logic from memory (we'll figure out where to
expose it)
- Remove `Tool` primitive (should be sufficient to use `BaseTool` for
typing purposes)
- Remove utilities to create kv stores. Unclear if they've had much
usage outside MultiparentRetriever
2025-07-24 14:41:05 +00:00
Mason Daugherty
bdf1cd383c fix(langchain): update deps 2025-07-24 10:37:08 -04:00
Mason Daugherty
77c981999e fix(text-splitters): update langchain-core version to 0.3.72 2025-07-24 10:35:07 -04:00
Mason Daugherty
7f015b6f14 fix(text-splitters): update lock for release 2025-07-24 10:32:04 -04:00
Mason Daugherty
71ad451e1f Merge branch 'master' of github.com:langchain-ai/langchain 2025-07-24 10:24:17 -04:00
Mason Daugherty
2c42893703 fix(langchain): update langchain-core version to 0.3.72 2025-07-24 10:24:04 -04:00
Mason Daugherty
0e139fb9a6 release(langchain): 0.3.27 (#32227) 2025-07-24 10:20:20 -04:00
tanwirahmad
622bb05751 fix(langchain): class HTMLSemanticPreservingSplitter ignores the text inside the div tag (#32213)
**Description:** We collect the text from the "html", "body", "div", and
"main" nodes, if they have any.

**Issue:** Fixes #32206.
2025-07-24 10:09:03 -04:00
Eugene Yurtsev
56dde3ade3 feat(langchain): v1 scaffolding (#32166)
This PR adds scaffolding for langchain 1.0 entry package.

Most contents have been removed. 

Currently remaining entrypoints for:

* chat models
* embedding models
* memory -> trimming messages, filtering messages and counting tokens
[we may remove this]
* prompts -> we may remove some prompts
* storage: primarily to support cache backed embeddings, may remove the
kv store
* tools -> report tool primitives

Things to be added:

* Selected agent implementations
* Selected workflows
* Common primitives: messages, Document
* Primitives for type hinting: BaseChatModel, BaseEmbeddings
* Selected retrievers
* Selected text splitters

Things to be removed:

* Globals needs to be removed (needs an update in langchain core)


Todos: 

* TBD indexing api (requires sqlalchemy which we don't want as a
dependency)
* Be explicit about public/private interfaces (e.g., likely rename
chat_models.base.py to something more internal)
* Remove dockerfiles
* Update module doc-strings and README.md
2025-07-24 09:47:48 -04:00
Mason Daugherty
bd3d6496f3 release(core): 0.3.72 (#32214)
fixes #32170
2025-07-23 20:33:48 -04:00
jmaillefaud
fb5da8384e fix(core): Dereference Refs for pydantic schema fails in tool schema generation (#32203)
The `_dereference_refs_helper` in `langchain_core.utils.json_schema`
incorrectly handled objects with a reference and other fields.

**Issue**: #32170

# Description

We change the check so that it accepts other keys in the object.
2025-07-23 20:28:27 -04:00
Maxime Grenu
a7d0e42f3f docs: fix typos in documentation (#32201)
## Summary
- Fixed redundant word "done" in SECURITY.md line 69  
- Fixed grammar errors in Fireworks README.md line 77: "how it fares
compares" → "how it compares" and "in terms just" → "in terms of"

## Test plan
- [x] Verified changes improve readability and correct grammar
- [x] No functional changes, documentation only

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-23 10:43:25 -04:00
597 changed files with 26936 additions and 9317 deletions

View File

@@ -15,12 +15,12 @@ You may use the button above, or follow these steps to open this repo in a Codes
1. Click **Create codespace on master**.
For more info, check out the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace#creating-a-codespace).
## VS Code Dev Containers
[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/langchain-ai/langchain)
> [!NOTE]
> [!NOTE]
> If you click the link above you will open the main repo (`langchain-ai/langchain`) and *not* your local cloned repo. This is fine if you only want to run and test the library, but if you want to contribute you can use the link below and replace with your username and cloned repo name:
```txt

View File

@@ -4,7 +4,7 @@ services:
build:
dockerfile: libs/langchain/dev.Dockerfile
context: ..
networks:
- langchain-network

View File

@@ -129,4 +129,4 @@ For answers to common questions about this code of conduct, see the FAQ at
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thank you for taking the time to file a bug report.
Thank you for taking the time to file a bug report.
Use this to report BUGS in LangChain. For usage questions, feature requests and general design questions, please use the [LangChain Forum](https://forum.langchain.com/).
@@ -50,7 +50,7 @@ body:
If a maintainer can copy it, run it, and see it right away, there's a much higher chance that you'll be able to get help.
**Important!**
**Important!**
* Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.
* Reduce your code to the minimum required to reproduce the issue if possible. This makes it much easier for others to help you.
@@ -58,14 +58,14 @@ body:
* INCLUDE the language label (e.g. `python`) after the first three backticks to enable syntax highlighting. (e.g., ```python rather than ```).
placeholder: |
The following code:
The following code:
```python
from langchain_core.runnables import RunnableLambda
def bad_code(inputs) -> int:
raise NotImplementedError('For demo purpose')
chain = RunnableLambda(bad_code)
chain.invoke('Hello!')
```

View File

@@ -14,7 +14,7 @@ body:
Do **NOT** use this to ask usage questions or reporting issues with your code.
If you have usage questions or need help solving some problem,
If you have usage questions or need help solving some problem,
please use the [LangChain Forum](https://forum.langchain.com/).
If you're in the wrong place, here are some helpful links to find a better

View File

@@ -8,7 +8,7 @@ body:
If you are not a LangChain maintainer or were not asked directly by a maintainer to create an issue, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead.
You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository
You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository
or are a regular contributor to LangChain with previous merged pull requests.
- type: checkboxes
id: privileged

View File

@@ -4,4 +4,4 @@ RUN pip install httpx PyGithub "pydantic==2.0.2" pydantic-settings "pyyaml>=5.3.
COPY ./app /app
CMD ["python", "/app/main.py"]
CMD ["python", "/app/main.py"]

View File

@@ -4,8 +4,8 @@ description: "Generate the data for the LangChain People page"
author: "Jacob Lee <jacob@langchain.dev>"
inputs:
token:
description: 'User token, to read the GitHub API. Can be passed in using {{ secrets.LANGCHAIN_PEOPLE_GITHUB_TOKEN }}'
description: "User token, to read the GitHub API. Can be passed in using {{ secrets.LANGCHAIN_PEOPLE_GITHUB_TOKEN }}"
required: true
runs:
using: 'docker'
image: 'Dockerfile'
using: "docker"
image: "Dockerfile"

View File

@@ -3,14 +3,12 @@ import json
import os
import sys
from collections import defaultdict
from typing import Dict, List, Set
from pathlib import Path
from typing import Dict, List, Set
import tomllib
from packaging.requirements import Requirement
from get_min_versions import get_min_version_from_toml
from packaging.requirements import Requirement
LANGCHAIN_DIRS = [
"libs/core",
@@ -38,7 +36,7 @@ IGNORED_PARTNERS = [
]
PY_312_MAX_PACKAGES = [
"libs/partners/chroma", # https://github.com/chroma-core/chroma/issues/4382
"libs/partners/chroma", # https://github.com/chroma-core/chroma/issues/4382
]
@@ -85,9 +83,9 @@ def dependents_graph() -> dict:
for depline in extended_deps:
if depline.startswith("-e "):
# editable dependency
assert depline.startswith(
"-e ../partners/"
), "Extended test deps should only editable install partner packages"
assert depline.startswith("-e ../partners/"), (
"Extended test deps should only editable install partner packages"
)
partner = depline.split("partners/")[1]
dep = f"langchain-{partner}"
else:
@@ -271,7 +269,7 @@ if __name__ == "__main__":
dirs_to_run["extended-test"].add(dir_)
elif file.startswith("libs/standard-tests"):
# TODO: update to include all packages that rely on standard-tests (all partner packages)
# note: won't run on external repo partners
# Note: won't run on external repo partners
dirs_to_run["lint"].add("libs/standard-tests")
dirs_to_run["test"].add("libs/standard-tests")
dirs_to_run["lint"].add("libs/cli")
@@ -285,7 +283,7 @@ if __name__ == "__main__":
elif file.startswith("libs/cli"):
dirs_to_run["lint"].add("libs/cli")
dirs_to_run["test"].add("libs/cli")
elif file.startswith("libs/partners"):
partner_dir = file.split("/")[2]
if os.path.isdir(f"libs/partners/{partner_dir}") and [
@@ -303,7 +301,10 @@ if __name__ == "__main__":
f"Unknown lib: {file}. check_diff.py likely needs "
"an update for this new library!"
)
elif file.startswith("docs/") or file in ["pyproject.toml", "uv.lock"]: # docs or root uv files
elif file.startswith("docs/") or file in [
"pyproject.toml",
"uv.lock",
]: # docs or root uv files
docs_edited = True
dirs_to_run["lint"].add(".")

View File

@@ -1,4 +1,5 @@
import sys
import tomllib
if __name__ == "__main__":

View File

@@ -1,5 +1,5 @@
from collections import defaultdict
import sys
from collections import defaultdict
from typing import Optional
if sys.version_info >= (3, 11):
@@ -8,17 +8,13 @@ else:
# for python 3.10 and below, which doesnt have stdlib tomllib
import tomli as tomllib
from packaging.requirements import Requirement
from packaging.specifiers import SpecifierSet
from packaging.version import Version
import requests
from packaging.version import parse
import re
from typing import List
import re
import requests
from packaging.requirements import Requirement
from packaging.specifiers import SpecifierSet
from packaging.version import Version, parse
MIN_VERSION_LIBS = [
"langchain-core",
@@ -72,11 +68,13 @@ def get_minimum_version(package_name: str, spec_string: str) -> Optional[str]:
spec_string = re.sub(r"\^0\.0\.(\d+)", r"0.0.\1", spec_string)
# rewrite occurrences of ^0.y.z to >=0.y.z,<0.y+1 (can be anywhere in constraint string)
for y in range(1, 10):
spec_string = re.sub(rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y+1}", spec_string)
spec_string = re.sub(
rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y + 1}", spec_string
)
# rewrite occurrences of ^x.y.z to >=x.y.z,<x+1.0.0 (can be anywhere in constraint string)
for x in range(1, 10):
spec_string = re.sub(
rf"\^{x}\.(\d+)\.(\d+)", rf">={x}.\1.\2,<{x+1}", spec_string
rf"\^{x}\.(\d+)\.(\d+)", rf">={x}.\1.\2,<{x + 1}", spec_string
)
spec_set = SpecifierSet(spec_string)
@@ -169,12 +167,12 @@ def check_python_version(version_string, constraint_string):
# rewrite occurrences of ^0.y.z to >=0.y.z,<0.y+1.0 (can be anywhere in constraint string)
for y in range(1, 10):
constraint_string = re.sub(
rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y+1}.0", constraint_string
rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y + 1}.0", constraint_string
)
# rewrite occurrences of ^x.y.z to >=x.y.z,<x+1.0.0 (can be anywhere in constraint string)
for x in range(1, 10):
constraint_string = re.sub(
rf"\^{x}\.0\.(\d+)", rf">={x}.0.\1,<{x+1}.0.0", constraint_string
rf"\^{x}\.0\.(\d+)", rf">={x}.0.\1,<{x + 1}.0.0", constraint_string
)
try:

View File

@@ -3,9 +3,10 @@
import os
import shutil
import yaml
from pathlib import Path
from typing import Dict, Any
from typing import Any, Dict
import yaml
def load_packages_yaml() -> Dict[str, Any]:
@@ -28,7 +29,6 @@ def get_target_dir(package_name: str) -> Path:
def clean_target_directories(packages: list) -> 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}")
@@ -38,7 +38,6 @@ def clean_target_directories(packages: list) -> None:
def move_libraries(packages: list) -> None:
"""Move libraries from their source locations to the target directories."""
for package in packages:
repo_name = package["repo"].split("/")[1]
source_path = package["path"]
target_dir = get_target_dir(package["name"])
@@ -68,23 +67,33 @@ def main():
package_yaml = load_packages_yaml()
# Clean target directories
clean_target_directories([
p
for p in package_yaml["packages"]
if (p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref"))
and p["repo"] != "langchain-ai/langchain"
and p["name"] != "langchain-ai21" # Skip AI21 due to dependency conflicts
])
clean_target_directories(
[
p
for p in package_yaml["packages"]
if (
p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref")
)
and p["repo"] != "langchain-ai/langchain"
and p["name"]
!= "langchain-ai21" # Skip AI21 due to dependency conflicts
]
)
# Move libraries to their new locations
move_libraries([
p
for p in package_yaml["packages"]
if not p.get("disabled", False)
and (p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref"))
and p["repo"] != "langchain-ai/langchain"
and p["name"] != "langchain-ai21" # Skip AI21 due to dependency conflicts
])
move_libraries(
[
p
for p in package_yaml["packages"]
if not p.get("disabled", False)
and (
p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref")
)
and p["repo"] != "langchain-ai/langchain"
and p["name"]
!= "langchain-ai21" # Skip AI21 due to dependency conflicts
]
)
# Delete ones without a pyproject.toml
for partner in Path("langchain/libs/partners").iterdir():

View File

@@ -81,56 +81,93 @@ import time
__version__ = "2022.12+dev"
# Update symlinks only if the platform supports not following them
UPDATE_SYMLINKS = bool(os.utime in getattr(os, 'supports_follow_symlinks', []))
UPDATE_SYMLINKS = bool(os.utime in getattr(os, "supports_follow_symlinks", []))
# Call os.path.normpath() only if not in a POSIX platform (Windows)
NORMALIZE_PATHS = (os.path.sep != '/')
NORMALIZE_PATHS = os.path.sep != "/"
# How many files to process in each batch when re-trying merge commits
STEPMISSING = 100
# (Extra) keywords for the os.utime() call performed by touch()
UTIME_KWS = {} if not UPDATE_SYMLINKS else {'follow_symlinks': False}
UTIME_KWS = {} if not UPDATE_SYMLINKS else {"follow_symlinks": False}
# Command-line interface ######################################################
def parse_args():
parser = argparse.ArgumentParser(
description=__doc__.split('\n---')[0])
parser = argparse.ArgumentParser(description=__doc__.split("\n---")[0])
group = parser.add_mutually_exclusive_group()
group.add_argument('--quiet', '-q', dest='loglevel',
action="store_const", const=logging.WARNING, default=logging.INFO,
help="Suppress informative messages and summary statistics.")
group.add_argument('--verbose', '-v', action="count", help="""
group.add_argument(
"--quiet",
"-q",
dest="loglevel",
action="store_const",
const=logging.WARNING,
default=logging.INFO,
help="Suppress informative messages and summary statistics.",
)
group.add_argument(
"--verbose",
"-v",
action="count",
help="""
Print additional information for each processed file.
Specify twice to further increase verbosity.
""")
""",
)
parser.add_argument('--cwd', '-C', metavar="DIRECTORY", help="""
parser.add_argument(
"--cwd",
"-C",
metavar="DIRECTORY",
help="""
Run as if %(prog)s was started in directory %(metavar)s.
This affects how --work-tree, --git-dir and PATHSPEC arguments are handled.
See 'man 1 git' or 'git --help' for more information.
""")
""",
)
parser.add_argument('--git-dir', dest='gitdir', metavar="GITDIR", help="""
parser.add_argument(
"--git-dir",
dest="gitdir",
metavar="GITDIR",
help="""
Path to the git repository, by default auto-discovered by searching
the current directory and its parents for a .git/ subdirectory.
""")
""",
)
parser.add_argument('--work-tree', dest='workdir', metavar="WORKTREE", help="""
parser.add_argument(
"--work-tree",
dest="workdir",
metavar="WORKTREE",
help="""
Path to the work tree root, by default the parent of GITDIR if it's
automatically discovered, or the current directory if GITDIR is set.
""")
""",
)
parser.add_argument('--force', '-f', default=False, action="store_true", help="""
parser.add_argument(
"--force",
"-f",
default=False,
action="store_true",
help="""
Force updating files with uncommitted modifications.
Untracked files and uncommitted deletions, renames and additions are
always ignored.
""")
""",
)
parser.add_argument('--merge', '-m', default=False, action="store_true", help="""
parser.add_argument(
"--merge",
"-m",
default=False,
action="store_true",
help="""
Include merge commits.
Leads to more recent times and more files per commit, thus with the same
time, which may or may not be what you want.
@@ -138,71 +175,130 @@ def parse_args():
are found sooner, which can improve performance, sometimes substantially.
But as merge commits are usually huge, processing them may also take longer.
By default, merge commits are only used for files missing from regular commits.
""")
""",
)
parser.add_argument('--first-parent', default=False, action="store_true", help="""
parser.add_argument(
"--first-parent",
default=False,
action="store_true",
help="""
Consider only the first parent, the "main branch", when evaluating merge commits.
Only effective when merge commits are processed, either when --merge is
used or when finding missing files after the first regular log search.
See --skip-missing.
""")
""",
)
parser.add_argument('--skip-missing', '-s', dest="missing", default=True,
action="store_false", help="""
parser.add_argument(
"--skip-missing",
"-s",
dest="missing",
default=True,
action="store_false",
help="""
Do not try to find missing files.
If merge commits were not evaluated with --merge and some files were
not found in regular commits, by default %(prog)s searches for these
files again in the merge commits.
This option disables this retry, so files found only in merge commits
will not have their timestamp updated.
""")
""",
)
parser.add_argument('--no-directories', '-D', dest='dirs', default=True,
action="store_false", help="""
parser.add_argument(
"--no-directories",
"-D",
dest="dirs",
default=True,
action="store_false",
help="""
Do not update directory timestamps.
By default, use the time of its most recently created, renamed or deleted file.
Note that just modifying a file will NOT update its directory time.
""")
""",
)
parser.add_argument('--test', '-t', default=False, action="store_true",
help="Test run: do not actually update any file timestamp.")
parser.add_argument(
"--test",
"-t",
default=False,
action="store_true",
help="Test run: do not actually update any file timestamp.",
)
parser.add_argument('--commit-time', '-c', dest='commit_time', default=False,
action='store_true', help="Use commit time instead of author time.")
parser.add_argument(
"--commit-time",
"-c",
dest="commit_time",
default=False,
action="store_true",
help="Use commit time instead of author time.",
)
parser.add_argument('--oldest-time', '-o', dest='reverse_order', default=False,
action='store_true', help="""
parser.add_argument(
"--oldest-time",
"-o",
dest="reverse_order",
default=False,
action="store_true",
help="""
Update times based on the oldest, instead of the most recent commit of a file.
This reverses the order in which the git log is processed to emulate a
file "creation" date. Note this will be inaccurate for files deleted and
re-created at later dates.
""")
""",
)
parser.add_argument('--skip-older-than', metavar='SECONDS', type=int, help="""
parser.add_argument(
"--skip-older-than",
metavar="SECONDS",
type=int,
help="""
Ignore files that are currently older than %(metavar)s.
Useful in workflows that assume such files already have a correct timestamp,
as it may improve performance by processing fewer files.
""")
""",
)
parser.add_argument('--skip-older-than-commit', '-N', default=False,
action='store_true', help="""
parser.add_argument(
"--skip-older-than-commit",
"-N",
default=False,
action="store_true",
help="""
Ignore files older than the timestamp it would be updated to.
Such files may be considered "original", likely in the author's repository.
""")
""",
)
parser.add_argument('--unique-times', default=False, action="store_true", help="""
parser.add_argument(
"--unique-times",
default=False,
action="store_true",
help="""
Set the microseconds to a unique value per commit.
Allows telling apart changes that would otherwise have identical timestamps,
as git's time accuracy is in seconds.
""")
""",
)
parser.add_argument('pathspec', nargs='*', metavar='PATHSPEC', help="""
parser.add_argument(
"pathspec",
nargs="*",
metavar="PATHSPEC",
help="""
Only modify paths matching %(metavar)s, relative to current directory.
By default, update all but untracked files and submodules.
""")
""",
)
parser.add_argument('--version', '-V', action='version',
version='%(prog)s version {version}'.format(version=get_version()))
parser.add_argument(
"--version",
"-V",
action="version",
version="%(prog)s version {version}".format(version=get_version()),
)
args_ = parser.parse_args()
if args_.verbose:
@@ -212,17 +308,18 @@ def parse_args():
def get_version(version=__version__):
if not version.endswith('+dev'):
if not version.endswith("+dev"):
return version
try:
cwd = os.path.dirname(os.path.realpath(__file__))
return Git(cwd=cwd, errors=False).describe().lstrip('v')
return Git(cwd=cwd, errors=False).describe().lstrip("v")
except Git.Error:
return '-'.join((version, "unknown"))
return "-".join((version, "unknown"))
# Helper functions ############################################################
def setup_logging():
"""Add TRACE logging level and corresponding method, return the root logger"""
logging.TRACE = TRACE = logging.DEBUG // 2
@@ -255,11 +352,13 @@ def normalize(path):
if path and path[0] == '"':
# Python 2: path = path[1:-1].decode("string-escape")
# Python 3: https://stackoverflow.com/a/46650050/624066
path = (path[1:-1] # Remove enclosing double quotes
.encode('latin1') # Convert to bytes, required by 'unicode-escape'
.decode('unicode-escape') # Perform the actual octal-escaping decode
.encode('latin1') # 1:1 mapping to bytes, UTF-8 encoded
.decode('utf8', 'surrogateescape')) # Decode from UTF-8
path = (
path[1:-1] # Remove enclosing double quotes
.encode("latin1") # Convert to bytes, required by 'unicode-escape'
.decode("unicode-escape") # Perform the actual octal-escaping decode
.encode("latin1") # 1:1 mapping to bytes, UTF-8 encoded
.decode("utf8", "surrogateescape")
) # Decode from UTF-8
if NORMALIZE_PATHS:
# Make sure the slash matches the OS; for Windows we need a backslash
path = os.path.normpath(path)
@@ -282,12 +381,12 @@ def touch_ns(path, mtime_ns):
def isodate(secs: int):
# time.localtime() accepts floats, but discards fractional part
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(secs))
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(secs))
def isodate_ns(ns: int):
# for integers fromtimestamp() is equivalent and ~16% slower than isodate()
return datetime.datetime.fromtimestamp(ns / 1000000000).isoformat(sep=' ')
return datetime.datetime.fromtimestamp(ns / 1000000000).isoformat(sep=" ")
def get_mtime_ns(secs: int, idx: int):
@@ -305,35 +404,49 @@ def get_mtime_path(path):
# Git class and parse_log(), the heart of the script ##########################
class Git:
def __init__(self, workdir=None, gitdir=None, cwd=None, errors=True):
self.gitcmd = ['git']
self.gitcmd = ["git"]
self.errors = errors
self._proc = None
if workdir: self.gitcmd.extend(('--work-tree', workdir))
if gitdir: self.gitcmd.extend(('--git-dir', gitdir))
if cwd: self.gitcmd.extend(('-C', cwd))
if workdir:
self.gitcmd.extend(("--work-tree", workdir))
if gitdir:
self.gitcmd.extend(("--git-dir", gitdir))
if cwd:
self.gitcmd.extend(("-C", cwd))
self.workdir, self.gitdir = self._get_repo_dirs()
def ls_files(self, paths: list = None):
return (normalize(_) for _ in self._run('ls-files --full-name', paths))
return (normalize(_) for _ in self._run("ls-files --full-name", paths))
def ls_dirty(self, force=False):
return (normalize(_[3:].split(' -> ', 1)[-1])
for _ in self._run('status --porcelain')
if _[:2] != '??' and (not force or (_[0] in ('R', 'A')
or _[1] == 'D')))
return (
normalize(_[3:].split(" -> ", 1)[-1])
for _ in self._run("status --porcelain")
if _[:2] != "??" and (not force or (_[0] in ("R", "A") or _[1] == "D"))
)
def log(self, merge=False, first_parent=False, commit_time=False,
reverse_order=False, paths: list = None):
cmd = 'whatchanged --pretty={}'.format('%ct' if commit_time else '%at')
if merge: cmd += ' -m'
if first_parent: cmd += ' --first-parent'
if reverse_order: cmd += ' --reverse'
def log(
self,
merge=False,
first_parent=False,
commit_time=False,
reverse_order=False,
paths: list = None,
):
cmd = "whatchanged --pretty={}".format("%ct" if commit_time else "%at")
if merge:
cmd += " -m"
if first_parent:
cmd += " --first-parent"
if reverse_order:
cmd += " --reverse"
return self._run(cmd, paths)
def describe(self):
return self._run('describe --tags', check=True)[0]
return self._run("describe --tags", check=True)[0]
def terminate(self):
if self._proc is None:
@@ -345,18 +458,22 @@ class Git:
pass
def _get_repo_dirs(self):
return (os.path.normpath(_) for _ in
self._run('rev-parse --show-toplevel --absolute-git-dir', check=True))
return (
os.path.normpath(_)
for _ in self._run(
"rev-parse --show-toplevel --absolute-git-dir", check=True
)
)
def _run(self, cmdstr: str, paths: list = None, output=True, check=False):
cmdlist = self.gitcmd + shlex.split(cmdstr)
if paths:
cmdlist.append('--')
cmdlist.append("--")
cmdlist.extend(paths)
popen_args = dict(universal_newlines=True, encoding='utf8')
popen_args = dict(universal_newlines=True, encoding="utf8")
if not self.errors:
popen_args['stderr'] = subprocess.DEVNULL
log.trace("Executing: %s", ' '.join(cmdlist))
popen_args["stderr"] = subprocess.DEVNULL
log.trace("Executing: %s", " ".join(cmdlist))
if not output:
return subprocess.call(cmdlist, **popen_args)
if check:
@@ -379,30 +496,26 @@ def parse_log(filelist, dirlist, stats, git, merge=False, filterlist=None):
mtime = 0
datestr = isodate(0)
for line in git.log(
merge,
args.first_parent,
args.commit_time,
args.reverse_order,
filterlist
merge, args.first_parent, args.commit_time, args.reverse_order, filterlist
):
stats['loglines'] += 1
stats["loglines"] += 1
# Blank line between Date and list of files
if not line:
continue
# Date line
if line[0] != ':': # Faster than `not line.startswith(':')`
stats['commits'] += 1
if line[0] != ":": # Faster than `not line.startswith(':')`
stats["commits"] += 1
mtime = int(line)
if args.unique_times:
mtime = get_mtime_ns(mtime, stats['commits'])
mtime = get_mtime_ns(mtime, stats["commits"])
if args.debug:
datestr = isodate(mtime)
continue
# File line: three tokens if it describes a renaming, otherwise two
tokens = line.split('\t')
tokens = line.split("\t")
# Possible statuses:
# M: Modified (content changed)
@@ -411,7 +524,7 @@ def parse_log(filelist, dirlist, stats, git, merge=False, filterlist=None):
# T: Type changed: to/from regular file, symlinks, submodules
# R099: Renamed (moved), with % of unchanged content. 100 = pure rename
# Not possible in log: C=Copied, U=Unmerged, X=Unknown, B=pairing Broken
status = tokens[0].split(' ')[-1]
status = tokens[0].split(" ")[-1]
file = tokens[-1]
# Handles non-ASCII chars and OS path separator
@@ -419,56 +532,76 @@ def parse_log(filelist, dirlist, stats, git, merge=False, filterlist=None):
def do_file():
if args.skip_older_than_commit and get_mtime_path(file) <= mtime:
stats['skip'] += 1
stats["skip"] += 1
return
if args.debug:
log.debug("%d\t%d\t%d\t%s\t%s",
stats['loglines'], stats['commits'], stats['files'],
datestr, file)
log.debug(
"%d\t%d\t%d\t%s\t%s",
stats["loglines"],
stats["commits"],
stats["files"],
datestr,
file,
)
try:
touch(os.path.join(git.workdir, file), mtime)
stats['touches'] += 1
stats["touches"] += 1
except Exception as e:
log.error("ERROR: %s: %s", e, file)
stats['errors'] += 1
stats["errors"] += 1
def do_dir():
if args.debug:
log.debug("%d\t%d\t-\t%s\t%s",
stats['loglines'], stats['commits'],
datestr, "{}/".format(dirname or '.'))
log.debug(
"%d\t%d\t-\t%s\t%s",
stats["loglines"],
stats["commits"],
datestr,
"{}/".format(dirname or "."),
)
try:
touch(os.path.join(git.workdir, dirname), mtime)
stats['dirtouches'] += 1
stats["dirtouches"] += 1
except Exception as e:
log.error("ERROR: %s: %s", e, dirname)
stats['direrrors'] += 1
stats["direrrors"] += 1
if file in filelist:
stats['files'] -= 1
stats["files"] -= 1
filelist.remove(file)
do_file()
if args.dirs and status in ('A', 'D'):
if args.dirs and status in ("A", "D"):
dirname = os.path.dirname(file)
if dirname in dirlist:
dirlist.remove(dirname)
do_dir()
# All files done?
if not stats['files']:
if not stats["files"]:
git.terminate()
return
# Main Logic ##################################################################
def main():
start = time.time() # yes, Wall time. CPU time is not realistic for users.
stats = {_: 0 for _ in ('loglines', 'commits', 'touches', 'skip', 'errors',
'dirtouches', 'direrrors')}
stats = {
_: 0
for _ in (
"loglines",
"commits",
"touches",
"skip",
"errors",
"dirtouches",
"direrrors",
)
}
logging.basicConfig(level=args.loglevel, format='%(message)s')
logging.basicConfig(level=args.loglevel, format="%(message)s")
log.trace("Arguments: %s", args)
# First things first: Where and Who are we?
@@ -499,13 +632,16 @@ def main():
# Symlink (to file, to dir or broken - git handles the same way)
if not UPDATE_SYMLINKS and os.path.islink(fullpath):
log.warning("WARNING: Skipping symlink, no OS support for updates: %s",
path)
log.warning(
"WARNING: Skipping symlink, no OS support for updates: %s", path
)
continue
# skip files which are older than given threshold
if (args.skip_older_than
and start - get_mtime_path(fullpath) > args.skip_older_than):
if (
args.skip_older_than
and start - get_mtime_path(fullpath) > args.skip_older_than
):
continue
# Always add files relative to worktree root
@@ -519,15 +655,17 @@ def main():
else:
dirty = set(git.ls_dirty())
if dirty:
log.warning("WARNING: Modified files in the working directory were ignored."
"\nTo include such files, commit your changes or use --force.")
log.warning(
"WARNING: Modified files in the working directory were ignored."
"\nTo include such files, commit your changes or use --force."
)
filelist -= dirty
# Build dir list to be processed
dirlist = set(os.path.dirname(_) for _ in filelist) if args.dirs else set()
stats['totalfiles'] = stats['files'] = len(filelist)
log.info("{0:,} files to be processed in work dir".format(stats['totalfiles']))
stats["totalfiles"] = stats["files"] = len(filelist)
log.info("{0:,} files to be processed in work dir".format(stats["totalfiles"]))
if not filelist:
# Nothing to do. Exit silently and without errors, just like git does
@@ -544,10 +682,18 @@ def main():
if args.missing and not args.merge:
filterlist = list(filelist)
missing = len(filterlist)
log.info("{0:,} files not found in log, trying merge commits".format(missing))
log.info(
"{0:,} files not found in log, trying merge commits".format(missing)
)
for i in range(0, missing, STEPMISSING):
parse_log(filelist, dirlist, stats, git,
merge=True, filterlist=filterlist[i:i + STEPMISSING])
parse_log(
filelist,
dirlist,
stats,
git,
merge=True,
filterlist=filterlist[i : i + STEPMISSING],
)
# Still missing some?
for file in filelist:
@@ -556,29 +702,33 @@ def main():
# Final statistics
# Suggestion: use git-log --before=mtime to brag about skipped log entries
def log_info(msg, *a, width=13):
ifmt = '{:%d,}' % (width,) # not using 'n' for consistency with ffmt
ffmt = '{:%d,.2f}' % (width,)
ifmt = "{:%d,}" % (width,) # not using 'n' for consistency with ffmt
ffmt = "{:%d,.2f}" % (width,)
# %-formatting lacks a thousand separator, must pre-render with .format()
log.info(msg.replace('%d', ifmt).replace('%f', ffmt).format(*a))
log.info(msg.replace("%d", ifmt).replace("%f", ffmt).format(*a))
log_info(
"Statistics:\n"
"%f seconds\n"
"%d log lines processed\n"
"%d commits evaluated",
time.time() - start, stats['loglines'], stats['commits'])
"Statistics:\n%f seconds\n%d log lines processed\n%d commits evaluated",
time.time() - start,
stats["loglines"],
stats["commits"],
)
if args.dirs:
if stats['direrrors']: log_info("%d directory update errors", stats['direrrors'])
log_info("%d directories updated", stats['dirtouches'])
if stats["direrrors"]:
log_info("%d directory update errors", stats["direrrors"])
log_info("%d directories updated", stats["dirtouches"])
if stats['touches'] != stats['totalfiles']:
log_info("%d files", stats['totalfiles'])
if stats['skip']: log_info("%d files skipped", stats['skip'])
if stats['files']: log_info("%d files missing", stats['files'])
if stats['errors']: log_info("%d file update errors", stats['errors'])
if stats["touches"] != stats["totalfiles"]:
log_info("%d files", stats["totalfiles"])
if stats["skip"]:
log_info("%d files skipped", stats["skip"])
if stats["files"]:
log_info("%d files missing", stats["files"])
if stats["errors"]:
log_info("%d file update errors", stats["errors"])
log_info("%d files updated", stats['touches'])
log_info("%d files updated", stats["touches"])
if args.test:
log.info("TEST RUN - No files modified!")

View File

@@ -1,6 +0,0 @@
"NotIn": "not in",
- `/checkin`: Check-in
docs/docs/integrations/providers/trulens.mdx
self.assertIn(
from trulens_eval import Tru
tru = Tru()

View File

@@ -1,4 +1,5 @@
name: '🚀 Integration Tests'
run-name: 'Test ${{ inputs.working-directory }} on Python ${{ inputs.python-version }}'
on:
workflow_dispatch:
@@ -11,6 +12,7 @@ on:
required: true
type: string
description: "Python version to use"
default: "3.11"
permissions:
contents: read
@@ -24,7 +26,7 @@ jobs:
run:
working-directory: ${{ inputs.working-directory }}
runs-on: ubuntu-latest
name: '🚀 Integration Tests (Python ${{ inputs.python-version }})'
name: 'Python ${{ inputs.python-version }}'
steps:
- uses: actions/checkout@v4

View File

@@ -1,5 +1,5 @@
name: '🚀 Package Release'
run-name: '🚀 Release ${{ inputs.working-directory }} by @${{ github.actor }}'
run-name: 'Release ${{ inputs.working-directory }} ${{ inputs.release-version }}'
on:
workflow_call:
inputs:
@@ -14,6 +14,11 @@ on:
type: string
description: "From which folder this pipeline executes"
default: 'libs/langchain'
release-version:
required: true
type: string
default: '0.1.0'
description: "New version of package being released"
dangerous-nonmaster-release:
required: false
type: boolean
@@ -111,7 +116,7 @@ jobs:
# Look for the latest release of the same base version
REGEX="^$PKG_NAME==$BASE_VERSION\$"
PREV_TAG=$(git tag --sort=-creatordate | (grep -P "$REGEX" || true) | head -1)
# If no exact base version match, look for the latest release of any kind
if [ -z "$PREV_TAG" ]; then
REGEX="^$PKG_NAME==\\d+\\.\\d+\\.\\d+\$"
@@ -122,7 +127,7 @@ jobs:
PREV_TAG="$PKG_NAME==${VERSION%.*}.$(( ${VERSION##*.} - 1 ))"; [[ "${VERSION##*.}" -eq 0 ]] && PREV_TAG=""
# backup case if releasing e.g. 0.3.0, looks up last release
# note if last release (chronologically) was e.g. 0.1.47 it will get
# note if last release (chronologically) was e.g. 0.1.47 it will get
# that instead of the last 0.2 release
if [ -z "$PREV_TAG" ]; then
REGEX="^$PKG_NAME==\\d+\\.\\d+\\.\\d+\$"
@@ -383,11 +388,12 @@ jobs:
- name: Test against ${{ matrix.partner }}
if: startsWith(inputs.working-directory, 'libs/core')
run: |
# Identify latest tag
# Identify latest tag, excluding pre-releases
LATEST_PACKAGE_TAG="$(
git ls-remote --tags origin "langchain-${{ matrix.partner }}*" \
| awk '{print $2}' \
| sed 's|refs/tags/||' \
| grep -Ev '==[^=]*(\.?dev[0-9]*|\.?rc[0-9]*)$' \
| sort -Vr \
| head -n 1
)"
@@ -484,7 +490,7 @@ jobs:
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Create Tag
uses: ncipollo/release-action@v1
with:

View File

@@ -79,4 +79,4 @@ jobs:
# grep will exit non-zero if the target message isn't found,
# and `set -e` above will cause the step to fail.
echo "$STATUS" | grep 'nothing to commit, working tree clean'

View File

@@ -64,4 +64,4 @@ jobs:
# grep will exit non-zero if the target message isn't found,
# and `set -e` above will cause the step to fail.
echo "$STATUS" | grep 'nothing to commit, working tree clean'
echo "$STATUS" | grep 'nothing to commit, working tree clean'

View File

@@ -1,4 +1,5 @@
name: '📚 API Documentation Build'
name: '📚 API Docs'
run-name: 'Build & Deploy API Reference'
# Runs daily or can be triggered manually for immediate updates
on:
@@ -51,7 +52,6 @@ jobs:
run: |
# Get unique repositories
REPOS=$(echo "$REPOS_UNSORTED" | sort -u)
# Checkout each unique repository
for repo in $REPOS; do
# Validate repository format (allow any org with proper format)
@@ -59,15 +59,14 @@ jobs:
echo "Error: Invalid repository format: $repo"
exit 1
fi
REPO_NAME=$(echo $repo | cut -d'/' -f2)
# Additional validation for repo name
if [[ ! "$REPO_NAME" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
echo "Error: Invalid repository name: $REPO_NAME"
exit 1
fi
echo "Checking out $repo to $REPO_NAME"
git clone --depth 1 https://github.com/$repo.git $REPO_NAME
done

View File

@@ -30,6 +30,7 @@ jobs:
build:
name: 'Detect Changes & Set Matrix'
runs-on: ubuntu-latest
if: ${{ !contains(github.event.pull_request.labels.*.name, 'ci-ignore') }}
steps:
- name: '📋 Checkout Code'
uses: actions/checkout@v4

View File

@@ -20,6 +20,7 @@ jobs:
codspeed:
name: 'Benchmark'
runs-on: ubuntu-latest
if: ${{ !contains(github.event.pull_request.labels.*.name, 'codspeed-ignore') }}
strategy:
matrix:
include:

View File

@@ -1,5 +1,6 @@
name: '👥 LangChain People'
run-name: 'Update People Data'
# This workflow updates the LangChain People data by fetching the latest information from the LangChain Git
on:
schedule:
- cron: "0 14 1 * *"

View File

@@ -1,5 +1,5 @@
name: '📝 Run Documentation Notebooks'
name: '📓 Validate Documentation Notebooks'
run-name: 'Test notebooks in ${{ inputs.working-directory }}'
on:
workflow_dispatch:
inputs:

View File

@@ -1,4 +1,5 @@
name: '⏰ Scheduled Integration Tests'
run-name: "Run Integration Tests - ${{ inputs.working-directory-force || 'all libs' }} (Python ${{ inputs.python-version-force || '3.9, 3.11' }})"
on:
workflow_dispatch: # Allows maintainers to trigger the workflow manually in GitHub UI
@@ -161,7 +162,7 @@ jobs:
- name: '🧹 Clean up External Libraries'
# Clean up external libraries to avoid affecting git status check
run: |
run: |
rm -rf \
langchain/libs/partners/google-genai \
langchain/libs/partners/google-vertexai \

View File

@@ -11,4 +11,4 @@
"MD046": {
"style": "fenced"
}
}
}

View File

@@ -21,7 +21,7 @@
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.organizeImports.ruff": "explicit",
"source.fixAll": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
@@ -77,4 +77,6 @@
"editor.tabSize": 2,
"editor.insertSpaces": true
},
"python.terminal.activateEnvironment": false,
"python.defaultInterpreterPath": "./.venv/bin/python"
}

325
CLAUDE.md Normal file
View File

@@ -0,0 +1,325 @@
# Global Development Guidelines for LangChain Projects
## Core Development Principles
### 1. Maintain Stable Public Interfaces ⚠️ CRITICAL
**Always attempt to preserve function signatures, argument positions, and names for exported/public methods.**
**Bad - Breaking Change:**
```python
def get_user(id, verbose=False): # Changed from `user_id`
pass
```
**Good - Stable Interface:**
```python
def get_user(user_id: str, verbose: bool = False) -> User:
"""Retrieve user by ID with optional verbose output."""
pass
```
**Before making ANY changes to public APIs:**
- Check if the function/class is exported in `__init__.py`
- Look for existing usage patterns in tests and examples
- Use keyword-only arguments for new parameters: `*, new_param: str = "default"`
- Mark experimental features clearly with docstring warnings (using reStructuredText, like `.. warning::`)
🧠 *Ask yourself:* "Would this change break someone's code if they used it last week?"
### 2. Code Quality Standards
**All Python code MUST include type hints and return types.**
**Bad:**
```python
def p(u, d):
return [x for x in u if x not in d]
```
**Good:**
```python
def filter_unknown_users(users: list[str], known_users: set[str]) -> list[str]:
"""Filter out users that are not in the known users set.
Args:
users: List of user identifiers to filter.
known_users: Set of known/valid user identifiers.
Returns:
List of users that are not in the known_users set.
"""
return [user for user in users if user not in known_users]
```
**Style Requirements:**
- Use descriptive, **self-explanatory variable names**. Avoid overly short or cryptic identifiers.
- Attempt to break up complex functions (>20 lines) into smaller, focused functions where it makes sense
- Avoid unnecessary abstraction or premature optimization
- Follow existing patterns in the codebase you're modifying
### 3. Testing Requirements
**Every new feature or bugfix MUST be covered by unit tests.**
**Test Organization:**
- Unit tests: `tests/unit_tests/` (no network calls allowed)
- Integration tests: `tests/integration_tests/` (network calls permitted)
- Use `pytest` as the testing framework
**Test Quality Checklist:**
- [ ] Tests fail when your new logic is broken
- [ ] Happy path is covered
- [ ] Edge cases and error conditions are tested
- [ ] Use fixtures/mocks for external dependencies
- [ ] Tests are deterministic (no flaky tests)
Checklist questions:
- [ ] Does the test suite fail if your new logic is broken?
- [ ] Are all expected behaviors exercised (happy path, invalid input, etc)?
- [ ] Do tests use fixtures or mocks where needed?
```python
def test_filter_unknown_users():
"""Test filtering unknown users from a list."""
users = ["alice", "bob", "charlie"]
known_users = {"alice", "bob"}
result = filter_unknown_users(users, known_users)
assert result == ["charlie"]
assert len(result) == 1
```
### 4. Security and Risk Assessment
**Security Checklist:**
- No `eval()`, `exec()`, or `pickle` on user-controlled input
- Proper exception handling (no bare `except:`) and use a `msg` variable for error messages
- Remove unreachable/commented code before committing
- Race conditions or resource leaks (file handles, sockets, threads).
- Ensure proper resource cleanup (file handles, connections)
**Bad:**
```python
def load_config(path):
with open(path) as f:
return eval(f.read()) # ⚠️ Never eval config
```
**Good:**
```python
import json
def load_config(path: str) -> dict:
with open(path) as f:
return json.load(f)
```
### 5. Documentation Standards
**Use Google-style docstrings with Args section for all public functions.**
**Insufficient Documentation:**
```python
def send_email(to, msg):
"""Send an email to a recipient."""
```
**Complete Documentation:**
```python
def send_email(to: str, msg: str, *, priority: str = "normal") -> bool:
"""
Send an email to a recipient with specified priority.
Args:
to: The email address of the recipient.
msg: The message body to send.
priority: Email priority level (``'low'``, ``'normal'``, ``'high'``).
Returns:
True if email was sent successfully, False otherwise.
Raises:
InvalidEmailError: If the email address format is invalid.
SMTPConnectionError: If unable to connect to email server.
"""
```
**Documentation Guidelines:**
- Types go in function signatures, NOT in docstrings
- Focus on "why" rather than "what" in descriptions
- Document all parameters, return values, and exceptions
- Keep descriptions concise but clear
- Use reStructuredText for docstrings to enable rich formatting
📌 *Tip:* Keep descriptions concise but clear. Only document return values if non-obvious.
### 6. Architectural Improvements
**When you encounter code that could be improved, suggest better designs:**
**Poor Design:**
```python
def process_data(data, db_conn, email_client, logger):
# Function doing too many things
validated = validate_data(data)
result = db_conn.save(validated)
email_client.send_notification(result)
logger.log(f"Processed {len(data)} items")
return result
```
**Better Design:**
```python
@dataclass
class ProcessingResult:
"""Result of data processing operation."""
items_processed: int
success: bool
errors: List[str] = field(default_factory=list)
class DataProcessor:
"""Handles data validation, storage, and notification."""
def __init__(self, db_conn: Database, email_client: EmailClient):
self.db = db_conn
self.email = email_client
def process(self, data: List[dict]) -> ProcessingResult:
"""Process and store data with notifications."""
validated = self._validate_data(data)
result = self.db.save(validated)
self._notify_completion(result)
return result
```
**Design Improvement Areas:**
If there's a **cleaner**, **more scalable**, or **simpler** design, highlight it and suggest improvements that would:
- Reduce code duplication through shared utilities
- Make unit testing easier
- Improve separation of concerns (single responsibility)
- Make unit testing easier through dependency injection
- Add clarity without adding complexity
- Prefer dataclasses for structured data
## Development Tools & Commands
### Package Management
```bash
# Add package
uv add package-name
# Sync project dependencies
uv sync
uv lock
```
### Testing
```bash
# Run unit tests (no network)
make test
# Don't run integration tests, as API keys must be set
# Run specific test file
uv run --group test pytest tests/unit_tests/test_specific.py
```
### Code Quality
```bash
# Lint code
make lint
# Format code
make format
# Type checking
uv run --group lint mypy .
```
### Dependency Management Patterns
**Local Development Dependencies:**
```toml
[tool.uv.sources]
langchain-core = { path = "../core", editable = true }
langchain-tests = { path = "../standard-tests", editable = true }
```
**For tools, use the `@tool` decorator from `langchain_core.tools`:**
```python
from langchain_core.tools import tool
@tool
def search_database(query: str) -> str:
"""Search the database for relevant information.
Args:
query: The search query string.
"""
# Implementation here
return results
```
## Commit Standards
**Use Conventional Commits format for PR titles:**
- `feat(core): add multi-tenant support`
- `fix(cli): resolve flag parsing error`
- `docs: update API usage examples`
- `docs(openai): update API usage examples`
## Framework-Specific Guidelines
- Follow the existing patterns in `langchain-core` for base abstractions
- Use `langchain_core.callbacks` for execution tracking
- Implement proper streaming support where applicable
- Avoid deprecated components like legacy `LLMChain`
### Partner Integrations
- Follow the established patterns in existing partner libraries
- Implement standard interfaces (`BaseChatModel`, `BaseEmbeddings`, etc.)
- Include comprehensive integration tests
- Document API key requirements and authentication
---
## Quick Reference Checklist
Before submitting code changes:
- [ ] **Breaking Changes**: Verified no public API changes
- [ ] **Type Hints**: All functions have complete type annotations
- [ ] **Tests**: New functionality is fully tested
- [ ] **Security**: No dangerous patterns (eval, silent failures, etc.)
- [ ] **Documentation**: Google-style docstrings for public functions
- [ ] **Code Quality**: `make lint` and `make format` pass
- [ ] **Architecture**: Suggested improvements where applicable
- [ ] **Commit Message**: Follows Conventional Commits format

View File

@@ -15,7 +15,7 @@
[![GitHub star chart](https://img.shields.io/github/stars/langchain-ai/langchain?style=flat-square)](https://star-history.com/#langchain-ai/langchain)
[![Open Issues](https://img.shields.io/github/issues-raw/langchain-ai/langchain?style=flat-square)](https://github.com/langchain-ai/langchain/issues)
[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode&style=flat-square)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/langchain-ai/langchain)
[<img src="https://github.com/codespaces/badge.svg" title="Open in Github Codespace" width="150" height="20">](https://codespaces.new/langchain-ai/langchain)
[<img src="https://github.com/codespaces/badge.svg" alt="Open in Github Codespace" title="Open in Github Codespace" width="150" height="20">](https://codespaces.new/langchain-ai/langchain)
[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchainai.svg?style=social&label=Follow%20%40LangChainAI)](https://twitter.com/langchainai)
[![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/langchain-ai/langchain)

View File

@@ -32,7 +32,7 @@ LangChain is partnered with [huntr by Protect AI](https://huntr.com/) to provide
a bounty program for our open source projects.
Please report security vulnerabilities associated with the LangChain
open source projects [here](https://huntr.com/bounties/disclose/?target=https%3A%2F%2Fgithub.com%2Flangchain-ai%2Flangchain&validSearch=true).
open source projects at [huntr](https://huntr.com/bounties/disclose/?target=https%3A%2F%2Fgithub.com%2Flangchain-ai%2Flangchain&validSearch=true).
Before reporting a vulnerability, please review:

View File

@@ -144,7 +144,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"id": "kWDWfSDBMPl8",
"metadata": {},
"outputs": [
@@ -185,7 +185,7 @@
" )\n",
" # Text summary chain\n",
" model = VertexAI(\n",
" temperature=0, model_name=\"gemini-2.0-flash-lite-001\", max_tokens=1024\n",
" temperature=0, model_name=\"gemini-2.5-flash\", max_tokens=1024\n",
" ).with_fallbacks([empty_response])\n",
" summarize_chain = {\"element\": lambda x: x} | prompt | model | StrOutputParser()\n",
"\n",
@@ -235,7 +235,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"id": "PeK9bzXv3olF",
"metadata": {},
"outputs": [],
@@ -254,7 +254,7 @@
"\n",
"def image_summarize(img_base64, prompt):\n",
" \"\"\"Make image summary\"\"\"\n",
" model = ChatVertexAI(model=\"gemini-2.0-flash\", max_tokens=1024)\n",
" model = ChatVertexAI(model=\"gemini-2.5-flash\", max_tokens=1024)\n",
"\n",
" msg = model.invoke(\n",
" [\n",
@@ -431,7 +431,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"id": "GlwCErBaCKQW",
"metadata": {},
"outputs": [],
@@ -553,7 +553,7 @@
" \"\"\"\n",
"\n",
" # Multi-modal LLM\n",
" model = ChatVertexAI(temperature=0, model_name=\"gemini-2.0-flash\", max_tokens=1024)\n",
" model = ChatVertexAI(temperature=0, model_name=\"gemini-2.5-flash\", max_tokens=1024)\n",
"\n",
" # RAG pipeline\n",
" chain = (\n",

View File

@@ -63,4 +63,4 @@ Notebook | Description
[rag-locally-on-intel-cpu.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/rag-locally-on-intel-cpu.ipynb) | Perform Retrieval-Augmented-Generation (RAG) on locally downloaded open-source models using langchain and open source tools and execute it on Intel Xeon CPU. We showed an example of how to apply RAG on Llama 2 model and enable it to answer the queries related to Intel Q1 2024 earnings release.
[visual_RAG_vdms.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/visual_RAG_vdms.ipynb) | Performs Visual Retrieval-Augmented-Generation (RAG) using videos and scene descriptions generated by open source models.
[contextual_rag.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/contextual_rag.ipynb) | Performs contextual retrieval-augmented generation (RAG) prepending chunk-specific explanatory context to each chunk before embedding.
[rag-agents-locally-on-intel-cpu.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/local_rag_agents_intel_cpu.ipynb) | Build a RAG agent locally with open source models that routes questions through one of two paths to find answers. The agent generates answers based on documents retrieved from either the vector database or retrieved from web search. If the vector database lacks relevant information, the agent opts for web search. Open-source models for LLM and embeddings are used locally on an Intel Xeon CPU to execute this pipeline.
[rag-agents-locally-on-intel-cpu.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/local_rag_agents_intel_cpu.ipynb) | Build a RAG agent locally with open source models that routes questions through one of two paths to find answers. The agent generates answers based on documents retrieved from either the vector database or retrieved from web search. If the vector database lacks relevant information, the agent opts for web search. Open-source models for LLM and embeddings are used locally on an Intel Xeon CPU to execute this pipeline.

View File

@@ -34,7 +34,7 @@
"tools = [multiply, exponentiate, add]\n",
"\n",
"gpt35 = ChatOpenAI(model=\"gpt-3.5-turbo-0125\", temperature=0).bind_tools(tools)\n",
"claude3 = ChatAnthropic(model=\"claude-3-sonnet-20240229\").bind_tools(tools)\n",
"claude3 = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\").bind_tools(tools)\n",
"llm_with_tools = gpt35.configurable_alternatives(\n",
" ConfigurableField(id=\"llm\"), default_key=\"gpt35\", claude3=claude3\n",
")"
@@ -113,14 +113,15 @@
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content=\"what's 3 plus 5 raised to the 2.743. also what's 17.24 - 918.1241\"),\n",
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_6yMU2WsS4Bqgi1WxFHxtfJRc', 'function': {'arguments': '{\"x\": 8, \"y\": 2.743}', 'name': 'exponentiate'}, 'type': 'function'}, {'id': 'call_GAL3dQiKFF9XEV0RrRLPTvVp', 'function': {'arguments': '{\"x\": 17.24, \"y\": -918.1241}', 'name': 'add'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 58, 'prompt_tokens': 168, 'total_tokens': 226}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': 'fp_b28b39ffa8', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-528302fc-7acf-4c11-82c4-119ccf40c573-0', tool_calls=[{'name': 'exponentiate', 'args': {'x': 8, 'y': 2.743}, 'id': 'call_6yMU2WsS4Bqgi1WxFHxtfJRc'}, {'name': 'add', 'args': {'x': 17.24, 'y': -918.1241}, 'id': 'call_GAL3dQiKFF9XEV0RrRLPTvVp'}]),\n",
" ToolMessage(content='300.03770462067547', tool_call_id='call_6yMU2WsS4Bqgi1WxFHxtfJRc'),\n",
" ToolMessage(content='-900.8841', tool_call_id='call_GAL3dQiKFF9XEV0RrRLPTvVp'),\n",
" AIMessage(content='The result of \\\\(3 + 5^{2.743}\\\\) is approximately 300.04, and the result of \\\\(17.24 - 918.1241\\\\) is approximately -900.88.', response_metadata={'token_usage': {'completion_tokens': 44, 'prompt_tokens': 251, 'total_tokens': 295}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': 'fp_b28b39ffa8', 'finish_reason': 'stop', 'logprobs': None}, id='run-d1161669-ed09-4b18-94bd-6d8530df5aa8-0')]}"
"{'messages': [HumanMessage(content=\"what's 3 plus 5 raised to the 2.743. also what's 17.24 - 918.1241\", additional_kwargs={}, response_metadata={}),\n",
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_xuNXwm2P6U2Pp2pAbC1sdIBz', 'function': {'arguments': '{\"x\": 3, \"y\": 5}', 'name': 'add'}, 'type': 'function'}, {'id': 'call_0pImUJUDlYa5zfBcxxuvWyYS', 'function': {'arguments': '{\"x\": 8, \"y\": 2.743}', 'name': 'exponentiate'}, 'type': 'function'}, {'id': 'call_yaownQ9TZK0dkqD1KSFyax4H', 'function': {'arguments': '{\"x\": 17.24, \"y\": -918.1241}', 'name': 'add'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 75, 'prompt_tokens': 131, 'total_tokens': 206, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'id': 'chatcmpl-ByJm2qxSWU3oTTSZQv64J4XQKZhA6', 'service_tier': 'default', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--35fad027-47f7-44d3-aa8b-99f4fc24098c-0', tool_calls=[{'name': 'add', 'args': {'x': 3, 'y': 5}, 'id': 'call_xuNXwm2P6U2Pp2pAbC1sdIBz', 'type': 'tool_call'}, {'name': 'exponentiate', 'args': {'x': 8, 'y': 2.743}, 'id': 'call_0pImUJUDlYa5zfBcxxuvWyYS', 'type': 'tool_call'}, {'name': 'add', 'args': {'x': 17.24, 'y': -918.1241}, 'id': 'call_yaownQ9TZK0dkqD1KSFyax4H', 'type': 'tool_call'}], usage_metadata={'input_tokens': 131, 'output_tokens': 75, 'total_tokens': 206, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}),\n",
" ToolMessage(content='8.0', tool_call_id='call_xuNXwm2P6U2Pp2pAbC1sdIBz'),\n",
" ToolMessage(content='300.03770462067547', tool_call_id='call_0pImUJUDlYa5zfBcxxuvWyYS'),\n",
" ToolMessage(content='-900.8841', tool_call_id='call_yaownQ9TZK0dkqD1KSFyax4H'),\n",
" AIMessage(content='The results are:\\n1. 3 plus 5 is 8.\\n2. 5 raised to the power of 2.743 is approximately 300.04.\\n3. 17.24 minus 918.1241 is approximately -900.88.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 55, 'prompt_tokens': 236, 'total_tokens': 291, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'id': 'chatcmpl-ByJm345MYnpowGS90iAZAlSs7haed', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--5fa66d47-d80e-45d0-9c32-31348c735d72-0', usage_metadata={'input_tokens': 236, 'output_tokens': 55, 'total_tokens': 291, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}"
]
},
"execution_count": 4,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -146,17 +147,17 @@
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content=\"what's 3 plus 5 raised to the 2.743. also what's 17.24 - 918.1241\"),\n",
" AIMessage(content=[{'text': \"Okay, let's break this down into two parts:\", 'type': 'text'}, {'id': 'toolu_01DEhqcXkXTtzJAiZ7uMBeDC', 'input': {'x': 3, 'y': 5}, 'name': 'add', 'type': 'tool_use'}], response_metadata={'id': 'msg_01AkLGH8sxMHaH15yewmjwkF', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'input_tokens': 450, 'output_tokens': 81}}, id='run-f35bfae8-8ded-4f8a-831b-0940d6ad16b6-0', tool_calls=[{'name': 'add', 'args': {'x': 3, 'y': 5}, 'id': 'toolu_01DEhqcXkXTtzJAiZ7uMBeDC'}]),\n",
" ToolMessage(content='8.0', tool_call_id='toolu_01DEhqcXkXTtzJAiZ7uMBeDC'),\n",
" AIMessage(content=[{'id': 'toolu_013DyMLrvnrto33peAKMGMr1', 'input': {'x': 8.0, 'y': 2.743}, 'name': 'exponentiate', 'type': 'tool_use'}], response_metadata={'id': 'msg_015Fmp8aztwYcce2JDAFfce3', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'input_tokens': 545, 'output_tokens': 75}}, id='run-48aaeeeb-a1e5-48fd-a57a-6c3da2907b47-0', tool_calls=[{'name': 'exponentiate', 'args': {'x': 8.0, 'y': 2.743}, 'id': 'toolu_013DyMLrvnrto33peAKMGMr1'}]),\n",
" ToolMessage(content='300.03770462067547', tool_call_id='toolu_013DyMLrvnrto33peAKMGMr1'),\n",
" AIMessage(content=[{'text': 'So 3 plus 5 raised to the 2.743 power is 300.04.\\n\\nFor the second part:', 'type': 'text'}, {'id': 'toolu_01UTmMrGTmLpPrPCF1rShN46', 'input': {'x': 17.24, 'y': -918.1241}, 'name': 'add', 'type': 'tool_use'}], response_metadata={'id': 'msg_015TkhfRBENPib2RWAxkieH6', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'input_tokens': 638, 'output_tokens': 105}}, id='run-45fb62e3-d102-4159-881d-241c5dbadeed-0', tool_calls=[{'name': 'add', 'args': {'x': 17.24, 'y': -918.1241}, 'id': 'toolu_01UTmMrGTmLpPrPCF1rShN46'}]),\n",
" ToolMessage(content='-900.8841', tool_call_id='toolu_01UTmMrGTmLpPrPCF1rShN46'),\n",
" AIMessage(content='Therefore, 17.24 - 918.1241 = -900.8841', response_metadata={'id': 'msg_01LgKnRuUcSyADCpxv9tPoYD', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 759, 'output_tokens': 24}}, id='run-1008254e-ccd1-497c-8312-9550dd77bd08-0')]}"
"{'messages': [HumanMessage(content=\"what's 3 plus 5 raised to the 2.743. also what's 17.24 - 918.1241\", additional_kwargs={}, response_metadata={}),\n",
" AIMessage(content=[{'text': \"I'll solve these calculations for you.\\n\\nFor the first part, I need to calculate 3 plus 5 raised to the power of 2.743.\\n\\nLet me break this down:\\n1) First, I'll calculate 5 raised to the power of 2.743\\n2) Then add 3 to the result\", 'type': 'text'}, {'id': 'toolu_01L1mXysBQtpPLQ2AZTaCGmE', 'input': {'x': 5, 'y': 2.743}, 'name': 'exponentiate', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_01HCbDmuzdg9ATMyKbnecbEE', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 563, 'output_tokens': 146, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--9f6469fb-bcbb-4c1c-9eec-79f6979c38e6-0', tool_calls=[{'name': 'exponentiate', 'args': {'x': 5, 'y': 2.743}, 'id': 'toolu_01L1mXysBQtpPLQ2AZTaCGmE', 'type': 'tool_call'}], usage_metadata={'input_tokens': 563, 'output_tokens': 146, 'total_tokens': 709, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}),\n",
" ToolMessage(content='82.65606421491815', tool_call_id='toolu_01L1mXysBQtpPLQ2AZTaCGmE'),\n",
" AIMessage(content=[{'text': \"Now I'll add 3 to this result:\", 'type': 'text'}, {'id': 'toolu_01NARC83e9obV35mZ6jYzBiN', 'input': {'x': 3, 'y': 82.65606421491815}, 'name': 'add', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_01ELwyCtVLeGC685PUFqmdz2', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 727, 'output_tokens': 87, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--d5af3d7c-e8b7-4cc2-997a-ad2dafd08751-0', tool_calls=[{'name': 'add', 'args': {'x': 3, 'y': 82.65606421491815}, 'id': 'toolu_01NARC83e9obV35mZ6jYzBiN', 'type': 'tool_call'}], usage_metadata={'input_tokens': 727, 'output_tokens': 87, 'total_tokens': 814, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}),\n",
" ToolMessage(content='85.65606421491815', tool_call_id='toolu_01NARC83e9obV35mZ6jYzBiN'),\n",
" AIMessage(content=[{'text': \"For the second part, you asked for 17.24 - 918.1241. I don't have a subtraction function available, but I can rewrite this as adding a negative number: 17.24 + (-918.1241)\", 'type': 'text'}, {'id': 'toolu_01Q6fLcZkBWZpMPCZ55WXR3N', 'input': {'x': 17.24, 'y': -918.1241}, 'name': 'add', 'type': 'tool_use'}], additional_kwargs={}, response_metadata={'id': 'msg_01WkmDwUxWjjaKGnTtdLGJnN', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 832, 'output_tokens': 130, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--39a6fbda-4c81-47a6-b361-524bd4ee5823-0', tool_calls=[{'name': 'add', 'args': {'x': 17.24, 'y': -918.1241}, 'id': 'toolu_01Q6fLcZkBWZpMPCZ55WXR3N', 'type': 'tool_call'}], usage_metadata={'input_tokens': 832, 'output_tokens': 130, 'total_tokens': 962, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}),\n",
" ToolMessage(content='-900.8841', tool_call_id='toolu_01Q6fLcZkBWZpMPCZ55WXR3N'),\n",
" AIMessage(content='So, the answers are:\\n1) 3 plus 5 raised to the 2.743 = 85.65606421491815\\n2) 17.24 - 918.1241 = -900.8841', additional_kwargs={}, response_metadata={'id': 'msg_015Yoc62CvdJbANGFouiQ6AQ', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 978, 'output_tokens': 58, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--174c0882-6180-47ea-8f63-d7b747302327-0', usage_metadata={'input_tokens': 978, 'output_tokens': 58, 'total_tokens': 1036, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})]}"
]
},
"execution_count": 5,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -177,7 +178,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -191,7 +192,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -97,7 +97,7 @@ def _load_module_members(module_path: str, namespace: str) -> ModuleMembers:
if type(type_) is typing_extensions._TypedDictMeta: # type: ignore
kind: ClassKind = "TypedDict"
elif type(type_) is typing._TypedDictMeta: # type: ignore
kind: ClassKind = "TypedDict"
kind = "TypedDict"
elif (
issubclass(type_, Runnable)
and issubclass(type_, BaseModel)
@@ -189,7 +189,7 @@ def _load_package_modules(
if isinstance(package_directory, str)
else package_directory
)
modules_by_namespace = {}
modules_by_namespace: Dict[str, ModuleMembers] = {}
# Get the high level package name
package_name = package_path.name
@@ -217,7 +217,11 @@ def _load_package_modules(
# Get the full namespace of the module
namespace = str(relative_module_name).replace(".py", "").replace("/", ".")
# Keep only the top level namespace
top_namespace = namespace.split(".")[0]
# (but make special exception for content_blocks and v1.messages)
if namespace == "messages.content_blocks" or namespace == "v1.messages":
top_namespace = namespace # Keep full namespace for content_blocks
else:
top_namespace = namespace.split(".")[0]
try:
# If submodule is present, we need to construct the paths in a slightly
@@ -283,7 +287,7 @@ def _construct_doc(
.. toctree::
:hidden:
:maxdepth: 2
"""
index_autosummary = """
"""
@@ -365,9 +369,9 @@ def _construct_doc(
module_doc += f"""\
:template: {template}
{class_["qualified_name"]}
"""
index_autosummary += f"""
{class_["qualified_name"]}
@@ -550,8 +554,8 @@ def _build_index(dirs: List[str]) -> None:
integrations = sorted(dir_ for dir_ in dirs if dir_ not in main_)
doc = """# LangChain Python API Reference
Welcome to the LangChain Python API reference. This is a reference for all
`langchain-x` packages.
Welcome to the LangChain Python API reference. This is a reference for all
`langchain-x` packages.
For user guides see [https://python.langchain.com](https://python.langchain.com).

View File

@@ -1,10 +1,10 @@
# arXiv
LangChain implements the latest research in the field of Natural Language Processing.
This page contains `arXiv` papers referenced in the LangChain Documentation, API Reference,
Templates, and Cookbooks.
From the opposite direction, scientists use `LangChain` in research and reference it in the research papers.
From the opposite direction, scientists use `LangChain` in research and reference it in the research papers.
`arXiv` papers with references to:
[LangChain](https://arxiv.org/search/?query=langchain&searchtype=all&source=header) | [LangGraph](https://arxiv.org/search/?query=langgraph&searchtype=all&source=header) | [LangSmith](https://arxiv.org/search/?query=langsmith&searchtype=all&source=header)
@@ -83,7 +83,7 @@ a set of open-domain QA datasets, covering multiple query complexities, and
show that ours enhances the overall efficiency and accuracy of QA systems,
compared to relevant baselines including the adaptive retrieval approaches.
Code is available at: https://github.com/starsuzi/Adaptive-RAG.
## Self-Discover: Large Language Models Self-Compose Reasoning Structures
- **Authors:** Pei Zhou, Jay Pujara, Xiang Ren, et al.
@@ -106,7 +106,7 @@ than 20%, while requiring 10-40x fewer inference compute. Finally, we show that
the self-discovered reasoning structures are universally applicable across
model families: from PaLM 2-L to GPT-4, and from GPT-4 to Llama2, and share
commonalities with human reasoning patterns.
## RAG-Fusion: a New Take on Retrieval-Augmented Generation
- **Authors:** Zackary Rackauckas
@@ -129,7 +129,7 @@ the generated queries' relevance to the original query is insufficient. This
research marks significant progress in artificial intelligence (AI) and natural
language processing (NLP) applications and demonstrates transformations in a
global and multi-industry context.
## RAPTOR: Recursive Abstractive Processing for Tree-Organized Retrieval
- **Authors:** Parth Sarthi, Salman Abdullah, Aditi Tuli, et al.
@@ -152,7 +152,7 @@ tasks. On question-answering tasks that involve complex, multi-step reasoning,
we show state-of-the-art results; for example, by coupling RAPTOR retrieval
with the use of GPT-4, we can improve the best performance on the QuALITY
benchmark by 20% in absolute accuracy.
## Corrective Retrieval Augmented Generation
- **Authors:** Shi-Qi Yan, Jia-Chen Gu, Yun Zhu, et al.
@@ -180,7 +180,7 @@ them. CRAG is plug-and-play and can be seamlessly coupled with various
RAG-based approaches. Experiments on four datasets covering short- and
long-form generation tasks show that CRAG can significantly improve the
performance of RAG-based approaches.
## Code Generation with AlphaCodium: From Prompt Engineering to Flow Engineering
- **Authors:** Tal Ridnik, Dedy Kredo, Itamar Friedman
@@ -206,7 +206,7 @@ to 44% with the AlphaCodium flow. Many of the principles and best practices
acquired in this work, we believe, are broadly applicable to general code
generation tasks. Full implementation is available at:
https://github.com/Codium-ai/AlphaCodium
## Mixtral of Experts
- **Authors:** Albert Q. Jiang, Alexandre Sablayrolles, Antoine Roux, et al.
@@ -229,7 +229,7 @@ multilingual benchmarks. We also provide a model fine-tuned to follow
instructions, Mixtral 8x7B - Instruct, that surpasses GPT-3.5 Turbo,
Claude-2.1, Gemini Pro, and Llama 2 70B - chat model on human benchmarks. Both
the base and instruct models are released under the Apache 2.0 license.
## Dense X Retrieval: What Retrieval Granularity Should We Use?
- **Authors:** Tong Chen, Hongwei Wang, Sihao Chen, et al.
@@ -255,7 +255,7 @@ also enhances the performance of downstream QA tasks, since the retrieved texts
are more condensed with question-relevant information, reducing the need for
lengthy input tokens and minimizing the inclusion of extraneous, irrelevant
information.
## Chain-of-Note: Enhancing Robustness in Retrieval-Augmented Language Models
- **Authors:** Wenhao Yu, Hongming Zhang, Xiaoman Pan, et al.
@@ -286,7 +286,7 @@ with CoN significantly outperform standard RALMs. Notably, CoN achieves an
average improvement of +7.9 in EM score given entirely noisy retrieved
documents and +10.5 in rejection rates for real-time questions that fall
outside the pre-training knowledge scope.
## Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection
- **Authors:** Akari Asai, Zeqiu Wu, Yizhong Wang, et al.
@@ -317,7 +317,7 @@ outperforms ChatGPT and retrieval-augmented Llama2-chat on Open-domain QA,
reasoning and fact verification tasks, and it shows significant gains in
improving factuality and citation accuracy for long-form generations relative
to these models.
## Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models
- **Authors:** Huaixiu Steven Zheng, Swaroop Mishra, Xinyun Chen, et al.
@@ -338,7 +338,7 @@ substantial performance gains on various challenging reasoning-intensive tasks
including STEM, Knowledge QA, and Multi-Hop Reasoning. For instance, Step-Back
Prompting improves PaLM-2L performance on MMLU (Physics and Chemistry) by 7%
and 11% respectively, TimeQA by 27%, and MuSiQue by 7%.
## Skeleton-of-Thought: Prompting LLMs for Efficient Parallel Generation
- **Authors:** Xuefei Ning, Zinan Lin, Zixuan Zhou, et al.
@@ -359,7 +359,7 @@ potentially improve the answer quality on several question categories. SoT is
an initial attempt at data-centric optimization for inference efficiency, and
showcases the potential of eliciting high-quality answers by explicitly
planning the answer structure in language.
## Llama 2: Open Foundation and Fine-Tuned Chat Models
- **Authors:** Hugo Touvron, Louis Martin, Kevin Stone, et al.
@@ -377,7 +377,7 @@ safety, may be a suitable substitute for closed-source models. We provide a
detailed description of our approach to fine-tuning and safety improvements of
Llama 2-Chat in order to enable the community to build on our work and
contribute to the responsible development of LLMs.
## Lost in the Middle: How Language Models Use Long Contexts
- **Authors:** Nelson F. Liu, Kevin Lin, John Hewitt, et al.
@@ -399,7 +399,7 @@ significantly degrades when models must access relevant information in the
middle of long contexts, even for explicitly long-context models. Our analysis
provides a better understanding of how language models use their input context
and provides new evaluation protocols for future long-context language models.
## Query Rewriting for Retrieval-Augmented Large Language Models
- **Authors:** Xinbei Ma, Yeyun Gong, Pengcheng He, et al.
@@ -426,7 +426,7 @@ Evaluation is conducted on downstream tasks, open-domain QA and multiple-choice
QA. Experiments results show consistent performance improvement, indicating
that our framework is proven effective and scalable, and brings a new framework
for retrieval-augmented LLM.
## Large Language Model Guided Tree-of-Thought
- **Authors:** Jieyi Long
@@ -452,7 +452,7 @@ the effectiveness of the proposed technique, we implemented a ToT-based solver
for the Sudoku Puzzle. Experimental results show that the ToT framework can
significantly increase the success rate of Sudoku puzzle solving. Our
implementation of the ToT-based Sudoku solver is available on [GitHub](https://github.com/jieyilong/tree-of-thought-puzzle-solver).
## Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models
- **Authors:** Lei Wang, Wanyu Xu, Yihuai Lan, et al.
@@ -482,7 +482,7 @@ by a large margin, is comparable to or exceeds Zero-shot-Program-of-Thought
Prompting, and has comparable performance with 8-shot CoT prompting on the math
reasoning problem. The code can be found at
https://github.com/AGI-Edgerunners/Plan-and-Solve-Prompting.
## Zero-Shot Listwise Document Reranking with a Large Language Model
- **Authors:** Xueguang Ma, Xinyu Zhang, Ronak Pradeep, et al.
@@ -506,7 +506,7 @@ results, but can also act as a final-stage reranker to improve the top-ranked
results of a pointwise method for improved efficiency. Additionally, we apply
our approach to subsets of MIRACL, a recent multilingual retrieval dataset,
with results showing its potential to generalize across different languages.
## Visual Instruction Tuning
- **Authors:** Haotian Liu, Chunyuan Li, Qingyang Wu, et al.
@@ -530,7 +530,7 @@ instruction-following dataset. When fine-tuned on Science QA, the synergy of
LLaVA and GPT-4 achieves a new state-of-the-art accuracy of 92.53%. We make
GPT-4 generated visual instruction tuning data, our model and code base
publicly available.
## Generative Agents: Interactive Simulacra of Human Behavior
- **Authors:** Joon Sung Park, Joseph C. O'Brien, Carrie J. Cai, et al.
@@ -563,7 +563,7 @@ architecture--observation, planning, and reflection--each contribute critically
to the believability of agent behavior. By fusing large language models with
computational, interactive agents, this work introduces architectural and
interaction patterns for enabling believable simulations of human behavior.
## CAMEL: Communicative Agents for "Mind" Exploration of Large Language Model Society
- **Authors:** Guohao Li, Hasan Abed Al Kader Hammoud, Hani Itani, et al.
@@ -590,7 +590,7 @@ include introducing a novel communicative agent framework, offering a scalable
approach for studying the cooperative behaviors and capabilities of multi-agent
systems, and open-sourcing our library to support research on communicative
agents and beyond: https://github.com/camel-ai/camel.
## HuggingGPT: Solving AI Tasks with ChatGPT and its Friends in Hugging Face
- **Authors:** Yongliang Shen, Kaitao Song, Xu Tan, et al.
@@ -619,7 +619,7 @@ HuggingGPT can tackle a wide range of sophisticated AI tasks spanning different
modalities and domains and achieve impressive results in language, vision,
speech, and other challenging tasks, which paves a new way towards the
realization of artificial general intelligence.
## A Watermark for Large Language Models
- **Authors:** John Kirchenbauer, Jonas Geiping, Yuxin Wen, et al.
@@ -641,7 +641,7 @@ interpretable p-values, and derive an information-theoretic framework for
analyzing the sensitivity of the watermark. We test the watermark using a
multi-billion parameter model from the Open Pretrained Transformer (OPT)
family, and discuss robustness and security.
## Precise Zero-Shot Dense Retrieval without Relevance Labels
- **Authors:** Luyu Gao, Xueguang Ma, Jimmy Lin, et al.
@@ -670,7 +670,7 @@ details. Our experiments show that HyDE significantly outperforms the
state-of-the-art unsupervised dense retriever Contriever and shows strong
performance comparable to fine-tuned retrievers, across various tasks (e.g. web
search, QA, fact verification) and languages~(e.g. sw, ko, ja).
## Constitutional AI: Harmlessness from AI Feedback
- **Authors:** Yuntao Bai, Saurav Kadavath, Sandipan Kundu, et al.
@@ -697,7 +697,7 @@ and RL methods can leverage chain-of-thought style reasoning to improve the
human-judged performance and transparency of AI decision making. These methods
make it possible to control AI behavior more precisely and with far fewer human
labels.
## Robust and Explainable Identification of Logical Fallacies in Natural Language Arguments
- **Authors:** Zhivar Sourati, Vishnu Priya Prasanna Venkatesh, Darshan Deshpande, et al.
@@ -727,7 +727,7 @@ components and fallacy classes, indicating that fallacy identification is a
challenging task that may require specialized forms of reasoning to capture
various classes. We share our open-source code and data on GitHub to support
further work on logical fallacy identification.
## Complementary Explanations for Effective In-Context Learning
- **Authors:** Xi Ye, Srinivasan Iyer, Asli Celikyilmaz, et al.
@@ -752,7 +752,7 @@ performance. Therefore, we propose a maximal marginal relevance-based exemplar
selection approach for constructing exemplar sets that are both relevant as
well as complementary, which successfully improves the in-context learning
performance across three real-world tasks on multiple LLMs.
## PAL: Program-aided Language Models
- **Authors:** Luyu Gao, Aman Madaan, Shuyan Zhou, et al.
@@ -784,7 +784,7 @@ larger models. For example, PAL using Codex achieves state-of-the-art few-shot
accuracy on the GSM8K benchmark of math word problems, surpassing PaLM-540B
which uses chain-of-thought by absolute 15% top-1. Our code and data are
publicly available at http://reasonwithpal.com/ .
## An Analysis of Fusion Functions for Hybrid Retrieval
- **Authors:** Sebastian Bruch, Siyu Gai, Amir Ingber
@@ -803,7 +803,7 @@ learning of a CC fusion is generally agnostic to the choice of score
normalization; that CC outperforms RRF in in-domain and out-of-domain settings;
and finally, that CC is sample efficient, requiring only a small set of
training examples to tune its only parameter to a target domain.
## ReAct: Synergizing Reasoning and Acting in Language Models
- **Authors:** Shunyu Yao, Jeffrey Zhao, Dian Yu, et al.
@@ -835,7 +835,7 @@ benchmarks (ALFWorld and WebShop), ReAct outperforms imitation and
reinforcement learning methods by an absolute success rate of 34% and 10%
respectively, while being prompted with only one or two in-context examples.
Project site with code: https://react-lm.github.io
## Deep Lake: a Lakehouse for Deep Learning
- **Authors:** Sasun Hambardzumyan, Abhinav Tuli, Levon Ghukasyan, et al.
@@ -860,7 +860,7 @@ streams the data over the network to (a) Tensor Query Language, (b) in-browser
visualization engine, or (c) deep learning frameworks without sacrificing GPU
utilization. Datasets stored in Deep Lake can be accessed from PyTorch,
TensorFlow, JAX, and integrate with numerous MLOps tools.
## Matryoshka Representation Learning
- **Authors:** Aditya Kusupati, Gantavya Bhatt, Aniket Rege, et al.
@@ -891,7 +891,7 @@ representations. Finally, we show that MRL extends seamlessly to web-scale
datasets (ImageNet, JFT) across various modalities -- vision (ViT, ResNet),
vision + language (ALIGN) and language (BERT). MRL code and pretrained models
are open-sourced at https://github.com/RAIVNLab/MRL.
## Bitext Mining Using Distilled Sentence Representations for Low-Resource Languages
- **Authors:** Kevin Heffernan, Onur Çelebi, Holger Schwenk
@@ -917,7 +917,7 @@ which is valuable in the low-resource setting.
very low-resource languages and handle 50 African languages, many of which are
not covered by any other model. For these languages, we train sentence
encoders, mine bitexts, and validate the bitexts by training NMT systems.
## Evaluating the Text-to-SQL Capabilities of Large Language Models
- **Authors:** Nitarshan Rajkumar, Raymond Li, Dzmitry Bahdanau
@@ -934,7 +934,7 @@ this setting. Furthermore, we demonstrate on the GeoQuery and Scholar
benchmarks that a small number of in-domain examples provided in the prompt
enables Codex to perform better than state-of-the-art models finetuned on such
few-shot examples.
## Locally Typical Sampling
- **Authors:** Clara Meister, Tiago Pimentel, Gian Wiher, et al.
@@ -963,7 +963,7 @@ human evaluations show that, in comparison to nucleus and top-k sampling,
locally typical sampling offers competitive performance (in both abstractive
summarization and story generation) in terms of quality while consistently
reducing degenerate repetitions.
## ColBERTv2: Effective and Efficient Retrieval via Lightweight Late Interaction
- **Authors:** Keshav Santhanam, Omar Khattab, Jon Saad-Falcon, et al.
@@ -985,7 +985,7 @@ improve the quality and space footprint of late interaction. We evaluate
ColBERTv2 across a wide range of benchmarks, establishing state-of-the-art
quality within and outside the training domain while reducing the space
footprint of late interaction models by 6--10$\times$.
## Learning Transferable Visual Models From Natural Language Supervision
- **Authors:** Alec Radford, Jong Wook Kim, Chris Hallacy, et al.
@@ -1014,7 +1014,7 @@ For instance, we match the accuracy of the original ResNet-50 on ImageNet
zero-shot without needing to use any of the 1.28 million training examples it
was trained on. We release our code and pre-trained model weights at
https://github.com/OpenAI/CLIP.
## Language Models are Few-Shot Learners
- **Authors:** Tom B. Brown, Benjamin Mann, Nick Ryder, et al.
@@ -1047,7 +1047,7 @@ training on large web corpora. Finally, we find that GPT-3 can generate samples
of news articles which human evaluators have difficulty distinguishing from
articles written by humans. We discuss broader societal impacts of this finding
and of GPT-3 in general.
## Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
- **Authors:** Patrick Lewis, Ethan Perez, Aleksandra Piktus, et al.
@@ -1078,7 +1078,7 @@ parametric seq2seq models and task-specific retrieve-and-extract architectures.
For language generation tasks, we find that RAG models generate more specific,
diverse and factual language than a state-of-the-art parametric-only seq2seq
baseline.
## CTRL: A Conditional Transformer Language Model for Controllable Generation
- **Authors:** Nitish Shirish Keskar, Bryan McCann, Lav R. Varshney, et al.
@@ -1098,4 +1098,3 @@ codes also allow CTRL to predict which parts of the training data are most
likely given a sequence. This provides a potential method for analyzing large
amounts of data via model-based source attribution. We have released multiple
full-sized, pretrained versions of CTRL at https://github.com/salesforce/ctrl.

View File

@@ -7,4 +7,4 @@
- `BaseChatModel` methods `__call__`, `call_as_llm`, `predict`, `predict_messages`. Will be removed in 0.2.0. Use `BaseChatModel.invoke` instead.
- `BaseChatModel` methods `apredict`, `apredict_messages`. Will be removed in 0.2.0. Use `BaseChatModel.ainvoke` instead.
- `BaseLLM` methods `__call__`, `predict`, `predict_messages`. Will be removed in 0.2.0. Use `BaseLLM.invoke` instead.
- `BaseLLM` methods `apredict`, `apredict_messages`. Will be removed in 0.2.0. Use `BaseLLM.ainvoke` instead.
- `BaseLLM` methods `apredict`, `apredict_messages`. Will be removed in 0.2.0. Use `BaseLLM.ainvoke` instead.

View File

@@ -90,4 +90,4 @@ Deprecated classes and methods will be removed in 0.2.0
| OpenAIMultiFunctionsAgent | create_openai_tools_agent | Use LCEL builder over a class |
| SelfAskWithSearchAgent | create_self_ask_with_search | Use LCEL builder over a class |
| StructuredChatAgent | create_structured_chat_agent | Use LCEL builder over a class |
| XMLAgent | create_xml_agent | Use LCEL builder over a class |
| XMLAgent | create_xml_agent | Use LCEL builder over a class |

View File

@@ -11,8 +11,8 @@ Please see the following resources for more information:
## Legacy agent concept: AgentExecutor
LangChain previously introduced the `AgentExecutor` as a runtime for agents.
While it served as an excellent starting point, its limitations became apparent when dealing with more sophisticated and customized agents.
LangChain previously introduced the `AgentExecutor` as a runtime for agents.
While it served as an excellent starting point, its limitations became apparent when dealing with more sophisticated and customized agents.
As a result, we're gradually phasing out `AgentExecutor` in favor of more flexible solutions in LangGraph.
### Transitioning from AgentExecutor to LangGraph

View File

@@ -70,4 +70,4 @@ This is a common reason why you may fail to see events being emitted from custom
runnables or tools.
:::
For specifics on how to use callbacks, see the [relevant how-to guides here](/docs/how_to/#callbacks).
For specifics on how to use callbacks, see the [relevant how-to guides here](/docs/how_to/#callbacks).

View File

@@ -26,7 +26,7 @@ A full conversation often involves a combination of two patterns of alternating
Since chat models have a maximum limit on input size, it's important to manage chat history and trim it as needed to avoid exceeding the [context window](/docs/concepts/chat_models/#context-window).
While processing chat history, it's essential to preserve a correct conversation structure.
While processing chat history, it's essential to preserve a correct conversation structure.
Key guidelines for managing chat history:

View File

@@ -127,7 +127,7 @@ If the input exceeds the context window, the model may not be able to process th
The size of the input is measured in [tokens](/docs/concepts/tokens) which are the unit of processing that the model uses.
## Advanced topics
### Rate-limiting
Many chat model providers impose a limit on the number of requests that can be made in a given time period.

View File

@@ -15,9 +15,9 @@ Embedding models can also be [multimodal](/docs/concepts/multimodality) though s
Imagine being able to capture the essence of any text - a tweet, document, or book - in a single, compact representation.
This is the power of embedding models, which lie at the heart of many retrieval systems.
Embedding models transform human language into a format that machines can understand and compare with speed and accuracy.
Embedding models transform human language into a format that machines can understand and compare with speed and accuracy.
These models take text as input and produce a fixed-length array of numbers, a numerical fingerprint of the text's semantic meaning.
Embeddings allow search system to find relevant documents not just based on keyword matches, but on semantic understanding.
Embeddings allow search system to find relevant documents not just based on keyword matches, but on semantic understanding.
## Key concepts
@@ -27,16 +27,16 @@ Embeddings allow search system to find relevant documents not just based on keyw
(2) **Measure similarity**: Embedding vectors can be compared using simple mathematical operations.
## Embedding
## Embedding
### Historical context
### Historical context
The landscape of embedding models has evolved significantly over the years.
A pivotal moment came in 2018 when Google introduced [BERT (Bidirectional Encoder Representations from Transformers)](https://www.nvidia.com/en-us/glossary/bert/).
The landscape of embedding models has evolved significantly over the years.
A pivotal moment came in 2018 when Google introduced [BERT (Bidirectional Encoder Representations from Transformers)](https://www.nvidia.com/en-us/glossary/bert/).
BERT applied transformer models to embed text as a simple vector representation, which lead to unprecedented performance across various NLP tasks.
However, BERT wasn't optimized for generating sentence embeddings efficiently.
However, BERT wasn't optimized for generating sentence embeddings efficiently.
This limitation spurred the creation of [SBERT (Sentence-BERT)](https://www.sbert.net/examples/training/sts/README.html), which adapted the BERT architecture to generate semantically rich sentence embeddings, easily comparable via similarity metrics like cosine similarity, dramatically reduced the computational overhead for tasks like finding similar sentences.
Today, the embedding model ecosystem is diverse, with numerous providers offering their own implementations.
Today, the embedding model ecosystem is diverse, with numerous providers offering their own implementations.
To navigate this variety, researchers and practitioners often turn to benchmarks like the Massive Text Embedding Benchmark (MTEB) [here](https://huggingface.co/blog/mteb) for objective comparisons.
:::info[Further reading]
@@ -93,9 +93,9 @@ LangChain offers many embedding model integrations which you can find [on the em
## Measure similarity
Each embedding is essentially a set of coordinates, often in a high-dimensional space.
Each embedding is essentially a set of coordinates, often in a high-dimensional space.
In this space, the position of each point (embedding) reflects the meaning of its corresponding text.
Just as similar words might be close to each other in a thesaurus, similar concepts end up close to each other in this embedding space.
Just as similar words might be close to each other in a thesaurus, similar concepts end up close to each other in this embedding space.
This allows for intuitive comparisons between different pieces of text.
By reducing text to these numerical representations, we can use simple mathematical operations to quickly measure how alike two pieces of text are, regardless of their original length or structure.
Some common similarity metrics include:
@@ -118,7 +118,7 @@ def cosine_similarity(vec1, vec2):
similarity = cosine_similarity(query_result, document_result)
print("Cosine Similarity:", similarity)
```
```
:::info[Further reading]
@@ -127,4 +127,4 @@ print("Cosine Similarity:", similarity)
* See Pinecone's [blog post](https://www.pinecone.io/learn/vector-similarity/) on similarity metrics.
* See OpenAI's [FAQ](https://platform.openai.com/docs/guides/embeddings/faq) on what similarity metric to use with OpenAI embeddings.
:::
:::

View File

@@ -14,4 +14,3 @@ This process is vital for building reliable applications.
- It allows you to track results over time and automatically run your evaluators on a schedule or as part of CI/Code
To learn more, check out [this LangSmith guide](https://docs.smith.langchain.com/concepts/evaluation).

View File

@@ -17,4 +17,4 @@ Sometimes these examples are hardcoded into the prompt, but for more advanced si
## Related resources
* [Example selector how-to guides](/docs/how_to/#example-selectors)
* [Example selector how-to guides](/docs/how_to/#example-selectors)

View File

@@ -14,7 +14,7 @@
* [Chat models](/docs/concepts/chat_models)
* [Messages](/docs/concepts/messages)
:::
LangChain supports multimodal data as input to chat models:
1. Following provider-specific formats

View File

@@ -8,7 +8,7 @@
## Overview
Retrieval Augmented Generation (RAG) is a powerful technique that enhances [language models](/docs/concepts/chat_models/) by combining them with external knowledge bases.
Retrieval Augmented Generation (RAG) is a powerful technique that enhances [language models](/docs/concepts/chat_models/) by combining them with external knowledge bases.
RAG addresses [a key limitation of models](https://www.glean.com/blog/how-to-build-an-ai-assistant-for-the-enterprise): models rely on fixed training datasets, which can lead to outdated or incomplete information.
When given a query, RAG systems first search a knowledge base for relevant information.
The system then incorporates this retrieved information into the model's prompt.
@@ -44,7 +44,7 @@ See our conceptual guide on [retrieval](/docs/concepts/retrieval/).
## Adding external knowledge
With a retrieval system in place, we need to pass knowledge from this system to the model.
With a retrieval system in place, we need to pass knowledge from this system to the model.
A RAG pipeline typically achieves this following these steps:
- Receive an input query.
@@ -59,12 +59,12 @@ from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
# Define a system prompt that tells the model how to use the retrieved context
system_prompt = """You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
system_prompt = """You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Use three sentences maximum and keep the answer concise.
Context: {context}:"""
# Define a question
question = """What are the main components of an LLM-powered autonomous agent system?"""
@@ -78,7 +78,7 @@ docs_text = "".join(d.page_content for d in docs)
system_prompt_fmt = system_prompt.format(context=docs_text)
# Create a model
model = ChatOpenAI(model="gpt-4o", temperature=0)
model = ChatOpenAI(model="gpt-4o", temperature=0)
# Generate a response
questions = model.invoke([SystemMessage(content=system_prompt_fmt),

View File

@@ -10,28 +10,28 @@
:::
:::danger[Security]
Some of the concepts reviewed here utilize models to generate queries (e.g., for SQL or graph databases).
There are inherent risks in doing this.
Make sure that your database connection permissions are scoped as narrowly as possible for your application's needs.
This will mitigate, though not eliminate, the risks of building a model-driven system capable of querying databases.
There are inherent risks in doing this.
Make sure that your database connection permissions are scoped as narrowly as possible for your application's needs.
This will mitigate, though not eliminate, the risks of building a model-driven system capable of querying databases.
For more on general security best practices, see our [security guide](/docs/security/).
:::
## Overview
## Overview
Retrieval systems are fundamental to many AI applications, efficiently identifying relevant information from large datasets.
Retrieval systems are fundamental to many AI applications, efficiently identifying relevant information from large datasets.
These systems accommodate various data formats:
- Unstructured text (e.g., documents) is often stored in vector stores or lexical search indexes.
- Structured data is typically housed in relational or graph databases with defined schemas.
Despite the growing diversity in data formats, modern AI applications increasingly aim to make all types of data accessible through natural language interfaces.
Models play a crucial role in this process by translating natural language queries into formats compatible with the underlying search index or database.
Despite the growing diversity in data formats, modern AI applications increasingly aim to make all types of data accessible through natural language interfaces.
Models play a crucial role in this process by translating natural language queries into formats compatible with the underlying search index or database.
This translation enables more intuitive and flexible interactions with complex data structures.
## Key concepts
## Key concepts
![Retrieval](/img/retrieval_concept.png)
@@ -39,20 +39,20 @@ This translation enables more intuitive and flexible interactions with complex d
(2) **Information retrieval**: Search queries are used to fetch information from various retrieval systems.
## Query analysis
## Query analysis
While users typically prefer to interact with retrieval systems using natural language, these systems may require specific query syntax or benefit from certain keywords.
While users typically prefer to interact with retrieval systems using natural language, these systems may require specific query syntax or benefit from certain keywords.
Query analysis serves as a bridge between raw user input and optimized search queries. Some common applications of query analysis include:
1. **Query Re-writing**: Queries can be re-written or expanded to improve semantic or lexical searches.
2. **Query Construction**: Search indexes may require structured queries (e.g., SQL for databases).
Query analysis employs models to transform or construct optimized search queries from raw user input.
Query analysis employs models to transform or construct optimized search queries from raw user input.
### Query re-writing
Retrieval systems should ideally handle a wide spectrum of user inputs, from simple and poorly worded queries to complex, multi-faceted questions.
To achieve this versatility, a popular approach is to use models to transform raw user queries into more effective search queries.
Retrieval systems should ideally handle a wide spectrum of user inputs, from simple and poorly worded queries to complex, multi-faceted questions.
To achieve this versatility, a popular approach is to use models to transform raw user queries into more effective search queries.
This transformation can range from simple keyword extraction to sophisticated query expansion and reformulation.
Here are some key benefits of using models for query analysis in unstructured data retrieval:
@@ -87,7 +87,7 @@ class Questions(BaseModel):
)
# Create an instance of the model and enforce the output structure
model = ChatOpenAI(model="gpt-4o", temperature=0)
model = ChatOpenAI(model="gpt-4o", temperature=0)
structured_model = model.with_structured_output(Questions)
# Define the system prompt
@@ -111,7 +111,7 @@ See our RAG from Scratch videos for a few different specific approaches:
### Query construction
Query analysis also can focus on translating natural language queries into specialized query languages or filters.
Query analysis also can focus on translating natural language queries into specialized query languages or filters.
This translation is crucial for effectively interacting with various types of databases that house structured or semi-structured data.
1. **Structured Data examples**: For relational and graph databases, Domain-Specific Languages (DSLs) are used to query data.
@@ -129,10 +129,10 @@ These approaches leverage models to bridge the gap between user intent and the s
| [Text to SQL](/docs/tutorials/sql_qa/) | If users are asking questions that require information housed in a relational database, accessible via SQL. | This uses an LLM to transform user input into a SQL query. |
| [Text-to-Cypher](/docs/tutorials/graph/) | If users are asking questions that require information housed in a graph database, accessible via Cypher. | This uses an LLM to transform user input into a Cypher query. |
As an example, here is how to use the `SelfQueryRetriever` to convert natural language queries into metadata filters.
As an example, here is how to use the `SelfQueryRetriever` to convert natural language queries into metadata filters.
```python
metadata_field_info = schema_for_metadata
metadata_field_info = schema_for_metadata
document_content_description = "Brief summary of a movie"
llm = ChatOpenAI(temperature=0)
retriever = SelfQueryRetriever.from_llm(
@@ -149,20 +149,20 @@ retriever = SelfQueryRetriever.from_llm(
* See our [blog post overview](https://blog.langchain.dev/query-construction/).
* See our RAG from Scratch video on [query construction](https://youtu.be/kl6NwWYxvbM?feature=shared).
:::
:::
## Information retrieval
## Information retrieval
### Common retrieval systems
#### Lexical search indexes
Many search engines are based upon matching words in a query to the words in each document.
Many search engines are based upon matching words in a query to the words in each document.
This approach is called lexical retrieval, using search [algorithms that are typically based upon word frequencies](https://cameronrwolfe.substack.com/p/the-basics-of-ai-powered-vector-search?utm_source=profile&utm_medium=reader2).
The intution is simple: a word appears frequently both in the users query and a particular document, then this document might be a good match.
The particular data structure used to implement this is often an [*inverted index*](https://www.geeksforgeeks.org/inverted-index/).
This types of index contains a list of words and a mapping of each word to a list of locations at which it occurs in various documents.
This types of index contains a list of words and a mapping of each word to a list of locations at which it occurs in various documents.
Using this data structure, it is possible to efficiently match the words in search queries to the documents in which they appear.
[BM25](https://en.wikipedia.org/wiki/Okapi_BM25#:~:text=BM25%20is%20a%20bag%2Dof,slightly%20different%20components%20and%20parameters.) and [TF-IDF](https://en.wikipedia.org/wiki/Tf%E2%80%93idf) are [two popular lexical search algorithms](https://cameronrwolfe.substack.com/p/the-basics-of-ai-powered-vector-search?utm_source=profile&utm_medium=reader2).
@@ -171,13 +171,13 @@ Using this data structure, it is possible to efficiently match the words in sear
* See the [BM25](/docs/integrations/retrievers/bm25/) retriever integration.
* See the [Elasticsearch](/docs/integrations/retrievers/elasticsearch_retriever/) retriever integration.
:::
:::
#### Vector indexes
Vector indexes are an alternative way to index and store unstructured data.
See our conceptual guide on [vectorstores](/docs/concepts/vectorstores/) for a detailed overview.
In short, rather than using word frequencies, vectorstores use an [embedding model](/docs/concepts/embedding_models/) to compress documents into high-dimensional vector representation.
See our conceptual guide on [vectorstores](/docs/concepts/vectorstores/) for a detailed overview.
In short, rather than using word frequencies, vectorstores use an [embedding model](/docs/concepts/embedding_models/) to compress documents into high-dimensional vector representation.
This allows for efficient similarity search over embedding vectors using simple mathematical operations like cosine similarity.
:::info[Further reading]
@@ -190,9 +190,9 @@ This allows for efficient similarity search over embedding vectors using simple
#### Relational databases
Relational databases are a fundamental type of structured data storage used in many applications.
They organize data into tables with predefined schemas, where each table represents an entity or relationship.
Data is stored in rows (records) and columns (attributes), allowing for efficient querying and manipulation through SQL (Structured Query Language).
Relational databases are a fundamental type of structured data storage used in many applications.
They organize data into tables with predefined schemas, where each table represents an entity or relationship.
Data is stored in rows (records) and columns (attributes), allowing for efficient querying and manipulation through SQL (Structured Query Language).
Relational databases excel at maintaining data integrity, supporting complex queries, and handling relationships between different data entities.
:::info[Further reading]
@@ -204,8 +204,8 @@ Relational databases excel at maintaining data integrity, supporting complex que
#### Graph databases
Graph databases are a specialized type of database designed to store and manage highly interconnected data.
Unlike traditional relational databases, graph databases use a flexible structure consisting of nodes (entities), edges (relationships), and properties.
Graph databases are a specialized type of database designed to store and manage highly interconnected data.
Unlike traditional relational databases, graph databases use a flexible structure consisting of nodes (entities), edges (relationships), and properties.
This structure allows for efficient representation and querying of complex, interconnected data.
Graph databases store data in a graph structure, with nodes, edges, and properties.
They are particularly useful for storing and querying complex relationships between data points, such as social networks, supply-chain management, fraud detection, and recommendation services
@@ -213,12 +213,12 @@ They are particularly useful for storing and querying complex relationships betw
:::info[Further reading]
* See our [tutorial](/docs/tutorials/graph/) for working with graph databases.
* See our [list of graph database integrations](/docs/integrations/graphs/).
* See our [list of graph database integrations](/docs/integrations/graphs/).
* See Neo4j's [starter kit for LangChain](https://neo4j.com/developer-blog/langchain-neo4j-starter-kit/).
:::
### Retriever
### Retriever
LangChain provides a unified interface for interacting with various retrieval systems through the [retriever](/docs/concepts/retrievers/) concept. The interface is straightforward:

View File

@@ -23,16 +23,16 @@ The LangChain [retriever](/docs/concepts/retrievers/) interface is straightforwa
## Key concept
![Retriever](/img/retriever_concept.png)
All retrievers implement a simple interface for retrieving documents using natural language queries.
## Interface
## Interface
The only requirement for a retriever is the ability to accepts a query and return documents.
The only requirement for a retriever is the ability to accepts a query and return documents.
In particular, [LangChain's retriever class](https://python.langchain.com/api_reference/core/retrievers/langchain_core.retrievers.BaseRetriever.html#) only requires that the `_get_relevant_documents` method is implemented, which takes a `query: str` and returns a list of [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) objects that are most relevant to the query.
The underlying logic used to get relevant documents is specified by the retriever and can be whatever is most useful for the application.
A LangChain retriever is a [runnable](/docs/how_to/lcel_cheatsheet/), which is a standard interface for LangChain components.
A LangChain retriever is a [runnable](/docs/how_to/lcel_cheatsheet/), which is a standard interface for LangChain components.
This means that it has a few common methods, including `invoke`, that are used to interact with it. A retriever can be invoked with a query:
```python
@@ -42,23 +42,23 @@ docs = retriever.invoke(query)
Retrievers return a list of [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) objects, which have two attributes:
* `page_content`: The content of this document. Currently is a string.
* `metadata`: Arbitrary metadata associated with this document (e.g., document id, file name, source, etc).
* `metadata`: Arbitrary metadata associated with this document (e.g., document id, file name, source, etc).
:::info[Further reading]
* See our [how-to guide](/docs/how_to/custom_retriever/) on building your own custom retriever.
:::
## Common types
Despite the flexibility of the retriever interface, a few common types of retrieval systems are frequently used.
### Search apis
It's important to note that retrievers don't need to actually *store* documents.
For example, we can build retrievers on top of search APIs that simply return search results!
See our retriever integrations with [Amazon Kendra](/docs/integrations/retrievers/amazon_kendra_retriever/) or [Wikipedia Search](/docs/integrations/retrievers/wikipedia/).
It's important to note that retrievers don't need to actually *store* documents.
For example, we can build retrievers on top of search APIs that simply return search results!
See our retriever integrations with [Amazon Kendra](/docs/integrations/retrievers/amazon_kendra_retriever/) or [Wikipedia Search](/docs/integrations/retrievers/wikipedia/).
### Relational or graph database
@@ -75,7 +75,7 @@ For example, you can build a retriever for a SQL database using text-to-SQL conv
### Lexical search
As discussed in our conceptual review of [retrieval](/docs/concepts/retrieval/), many search engines are based upon matching words in a query to the words in each document.
As discussed in our conceptual review of [retrieval](/docs/concepts/retrieval/), many search engines are based upon matching words in a query to the words in each document.
[BM25](https://en.wikipedia.org/wiki/Okapi_BM25#:~:text=BM25%20is%20a%20bag%2Dof,slightly%20different%20components%20and%20parameters.) and [TF-IDF](https://en.wikipedia.org/wiki/Tf%E2%80%93idf) are [two popular lexical search algorithms](https://cameronrwolfe.substack.com/p/the-basics-of-ai-powered-vector-search?utm_source=profile&utm_medium=reader2).
LangChain has retrievers for many popular lexical search algorithms / engines.
@@ -85,11 +85,11 @@ LangChain has retrievers for many popular lexical search algorithms / engines.
* See the [TF-IDF](/docs/integrations/retrievers/tf_idf/) retriever integration.
* See the [Elasticsearch](/docs/integrations/retrievers/elasticsearch_retriever/) retriever integration.
:::
:::
### Vector store
### Vector store
[Vector stores](/docs/concepts/vectorstores/) are a powerful and efficient way to index and retrieve unstructured data.
[Vector stores](/docs/concepts/vectorstores/) are a powerful and efficient way to index and retrieve unstructured data.
A vectorstore can be used as a retriever by calling the `as_retriever()` method.
```python
@@ -99,7 +99,7 @@ retriever = vectorstore.as_retriever()
## Advanced retrieval patterns
### Ensemble
### Ensemble
Because the retriever interface is so simple, returning a list of `Document` objects given a search query, it is possible to combine multiple retrievers using ensembling.
This is particularly useful when you have multiple retrievers that are good at finding different types of relevant documents.
@@ -112,24 +112,24 @@ ensemble_retriever = EnsembleRetriever(
)
```
When ensembling, how do we combine search results from many retrievers?
When ensembling, how do we combine search results from many retrievers?
This motivates the concept of re-ranking, which takes the output of multiple retrievers and combines them using a more sophisticated algorithm such as [Reciprocal Rank Fusion (RRF)](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf).
### Source document retention
### Source document retention
Many retrievers utilize some kind of index to make documents easily searchable.
The process of indexing can include a transformation step (e.g., vectorstores often use document splitting).
The process of indexing can include a transformation step (e.g., vectorstores often use document splitting).
Whatever transformation is used, can be very useful to retain a link between the *transformed document* and the original, giving the retriever the ability to return the *original* document.
![Retrieval with full docs](/img/retriever_full_docs.png)
This is particularly useful in AI applications, because it ensures no loss in document context for the model.
For example, you may use small chunk size for indexing documents in a vectorstore.
If you return *only* the chunks as the retrieval result, then the model will have lost the original document context for the chunks.
For example, you may use small chunk size for indexing documents in a vectorstore.
If you return *only* the chunks as the retrieval result, then the model will have lost the original document context for the chunks.
LangChain has two different retrievers that can be used to address this challenge.
The [Multi-Vector](/docs/how_to/multi_vector/) retriever allows the user to use any document transformation (e.g., use an LLM to write a summary of the document) for indexing while retaining linkage to the source document.
The [ParentDocument](/docs/how_to/parent_document_retriever/) retriever links document chunks from a text-splitter transformation for indexing while retaining linkage to the source document.
LangChain has two different retrievers that can be used to address this challenge.
The [Multi-Vector](/docs/how_to/multi_vector/) retriever allows the user to use any document transformation (e.g., use an LLM to write a summary of the document) for indexing while retaining linkage to the source document.
The [ParentDocument](/docs/how_to/parent_document_retriever/) retriever links document chunks from a text-splitter transformation for indexing while retaining linkage to the source document.
| Name | Index Type | Uses an LLM | When to Use | Description |
|-----------------------------------------------------------|-------------------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

View File

@@ -107,7 +107,7 @@ The Runnable interface provides methods to get the [JSON Schema](https://json-sc
These APIs are mostly used internally for unit-testing and by [LangServe](/docs/concepts/architecture#langserve) which uses the APIs for input validation and generation of [OpenAPI documentation](https://www.openapis.org/).
In addition, to the input and output types, some Runnables have been set up with additional run time configuration options.
In addition, to the input and output types, some Runnables have been set up with additional run time configuration options.
There are corresponding APIs to get the Pydantic Schema and JSON Schema of the configuration options for the Runnable.
Please see the [Configurable Runnables](#configurable-runnables) section for more information.
@@ -151,12 +151,12 @@ Passing `config` to the `invoke` method is done like so:
```python
some_runnable.invoke(
some_input,
some_input,
config={
'run_name': 'my_run',
'tags': ['tag1', 'tag2'],
'run_name': 'my_run',
'tags': ['tag1', 'tag2'],
'metadata': {'key': 'value'}
}
)
```
@@ -185,13 +185,13 @@ There are two main patterns by which new `Runnables` are created:
foo_runnable = RunnableLambda(foo)
```
LangChain will try to propagate `RunnableConfig` automatically for both of the patterns.
LangChain will try to propagate `RunnableConfig` automatically for both of the patterns.
For handling the second pattern, LangChain relies on Python's [contextvars](https://docs.python.org/3/library/contextvars.html).
In Python 3.11 and above, this works out of the box, and you do not need to do anything special to propagate the `RunnableConfig` to the sub-calls.
In Python 3.9 and 3.10, if you are using **async code**, you need to manually pass the `RunnableConfig` through to the `Runnable` when invoking it.
In Python 3.9 and 3.10, if you are using **async code**, you need to manually pass the `RunnableConfig` through to the `Runnable` when invoking it.
This is due to a limitation in [asyncio's tasks](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task) in Python 3.9 and 3.10 which did
not accept a `context` argument.
@@ -201,7 +201,7 @@ Propagating the `RunnableConfig` manually is done like so:
```python
async def foo(input, config): # <-- Note the config argument
return await bar_runnable.ainvoke(input, config=config)
foo_runnable = RunnableLambda(foo)
```
@@ -235,7 +235,7 @@ The attributes will also be propagated to [callbacks](/docs/concepts/callbacks),
This is an advanced feature that is unnecessary for most users.
:::
You may need to set a custom `run_id` for a given run, in case you want
You may need to set a custom `run_id` for a given run, in case you want
to reference it later or correlate it with other systems.
The `run_id` MUST be a valid UUID string and **unique** for each run. It is used to identify
@@ -249,7 +249,7 @@ import uuid
run_id = uuid.uuid4()
some_runnable.invoke(
some_input,
some_input,
config={
'run_id': run_id
}
@@ -292,7 +292,7 @@ In addition, you can use it to specify any custom configuration options to pass
### Setting callbacks
Use this option to configure [callbacks](/docs/concepts/callbacks) for the runnable at
Use this option to configure [callbacks](/docs/concepts/callbacks) for the runnable at
runtime. The callbacks will be passed to all sub-calls made by the runnable.
```python

View File

@@ -52,7 +52,7 @@ In addition, there is a **legacy** async [astream_log](https://python.langchain.
The `stream()` method returns an iterator that yields chunks of output synchronously as they are produced. You can use a `for` loop to process each chunk in real-time. For example, when using an LLM, this allows the output to be streamed incrementally as it is generated, reducing the wait time for users.
The type of chunk yielded by the `stream()` and `astream()` methods depends on the component being streamed. For example, when streaming from an [LLM](/docs/concepts/chat_models) each component will be an [AIMessageChunk](/docs/concepts/messages#aimessagechunk); however, for other components, the chunk may be different.
The type of chunk yielded by the `stream()` and `astream()` methods depends on the component being streamed. For example, when streaming from an [LLM](/docs/concepts/chat_models) each component will be an [AIMessageChunk](/docs/concepts/messages#aimessagechunk); however, for other components, the chunk may be different.
The `stream()` method returns an iterator that yields these chunks as they are produced. For example,
@@ -99,7 +99,7 @@ If you compose multiple Runnables using [LangChains Expression Language (LCEL
<span data-heading-keywords="astream_events,stream_events,stream events"></span>
:::tip
Use the `astream_events` API to access custom data and intermediate outputs from LLM applications built entirely with [LCEL](/docs/concepts/lcel).
Use the `astream_events` API to access custom data and intermediate outputs from LLM applications built entirely with [LCEL](/docs/concepts/lcel).
While this API is available for use with [LangGraph](/docs/concepts/architecture#langgraph) as well, it is usually not necessary when working with LangGraph, as the `stream` and `astream` methods provide comprehensive streaming capabilities for LangGraph graphs.
:::
@@ -119,7 +119,7 @@ from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-3-sonnet-20240229")
model = ChatAnthropic(model="claude-3-7-sonnet-20250219")
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
parser = StrOutputParser()
@@ -148,7 +148,7 @@ LangChain simplifies streaming from [chat models](/docs/concepts/chat_models) by
### How It Works
When you call the `invoke` (or `ainvoke`) method on a chat model, LangChain will automatically switch to streaming mode if it detects that you are trying to stream the overall application.
When you call the `invoke` (or `ainvoke`) method on a chat model, LangChain will automatically switch to streaming mode if it detects that you are trying to stream the overall application.
Under the hood, it'll have `invoke` (or `ainvoke`) use the `stream` (or `astream`) method to generate its output. The result of the invocation will be the same as far as the code that was using `invoke` is concerned; however, while the chat model is being streamed, LangChain will take care of invoking `on_llm_new_token` events in LangChain's [callback system](/docs/concepts/callbacks). These callback events
allow LangGraph `stream`/`astream` and `astream_events` to surface the chat model's output in real-time.
@@ -158,14 +158,14 @@ Example:
```python
def node(state):
...
# The code below uses the invoke method, but LangChain will
# The code below uses the invoke method, but LangChain will
# automatically switch to streaming mode
# when it detects that the overall
# when it detects that the overall
# application is being streamed.
ai_message = model.invoke(state["messages"])
...
for chunk in compiled_graph.stream(..., mode="messages"):
for chunk in compiled_graph.stream(..., mode="messages"):
...
```
## Async Programming

View File

@@ -1,15 +1,15 @@
# Structured outputs
## Overview
## Overview
For many applications, such as chatbots, models need to respond to users directly in natural language.
However, there are scenarios where we need models to output in a *structured format*.
For many applications, such as chatbots, models need to respond to users directly in natural language.
However, there are scenarios where we need models to output in a *structured format*.
For example, we might want to store the model output in a database and ensure that the output conforms to the database schema.
This need motivates the concept of structured output, where models can be instructed to respond with a particular output structure.
![Structured output](/img/structured_output.png)
## Key concepts
## Key concepts
1. **Schema definition:** The output structure is represented as a schema, which can be defined in several ways.<br/>
2. **Returning structured output:** The model is given this schema, and is instructed to return output that conforms to it.
@@ -18,7 +18,7 @@ This need motivates the concept of structured output, where models can be instru
This pseudocode illustrates the recommended workflow when using structured output.
LangChain provides a method, [`with_structured_output()`](/docs/how_to/structured_output/#the-with_structured_output-method), that automates the process of binding the schema to the [model](/docs/concepts/chat_models/) and parsing the output.
This helper function is available for all model providers that support structured output.
This helper function is available for all model providers that support structured output.
```python
# Define schema
@@ -31,7 +31,7 @@ structured_output = model_with_structure.invoke(user_input)
## Schema definition
The central concept is that the output structure of model responses needs to be represented in some way.
The central concept is that the output structure of model responses needs to be represented in some way.
While types of objects you can use depend on the model you're working with, there are common types of objects that are typically allowed or recommended for structured output in Python.
The simplest and most common format for structured output is a JSON-like structure, which in Python can be represented as a dictionary (dict) or list (list).
@@ -45,7 +45,7 @@ JSON objects (or dicts in Python) are often used directly when the tool requires
```
As a second example, [Pydantic](https://docs.pydantic.dev/latest/) is particularly useful for defining structured output schemas because it offers type hints and validation.
Here's an example of a Pydantic schema:
Here's an example of a Pydantic schema:
```python
from pydantic import BaseModel, Field
@@ -59,7 +59,7 @@ class ResponseFormatter(BaseModel):
## Returning structured output
With a schema defined, we need a way to instruct the model to use it.
While one approach is to include this schema in the prompt and *ask nicely* for the model to use it, this is not recommended.
While one approach is to include this schema in the prompt and *ask nicely* for the model to use it, this is not recommended.
Several more powerful methods that utilizes native features in the model provider's API are available.
### Using tool calling
@@ -78,7 +78,7 @@ model_with_tools = model.bind_tools([ResponseFormatter])
ai_msg = model_with_tools.invoke("What is the powerhouse of the cell?")
```
The arguments of the tool call are already extracted as a dictionary.
The arguments of the tool call are already extracted as a dictionary.
This dictionary can be optionally parsed into a Pydantic object, matching our original `ResponseFormatter` schema.
```python
@@ -92,7 +92,7 @@ pydantic_object = ResponseFormatter.model_validate(ai_msg.tool_calls[0]["args"])
### JSON mode
In addition to tool calling, some model providers support a feature called `JSON mode`.
In addition to tool calling, some model providers support a feature called `JSON mode`.
This supports JSON schema definition as input and enforces the model to produce a conforming JSON output.
You can find a table of model providers that support JSON mode [here](/docs/integrations/chat/).
Here is an example of how to use JSON mode with OpenAI:
@@ -105,21 +105,21 @@ ai_msg
{'random_ints': [45, 67, 12, 34, 89, 23, 78, 56, 90, 11]}
```
## Structured output method
## Structured output method
There are a few challenges when producing structured output with the above methods:
There are a few challenges when producing structured output with the above methods:
1. When tool calling is used, tool call arguments needs to be parsed from a dictionary back to the original schema.<br/>
1. When tool calling is used, tool call arguments needs to be parsed from a dictionary back to the original schema.<br/>
2. In addition, the model needs to be instructed to *always* use the tool when we want to enforce structured output, which is a provider specific setting.<br/>
2. In addition, the model needs to be instructed to *always* use the tool when we want to enforce structured output, which is a provider specific setting.<br/>
3. When JSON mode is used, the output needs to be parsed into a JSON object.
3. When JSON mode is used, the output needs to be parsed into a JSON object.
With these challenges in mind, LangChain provides a helper function (`with_structured_output()`) to streamline the process.
![Diagram of with structured output](/img/with_structured_output.png)
This both binds the schema to the model as a tool and parses the output to the specified output schema.
This both binds the schema to the model as a tool and parses the output to the specified output schema.
```python
# Bind the schema to the model

View File

@@ -23,9 +23,9 @@ def test_convert_to_openai_messages():
ToolCall(name='parrot_multiply_tool', id='1', args={'a': 2, 'b': 3}),
]
)
result = convert_to_openai_messages(ai_message)
expected = {
"role": "assistant",
"tool_calls": [

View File

@@ -7,4 +7,4 @@ You are probably looking for the [Chat Model Concept Guide](/docs/concepts/chat_
LangChain has implementations for older language models that take a string as input and return a string as output. These models are typically named without the "Chat" prefix (e.g., `Ollama`, `Anthropic`, `OpenAI`, etc.), and may include the "LLM" suffix (e.g., `OllamaLLM`, `AnthropicLLM`, `OpenAILLM`, etc.). These models implement the [BaseLLM](https://python.langchain.com/api_reference/core/language_models/langchain_core.language_models.llms.BaseLLM.html#langchain_core.language_models.llms.BaseLLM) interface.
Users should be using almost exclusively the newer [Chat Models](/docs/concepts/chat_models) as most
model providers have adopted a chat like interface for interacting with language models.
model providers have adopted a chat like interface for interacting with language models.

View File

@@ -69,7 +69,7 @@ texts = text_splitter.split_text(document)
### Text-structured based
Text is naturally organized into hierarchical units such as paragraphs, sentences, and words.
Text is naturally organized into hierarchical units such as paragraphs, sentences, and words.
We can leverage this inherent structure to inform our splitting strategy, creating split that maintain natural language flow, maintain semantic coherence within split, and adapts to varying levels of text granularity.
LangChain's [`RecursiveCharacterTextSplitter`](/docs/how_to/recursive_text_splitter/) implements this concept:
- The `RecursiveCharacterTextSplitter` attempts to keep larger units (e.g., paragraphs) intact.
@@ -92,7 +92,7 @@ texts = text_splitter.split_text(document)
### Document-structured based
Some documents have an inherent structure, such as HTML, Markdown, or JSON files.
Some documents have an inherent structure, such as HTML, Markdown, or JSON files.
In these cases, it's beneficial to split the document based on its structure, as it often naturally groups semantically related text.
Key benefits of structure-based splitting:
- Preserves the logical organization of the document
@@ -116,7 +116,7 @@ Examples of structure-based splitting:
### Semantic meaning based
Unlike the previous methods, semantic-based splitting actually considers the *content* of the text.
Unlike the previous methods, semantic-based splitting actually considers the *content* of the text.
While other approaches use document or text structure as proxies for semantic meaning, this method directly analyzes the text's semantics.
There are several ways to implement this, but conceptually the approach is split text when there are significant changes in text *meaning*.
As an example, we can use a sliding window approach to generate embeddings, and compare the embeddings to find significant differences:

View File

@@ -55,4 +55,4 @@ According to the OpenAI post, the approximate token counts for English text are
* 1 token ~= 4 chars in English
* 1 token ~= ¾ words
* 100 tokens ~= 75 words
* 100 tokens ~= 75 words

View File

@@ -6,7 +6,7 @@
:::
## Overview
## Overview
Many AI applications interact directly with humans. In these cases, it is appropriate for models to respond in natural language.
But what about cases where we want a model to also interact *directly* with systems, such as databases or an API?
@@ -14,12 +14,12 @@ These systems often have a particular input schema; for example, APIs frequently
This need motivates the concept of *tool calling*. You can use [tool calling](https://platform.openai.com/docs/guides/function-calling/example-use-cases) to request model responses that match a particular schema.
:::info
You will sometimes hear the term `function calling`. We use this term interchangeably with `tool calling`.
You will sometimes hear the term `function calling`. We use this term interchangeably with `tool calling`.
:::
![Conceptual overview of tool calling](/img/tool_calling_concept.png)
## Key concepts
## Key concepts
1. **Tool Creation:** Use the [@tool](https://python.langchain.com/api_reference/core/tools/langchain_core.tools.convert.tool.html) decorator to create a [tool](/docs/concepts/tools). A tool is an association between a function and its schema.<br/>
2. **Tool Binding:** The tool needs to be connected to a model that supports tool calling. This gives the model awareness of the tool and the associated input schema required by the tool.<br/>
@@ -40,7 +40,7 @@ The tool call arguments can be passed directly to the tool.
tools = [my_tool]
# Tool binding
model_with_tools = model.bind_tools(tools)
# Tool calling
# Tool calling
response = model_with_tools.invoke(user_input)
```
@@ -65,16 +65,16 @@ def multiply(a: int, b: int) -> int:
:::
## Tool binding
## Tool binding
[Many](https://platform.openai.com/docs/guides/function-calling) [model providers](https://platform.openai.com/docs/guides/function-calling) support tool calling.
[Many](https://platform.openai.com/docs/guides/function-calling) [model providers](https://platform.openai.com/docs/guides/function-calling) support tool calling.
:::tip
See our [model integration page](/docs/integrations/chat/) for a list of providers that support tool calling.
:::
The central concept to understand is that LangChain provides a standardized interface for connecting tools to models.
The `.bind_tools()` method can be used to specify which tools are available for a model to call.
The central concept to understand is that LangChain provides a standardized interface for connecting tools to models.
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)
@@ -113,7 +113,7 @@ However, if we pass an input *relevant to the tool*, the model should choose to
result = llm_with_tools.invoke("What is 2 multiplied by 3?")
```
As before, the output `result` will be an `AIMessage`.
As before, the output `result` will be an `AIMessage`.
But, if the tool was called, `result` will have a `tool_calls` [attribute](https://python.langchain.com/api_reference/core/messages/langchain_core.messages.ai.AIMessage.html#langchain_core.messages.ai.AIMessage.tool_calls).
This attribute includes everything needed to execute the tool, including the tool name and input arguments:

View File

@@ -6,7 +6,7 @@
## Overview
The **tool** abstraction in LangChain associates a Python **function** with a **schema** that defines the function's **name**, **description** and **expected arguments**.
The **tool** abstraction in LangChain associates a Python **function** with a **schema** that defines the function's **name**, **description** and **expected arguments**.
**Tools** can be passed to [chat models](/docs/concepts/chat_models) that support [tool calling](/docs/concepts/tool_calling) allowing the model to request the execution of a specific function with specific inputs.
@@ -68,10 +68,10 @@ You can also inspect the tool's schema and other properties:
```python
print(multiply.name) # multiply
print(multiply.description) # Multiply two numbers.
print(multiply.args)
print(multiply.args)
# {
# 'type': 'object',
# 'properties': {'a': {'type': 'integer'}, 'b': {'type': 'integer'}},
# 'type': 'object',
# 'properties': {'a': {'type': 'integer'}, 'b': {'type': 'integer'}},
# 'required': ['a', 'b']
# }
```
@@ -89,14 +89,14 @@ Please see the [API reference for @tool](https://python.langchain.com/api_refere
## Tool artifacts
**Tools** are utilities that can be called by a model, and whose outputs are designed to be fed back to a model. Sometimes, however, there are artifacts of a tool's execution that we want to make accessible to downstream components in our chain or agent, but that we don't want to expose to the model itself. For example if a tool returns a custom object, a dataframe or an image, we may want to pass some metadata about this output to the model without passing the actual output to the model. At the same time, we may want to be able to access this full output elsewhere, for example in downstream tools.
**Tools** are utilities that can be called by a model, and whose outputs are designed to be fed back to a model. Sometimes, however, there are artifacts of a tool's execution that we want to make accessible to downstream components in our chain or agent, but that we don't want to expose to the model itself. For example if a tool returns a custom object, a dataframe or an image, we may want to pass some metadata about this output to the model without passing the actual output. At the same time, we may want to be able to access this full output elsewhere, for example in downstream tools.
```python
@tool(response_format="content_and_artifact")
def some_tool(...) -> Tuple[str, Any]:
"""Tool that does something."""
...
return 'Message for chat model', some_artifact
return 'Message for chat model', some_artifact
```
See [how to return artifacts from tools](/docs/how_to/tool_artifacts/) for more details.
@@ -134,7 +134,7 @@ def user_specific_tool(input_data: str, user_id: InjectedToolArg) -> str:
Annotating the `user_id` argument with `InjectedToolArg` tells LangChain that this argument should not be exposed as part of the
tool's schema.
See [how to pass run time values to tools](/docs/how_to/tool_runtime/) for more details on how to use `InjectedToolArg`.
See [how to pass run time values to tools](/docs/how_to/tool_runtime/) for more details on how to use `InjectedToolArg`.
### RunnableConfig

View File

@@ -9,7 +9,7 @@
:::
:::info[Note]
This conceptual overview focuses on text-based indexing and retrieval for simplicity.
This conceptual overview focuses on text-based indexing and retrieval for simplicity.
However, embedding models can be [multi-modal](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-multimodal-embeddings)
and vector stores can be used to store and retrieve a variety of data types beyond text.
:::
@@ -125,7 +125,7 @@ to the documentation of the specific vectorstore you are using to see what simil
Given a similarity metric to measure the distance between the embedded query and any embedded document, we need an algorithm to efficiently search over *all* the embedded documents to find the most similar ones.
There are various ways to do this. As an example, many vectorstores implement [HNSW (Hierarchical Navigable Small World)](https://www.pinecone.io/learn/series/faiss/hnsw/), a graph-based index structure that allows for efficient similarity search.
Regardless of the search algorithm used under the hood, the LangChain vectorstore interface has a `similarity_search` method for all integrations.
Regardless of the search algorithm used under the hood, the LangChain vectorstore interface has a `similarity_search` method for all integrations.
This will take the search query, create an embedding, find similar documents, and return them as a list of [Documents](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html).
```python
@@ -166,7 +166,7 @@ vectorstore.similarity_search(
k=2,
filter={"source": "tweet"},
)
```
```
:::info[Further reading]
@@ -179,7 +179,7 @@ vectorstore.similarity_search(
While algorithms like HNSW provide the foundation for efficient similarity search in many cases, additional techniques can be employed to improve search quality and diversity.
For example, [maximal marginal relevance](https://python.langchain.com/v0.1/docs/modules/model_io/prompts/example_selectors/mmr/) is a re-ranking algorithm used to diversify search results, which is applied after the initial similarity search to ensure a more diverse set of results.
As a second example, some [vector stores](/docs/integrations/retrievers/pinecone_hybrid_search/) offer built-in [hybrid-search](https://docs.pinecone.io/guides/data/understanding-hybrid-search) to combine keyword and semantic similarity search, which marries the benefits of both approaches.
As a second example, some [vector stores](/docs/integrations/retrievers/pinecone_hybrid_search/) offer built-in [hybrid-search](https://docs.pinecone.io/guides/data/understanding-hybrid-search) to combine keyword and semantic similarity search, which marries the benefits of both approaches.
At the moment, there is no unified way to perform hybrid search using LangChain vectorstores, but it is generally exposed as a keyword argument that is passed in with `similarity_search`.
See this [how-to guide on hybrid search](/docs/how_to/hybrid/) for more details.
@@ -188,4 +188,4 @@ See this [how-to guide on hybrid search](/docs/how_to/hybrid/) for more details.
| [Hybrid search](/docs/integrations/retrievers/pinecone_hybrid_search/) | When combining keyword-based and semantic similarity. | Hybrid search combines keyword and semantic similarity, marrying the benefits of both approaches. [Paper](https://arxiv.org/abs/2210.11934). |
| [Maximal Marginal Relevance (MMR)](https://python.langchain.com/api_reference/pinecone/vectorstores/langchain_pinecone.vectorstores.PineconeVectorStore.html#langchain_pinecone.vectorstores.PineconeVectorStore.max_marginal_relevance_search) | When needing to diversify search results. | MMR attempts to diversify the results of a search to avoid returning similar and redundant documents. |

View File

@@ -18,7 +18,7 @@ LangChain exposes a standard interface for key components, making it easy to swi
3. **Observability and evaluation:** As applications become more complex, it becomes increasingly difficult to understand what is happening within them.
Furthermore, the pace of development can become rate-limited by the [paradox of choice](https://en.wikipedia.org/wiki/Paradox_of_choice).
For example, developers often wonder how to engineer their prompt or which LLM best balances accuracy, latency, and cost.
For example, developers often wonder how to engineer their prompt or which LLM best balances accuracy, latency, and cost.
[Observability](https://en.wikipedia.org/wiki/Observability) and evaluations can help developers monitor their applications and rapidly answer these types of questions with confidence.
@@ -29,10 +29,10 @@ As an example, all [chat models](/docs/concepts/chat_models/) implement the [Bas
This provides a standard way to interact with chat models, supporting important but often provider-specific features like [tool calling](/docs/concepts/tool_calling/) and [structured outputs](/docs/concepts/structured_outputs/).
### Example: chat models
### Example: chat models
Many [model providers](/docs/concepts/chat_models/) support [tool calling](/docs/concepts/tool_calling/), a critical feature for many applications (e.g., [agents](https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/)), that allows a developer to request model responses that match a particular schema.
The APIs for each provider differ.
The APIs for each provider differ.
LangChain's [chat model](/docs/concepts/chat_models/) interface provides a common way to bind [tools](/docs/concepts/tools) to a model in order to support [tool calling](/docs/concepts/tool_calling/):
```python
@@ -42,7 +42,7 @@ tools = [my_tool]
model_with_tools = model.bind_tools(tools)
```
Similarly, getting models to produce [structured outputs](/docs/concepts/structured_outputs/) is an extremely common use case.
Similarly, getting models to produce [structured outputs](/docs/concepts/structured_outputs/) is an extremely common use case.
Providers support different approaches for this, including [JSON mode or tool calling](https://platform.openai.com/docs/guides/structured-outputs), with different APIs.
LangChain's [chat model](/docs/concepts/chat_models/) interface provides a common way to produce structured outputs using the `with_structured_output()` method:
@@ -62,9 +62,9 @@ The underlying implementation of the retriever depends on the type of data store
documents = my_retriever.invoke("What is the meaning of life?")
```
## Orchestration
## Orchestration
While standardization for individual components is useful, we've increasingly seen that developers want to *combine* components into more complex applications.
While standardization for individual components is useful, we've increasingly seen that developers want to *combine* components into more complex applications.
This motivates the need for [orchestration](https://en.wikipedia.org/wiki/Orchestration_(computing)).
There are several common characteristics of LLM applications that this orchestration layer should support:
@@ -75,7 +75,7 @@ There are several common characteristics of LLM applications that this orchestra
The recommended way to orchestrate components for complex applications is [LangGraph](https://langchain-ai.github.io/langgraph/concepts/high_level/).
LangGraph is a library that gives developers a high degree of control by expressing the flow of the application as a set of nodes and edges.
LangGraph comes with built-in support for [persistence](https://langchain-ai.github.io/langgraph/concepts/persistence/), [human-in-the-loop](https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop/), [memory](https://langchain-ai.github.io/langgraph/concepts/memory/), and other features.
It's particularly well suited for building [agents](https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/) or [multi-agent](https://langchain-ai.github.io/langgraph/concepts/multi_agent/) applications.
It's particularly well suited for building [agents](https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/) or [multi-agent](https://langchain-ai.github.io/langgraph/concepts/multi_agent/) applications.
Importantly, individual LangChain components can be used as LangGraph nodes, but you can also use LangGraph **without** using LangChain components.
:::info[Further reading]
@@ -86,8 +86,8 @@ Have a look at our free course, [Introduction to LangGraph](https://academy.lang
## Observability and evaluation
The pace of AI application development is often rate-limited by high-quality evaluations because there is a paradox of choice.
Developers often wonder how to engineer their prompt or which LLM best balances accuracy, latency, and cost.
The pace of AI application development is often rate-limited by high-quality evaluations because there is a paradox of choice.
Developers often wonder how to engineer their prompt or which LLM best balances accuracy, latency, and cost.
High quality tracing and evaluations can help you rapidly answer these types of questions with confidence.
[LangSmith](https://docs.smith.langchain.com/) is our platform that supports observability and evaluation for AI applications.
See our conceptual guides on [evaluations](https://docs.smith.langchain.com/concepts/evaluation) and [tracing](https://docs.smith.langchain.com/concepts/tracing) for more details.

View File

@@ -9,6 +9,14 @@ This project utilizes [uv](https://docs.astral.sh/uv/) v0.5+ as a dependency man
Install `uv`: **[documentation on how to install it](https://docs.astral.sh/uv/getting-started/installation/)**.
### Windows Users
If you're on Windows and don't have `make` installed, you can install it via:
- **Option 1**: Install via [Chocolatey](https://chocolatey.org/): `choco install make`
- **Option 2**: Install via [Scoop](https://scoop.sh/): `scoop install make`
- **Option 3**: Use [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/)
- **Option 4**: Use the direct `uv` commands shown in the sections below
## Different packages
This repository contains multiple packages:
@@ -48,7 +56,11 @@ uv sync
Then verify dependency installation:
```bash
# If you have `make` installed:
make test
# If you don't have `make` (Windows alternative):
uv run --group test pytest -n auto --disable-socket --allow-unix-socket tests/unit_tests
```
## Testing
@@ -61,7 +73,11 @@ If you add new logic, please add a unit test.
To run unit tests:
```bash
# If you have `make` installed:
make test
# If you don't have make (Windows alternative):
uv run --group test pytest -n auto --disable-socket --allow-unix-socket tests/unit_tests
```
There are also [integration tests and code-coverage](../testing.mdx) available.
@@ -72,7 +88,12 @@ If you are only developing `langchain_core`, you can simply install the dependen
```bash
cd libs/core
# If you have `make` installed:
make test
# If you don't have `make` (Windows alternative):
uv run --group test pytest -n auto --disable-socket --allow-unix-socket tests/unit_tests
```
## Formatting and linting
@@ -86,20 +107,37 @@ Formatting for this project is done via [ruff](https://docs.astral.sh/ruff/rules
To run formatting for docs, cookbook and templates:
```bash
# If you have `make` installed:
make format
# If you don't have make (Windows alternative):
uv run --all-groups ruff format .
uv run --all-groups ruff check --fix .
```
To run formatting for a library, run the same command from the relevant library directory:
```bash
cd libs/{LIBRARY}
# If you have `make` installed:
make format
# If you don't have make (Windows alternative):
uv run --all-groups ruff format .
uv run --all-groups ruff check --fix .
```
Additionally, you can run the formatter only on the files that have been modified in your current branch as compared to the master branch using the format_diff command:
```bash
# If you have `make` installed:
make format_diff
# If you don't have `make` (Windows alternative):
# First, get the list of modified files:
git diff --relative=libs/langchain --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$' | xargs uv run --all-groups ruff format
git diff --relative=libs/langchain --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$' | xargs uv run --all-groups ruff check --fix
```
This is especially useful when you have made changes to a subset of the project and want to ensure your changes are properly formatted without affecting the rest of the codebase.
@@ -111,20 +149,40 @@ Linting for this project is done via a combination of [ruff](https://docs.astral
To run linting for docs, cookbook and templates:
```bash
# If you have `make` installed:
make lint
# If you don't have `make` (Windows alternative):
uv run --all-groups ruff check .
uv run --all-groups ruff format . --diff
uv run --all-groups mypy . --cache-dir .mypy_cache
```
To run linting for a library, run the same command from the relevant library directory:
```bash
cd libs/{LIBRARY}
# If you have `make` installed:
make lint
# If you don't have `make` (Windows alternative):
uv run --all-groups ruff check .
uv run --all-groups ruff format . --diff
uv run --all-groups mypy . --cache-dir .mypy_cache
```
In addition, you can run the linter only on the files that have been modified in your current branch as compared to the master branch using the lint_diff command:
```bash
# If you have `make` installed:
make lint_diff
# If you don't have `make` (Windows alternative):
# First, get the list of modified files:
git diff --relative=libs/langchain --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$' | xargs uv run --all-groups ruff check
git diff --relative=libs/langchain --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$' | xargs uv run --all-groups ruff format --diff
git diff --relative=libs/langchain --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$' | xargs uv run --all-groups mypy --cache-dir .mypy_cache
```
This can be very helpful when you've made changes to only certain parts of the project and want to ensure your changes meet the linting standards without having to check the entire codebase.
@@ -139,13 +197,21 @@ Note that `codespell` finds common typos, so it could have false-positive (corre
To check spelling for this project:
```bash
# If you have `make` installed:
make spell_check
# If you don't have `make` (Windows alternative):
uv run --all-groups codespell --toml pyproject.toml
```
To fix spelling in place:
```bash
# If you have `make` installed:
make spell_fix
# If you don't have `make` (Windows alternative):
uv run --all-groups codespell --toml pyproject.toml -w
```
If codespell is incorrectly flagging a word, you can skip spellcheck for that word by adding it to the codespell config in the `pyproject.toml` file.

View File

@@ -1,6 +1,6 @@
# Contribute documentation
Documentation is a vital part of LangChain. We welcome both new documentation for new features and
Documentation is a vital part of LangChain. We welcome both new documentation for new features and
community improvements to our current documentation. Please read the resources below before getting started:
- [Documentation style guide](style_guide.mdx)

View File

@@ -35,7 +35,7 @@ Some examples include:
- [Build a Retrieval Augmented Generation (RAG) App](/docs/tutorials/rag/)
A good structural rule of thumb is to follow the structure of this [example from Numpy](https://numpy.org/numpy-tutorials/content/tutorial-svd.html).
Here are some high-level tips on writing a good tutorial:
- Focus on guiding the user to get something done, but keep in mind the end-goal is more to impart principles than to create a perfect production system.
@@ -49,7 +49,7 @@ Here are some high-level tips on writing a good tutorial:
- The first time you mention a LangChain concept, use its full name (e.g. "LangChain Expression Language (LCEL)"), and link to its conceptual/other documentation page.
- It's also helpful to add a prerequisite callout that links to any pages with necessary background information.
- End with a recap/next steps section summarizing what the tutorial covered and future reading, such as related how-to guides.
### How-to guides
A how-to guide, as the name implies, demonstrates how to do something discrete and specific.

View File

@@ -15,7 +15,7 @@ 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
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
@@ -23,7 +23,7 @@ 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
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:

View File

@@ -14,8 +14,8 @@ First, duplicate this template repository: https://github.com/langchain-ai/integ
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
A package is
installed by users with `pip install langchain-{partner}`, and the package members
can be imported with code like:
```python
@@ -93,11 +93,11 @@ 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.
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
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
@@ -116,8 +116,8 @@ After our change, it would look like this:
from langchain_core._api.deprecation import deprecated
@deprecated(
since="0.0.<next community version>",
removal="1.0.0",
since="0.0.<next community version>",
removal="1.0.0",
alternative_import="langchain_parrot_link.ChatParrotLink"
)
class ChatParrotLink(BaseChatModel):

View File

@@ -4,7 +4,7 @@ pagination_prev: contributing/how_to/integrations/index
---
# How to implement an integration package
This guide walks through the process of implementing a LangChain integration
This guide walks through the process of implementing a LangChain integration
package.
Integration packages are just Python packages that can be installed with `pip install <your-package>`,
@@ -14,11 +14,11 @@ We will cover:
1. (Optional) How to bootstrap a new integration package
2. How to implement components, such as [chat models](/docs/concepts/chat_models/) and [vector stores](/docs/concepts/vectorstores/), that adhere
to the LangChain interface;
to the LangChain interface;
## (Optional) bootstrapping a new integration package
In this section, we will outline 2 options for bootstrapping a new integration package,
In this section, we will outline 2 options for bootstrapping a new integration package,
and you're welcome to use other tools if you prefer!
1. **langchain-cli**: This is a command-line tool that can be used to bootstrap a new integration package with a template for LangChain components and Poetry for dependency management.
@@ -132,7 +132,7 @@ We will also add some `test` dependencies in a separate poetry dependency group.
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.
`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.
@@ -168,8 +168,8 @@ langchain-parrot-link/
└── 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`
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.
For `chat_models.py`, simply paste the contents of the chat model implementation
@@ -202,7 +202,7 @@ import CodeBlock from '@theme/CodeBlock';
<Tabs>
<TabItem value="chat_models" label="Chat models">
Refer to the [Custom Chat Model Guide](/docs/how_to/custom_chat_model) guide for
detail on a starter chat model [implementation](/docs/how_to/custom_chat_model/#implementation).
@@ -244,7 +244,7 @@ import ChatModelSource from '../../../../src/theme/integration_template/integrat
base class. This interface consists of methods for writing, deleting and searching
for documents in the vector store.
`VectorStore` supports a variety of synchronous and asynchronous search types (e.g.,
`VectorStore` supports a variety of synchronous and asynchronous search types (e.g.,
nearest-neighbor or maximum marginal relevance), as well as interfaces for adding
documents to the store. See the [API Reference](https://python.langchain.com/api_reference/core/vectorstores/langchain_core.vectorstores.base.VectorStore.html)
for all supported methods. The required methods are tabulated below:
@@ -331,7 +331,7 @@ or parameters to call the tool with.
2. To take a "tool call" as generated above, and take some action and return a response
that can be passed back to the chat model as a ToolMessage.
The `Tools` class must inherit from the [BaseTool](https://python.langchain.com/api_reference/core/tools/langchain_core.tools.base.BaseTool.html#langchain_core.tools.base.BaseTool) base class. This interface has 3 properties and 2 methods that should be implemented in a
The `Tools` class must inherit from the [BaseTool](https://python.langchain.com/api_reference/core/tools/langchain_core.tools.base.BaseTool.html#langchain_core.tools.base.BaseTool) base class. This interface has 3 properties and 2 methods that should be implemented in a
subclass.
| Method/Property | Description |
@@ -355,7 +355,7 @@ important for the initial user experience of the tool.
arguments. This is used to validate the input arguments to the tool, and to provide
a schema for the LLM to fill out when calling the tool. Similar to the `name` and
`description` of the overall Tool class, the fields' names (the variable name) and
description (part of `Field(..., description="description")`) are passed to the LLM,
description (part of `Field(..., description="description")`) are passed to the LLM,
and the values in these fields should be concise and LLM-usable.
### Run methods

View File

@@ -15,7 +15,7 @@ First, let's install 2 dependencies:
:::note
Because added tests in new versions of `langchain-tests` can break your CI/CD pipelines, we recommend pinning the
Because added tests in new versions of `langchain-tests` can break your CI/CD pipelines, we recommend pinning the
version of `langchain-tests` to avoid unexpected changes.
:::
@@ -45,7 +45,7 @@ pip install --editable .
## Add and configure standard tests
There are 2 namespaces in the `langchain-tests` package:
There are 2 namespaces in the `langchain-tests` package:
- [unit tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.unit_tests`): designed to be used to test the component in isolation and without access to external services
- [integration tests](../../../concepts/testing.mdx#integration-tests) (`langchain_tests.integration_tests`): designed to be used to test the component with access to external services (in particular, the external service that the component is designed to interact with).
@@ -283,7 +283,7 @@ to specify the tool to be tested and the tool's configuration:
| `tool_constructor_params` | The parameters to pass to the tool (optional). |
| `tool_invoke_params_example` | An example of the parameters to pass to the tool's `invoke` method. |
If you are testing a tool class and pass a class like `MyTool` to `tool_constructor`, you can pass the parameters to the constructor in `tool_constructor_params`.
If you are testing a tool class and pass a class like `MyTool` to `tool_constructor`, you can pass the parameters to the constructor in `tool_constructor_params`.
If you are testing an instantiated tool, you can pass the instantiated tool to `tool_constructor` and do not
override `tool_constructor_params`.

View File

@@ -124,6 +124,47 @@ start "" htmlcov/index.html || open htmlcov/index.html
```
## Snapshot Testing
Some tests use [syrupy](https://github.com/tophat/syrupy) for snapshot testing, which captures the output of functions and compares them to stored snapshots. This is particularly useful for testing JSON schema generation and other structured outputs.
### Updating Snapshots
To update snapshots when the expected output has legitimately changed:
```bash
uv run --group test pytest path/to/test.py --snapshot-update
```
### Pydantic Version Compatibility Issues
Pydantic generates different JSON schemas across versions, which can cause snapshot test failures in CI when tests run with different Pydantic versions than what was used to generate the snapshots.
**Symptoms:**
- CI fails with snapshot mismatches showing differences like missing or extra fields.
- Tests pass locally but fail in CI with different Pydantic versions
**Solution:**
Locally update snapshots using the same Pydantic version that CI uses:
1. **Identify the failing Pydantic version** from CI logs (e.g., `2.7.0`, `2.8.0`, `2.9.0`)
2. **Update snapshots with that version:**
```bash
uv run --with "pydantic==2.9.0" --group test pytest tests/unit_tests/path/to/test.py::test_name --snapshot-update
```
3. **Verify compatibility across supported versions:**
```bash
# Test with the version you used to update
uv run --with "pydantic==2.9.0" --group test pytest tests/unit_tests/path/to/test.py::test_name
# Test with other supported versions
uv run --with "pydantic==2.8.0" --group test pytest tests/unit_tests/path/to/test.py::test_name
```
**Note:** Some tests use `@pytest.mark.skipif` decorators to only run with specific Pydantic version ranges (e.g., `PYDANTIC_VERSION_AT_LEAST_210`). Make sure to understand these constraints when updating snapshots.
## Coverage
Code coverage (i.e. the amount of code that is covered by unit tests) helps identify areas of the code that are potentially more or less brittle.

View File

@@ -13,7 +13,7 @@ necessary before merging it. Oftentimes, it is more efficient for the
maintainers to make these changes themselves before merging, rather than asking you
to do so in code review.
By default, most pull requests will have a
By default, most pull requests will have a
`✅ Maintainers are allowed to edit this pull request.`
badge in the right-hand sidebar.

View File

@@ -2,4 +2,4 @@
- [**Repository Structure**](repo_structure.mdx): Understand the high level structure of the repository.
- [**Review Process**](review_process.mdx): Learn about the review process for pull requests.
- [**Frequently Asked Questions (FAQ)**](faq.mdx): Get answers to common questions about contributing.
- [**Frequently Asked Questions (FAQ)**](faq.mdx): Get answers to common questions about contributing.

View File

@@ -8,7 +8,7 @@ This document outlines the process used by the LangChain maintainers for reviewi
We categorize PRs using three main statuses, which are marked as project item statuses in the right sidebar and can be viewed in detail [here](https://github.com/orgs/langchain-ai/projects/12/views/1).
- **Triage**:
- **Triage**:
- Initial status for all newly submitted PRs.
- Requires a maintainer to categorize it into one of the other statuses.

View File

@@ -56,32 +56,13 @@
"text": [
"zzzz....\n",
"Hi! I just woke up. Your llm is starting\n",
"Sync handler being called in a `thread_pool_executor`: token: Here\n",
"Sync handler being called in a `thread_pool_executor`: token: 's\n",
"Sync handler being called in a `thread_pool_executor`: token: a\n",
"Sync handler being called in a `thread_pool_executor`: token: little\n",
"Sync handler being called in a `thread_pool_executor`: token: joke\n",
"Sync handler being called in a `thread_pool_executor`: token: for\n",
"Sync handler being called in a `thread_pool_executor`: token: you\n",
"Sync handler being called in a `thread_pool_executor`: token: :\n",
"Sync handler being called in a `thread_pool_executor`: token: \n",
"Sync handler being called in a `thread_pool_executor`: token: Why\n",
"Sync handler being called in a `thread_pool_executor`: token: don't scientists trust atoms?\n",
"\n",
"Why\n",
"Sync handler being called in a `thread_pool_executor`: token: can\n",
"Sync handler being called in a `thread_pool_executor`: token: 't\n",
"Sync handler being called in a `thread_pool_executor`: token: a\n",
"Sync handler being called in a `thread_pool_executor`: token: bicycle\n",
"Sync handler being called in a `thread_pool_executor`: token: stan\n",
"Sync handler being called in a `thread_pool_executor`: token: d up\n",
"Sync handler being called in a `thread_pool_executor`: token: by\n",
"Sync handler being called in a `thread_pool_executor`: token: itself\n",
"Sync handler being called in a `thread_pool_executor`: token: ?\n",
"Sync handler being called in a `thread_pool_executor`: token: Because\n",
"Sync handler being called in a `thread_pool_executor`: token: it\n",
"Sync handler being called in a `thread_pool_executor`: token: 's\n",
"Sync handler being called in a `thread_pool_executor`: token: two\n",
"Sync handler being called in a `thread_pool_executor`: token: -\n",
"Sync handler being called in a `thread_pool_executor`: token: tire\n",
"Because they make up\n",
"Sync handler being called in a `thread_pool_executor`: token: everything!\n",
"Sync handler being called in a `thread_pool_executor`: token: \n",
"zzzz....\n",
"Hi! I just woke up. Your llm is ending\n"
]
@@ -89,10 +70,10 @@
{
"data": {
"text/plain": [
"LLMResult(generations=[[ChatGeneration(text=\"Here's a little joke for you:\\n\\nWhy can't a bicycle stand up by itself? Because it's two-tire\", message=AIMessage(content=\"Here's a little joke for you:\\n\\nWhy can't a bicycle stand up by itself? Because it's two-tire\", id='run-8afc89e8-02c0-4522-8480-d96977240bd4-0'))]], llm_output={}, run=[RunInfo(run_id=UUID('8afc89e8-02c0-4522-8480-d96977240bd4'))])"
"LLMResult(generations=[[ChatGeneration(text=\"Why don't scientists trust atoms?\\n\\nBecause they make up everything!\", message=AIMessage(content=\"Why don't scientists trust atoms?\\n\\nBecause they make up everything!\", additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None}, id='run--a596349d-8a7c-45fe-8691-bb1f9cfd6c08-0', usage_metadata={'input_tokens': 11, 'output_tokens': 17, 'total_tokens': 28, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}}))]], llm_output={}, run=[RunInfo(run_id=UUID('a596349d-8a7c-45fe-8691-bb1f9cfd6c08'))], type='LLMResult')"
]
},
"execution_count": 2,
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
@@ -134,7 +115,7 @@
"# To enable streaming, we pass in `streaming=True` to the ChatModel constructor\n",
"# Additionally, we pass in a list with our custom handler\n",
"chat = ChatAnthropic(\n",
" model=\"claude-3-sonnet-20240229\",\n",
" model=\"claude-3-7-sonnet-20250219\",\n",
" max_tokens=25,\n",
" streaming=True,\n",
" callbacks=[MyCustomSyncHandler(), MyCustomAsyncHandler()],\n",
@@ -157,7 +138,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -171,7 +152,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -49,22 +49,28 @@
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Error in LoggingHandler.on_chain_start callback: AttributeError(\"'NoneType' object has no attribute 'get'\")\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Chain RunnableSequence started\n",
"Chain ChatPromptTemplate started\n",
"Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?')]\n",
"Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?', additional_kwargs={}, response_metadata={})]\n",
"Chat model started\n",
"Chat model ended, response: generations=[[ChatGeneration(text='1 + 2 = 3', message=AIMessage(content='1 + 2 = 3', response_metadata={'id': 'msg_01NTYMsH9YxkoWsiPYs4Lemn', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}}, id='run-d6bcfd72-9c94-466d-bac0-f39e456ad6e3-0'))]] llm_output={'id': 'msg_01NTYMsH9YxkoWsiPYs4Lemn', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}} run=None\n",
"Chain ended, outputs: content='1 + 2 = 3' response_metadata={'id': 'msg_01NTYMsH9YxkoWsiPYs4Lemn', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}} id='run-d6bcfd72-9c94-466d-bac0-f39e456ad6e3-0'\n"
"Chat model ended, response: generations=[[ChatGeneration(text='The sum of 1 + 2 is 3.', message=AIMessage(content='The sum of 1 + 2 is 3.', additional_kwargs={}, response_metadata={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--71edddf3-2474-42dc-ad43-fadb4882c3c8-0', usage_metadata={'input_tokens': 16, 'output_tokens': 17, 'total_tokens': 33, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}))]] llm_output={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} run=None type='LLMResult'\n",
"Chain ended, outputs: content='The sum of 1 + 2 is 3.' additional_kwargs={} response_metadata={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} id='run--71edddf3-2474-42dc-ad43-fadb4882c3c8-0' usage_metadata={'input_tokens': 16, 'output_tokens': 17, 'total_tokens': 33, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}\n"
]
},
{
"data": {
"text/plain": [
"AIMessage(content='1 + 2 = 3', response_metadata={'id': 'msg_01NTYMsH9YxkoWsiPYs4Lemn', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}}, id='run-d6bcfd72-9c94-466d-bac0-f39e456ad6e3-0')"
"AIMessage(content='The sum of 1 + 2 is 3.', additional_kwargs={}, response_metadata={'id': 'msg_01F1qPrmBD9igfzHdqVipmKX', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 17, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--71edddf3-2474-42dc-ad43-fadb4882c3c8-0', usage_metadata={'input_tokens': 16, 'output_tokens': 17, 'total_tokens': 33, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})"
]
},
"execution_count": 1,
@@ -101,7 +107,7 @@
"\n",
"\n",
"callbacks = [LoggingHandler()]\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\")\n",
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\")\n",
"prompt = ChatPromptTemplate.from_template(\"What is 1 + {number}?\")\n",
"\n",
"chain = prompt | llm\n",
@@ -127,7 +133,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -141,7 +147,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -52,16 +52,16 @@
"output_type": "stream",
"text": [
"Chat model started\n",
"Chat model ended, response: generations=[[ChatGeneration(text='1 + 2 = 3', message=AIMessage(content='1 + 2 = 3', response_metadata={'id': 'msg_01CdKsRmeS9WRb8BWnHDEHm7', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}}, id='run-2d7fdf2a-7405-4e17-97c0-67e6b2a65305-0'))]] llm_output={'id': 'msg_01CdKsRmeS9WRb8BWnHDEHm7', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}} run=None\n"
"Chat model ended, response: generations=[[ChatGeneration(text='1 + 2 = 3', message=AIMessage(content='1 + 2 = 3', additional_kwargs={}, response_metadata={'id': 'msg_01DQMbSk263KpY2vouHM5gsC', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--ab896e4e-c3fd-48b1-a41a-b6b525cbc041-0', usage_metadata={'input_tokens': 16, 'output_tokens': 13, 'total_tokens': 29, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}))]] llm_output={'id': 'msg_01DQMbSk263KpY2vouHM5gsC', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} run=None type='LLMResult'\n"
]
},
{
"data": {
"text/plain": [
"AIMessage(content='1 + 2 = 3', response_metadata={'id': 'msg_01CdKsRmeS9WRb8BWnHDEHm7', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}}, id='run-2d7fdf2a-7405-4e17-97c0-67e6b2a65305-0')"
"AIMessage(content='1 + 2 = 3', additional_kwargs={}, response_metadata={'id': 'msg_01DQMbSk263KpY2vouHM5gsC', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--ab896e4e-c3fd-48b1-a41a-b6b525cbc041-0', usage_metadata={'input_tokens': 16, 'output_tokens': 13, 'total_tokens': 29, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})"
]
},
"execution_count": 18,
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
@@ -95,7 +95,7 @@
"\n",
"\n",
"callbacks = [LoggingHandler()]\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\", callbacks=callbacks)\n",
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\", callbacks=callbacks)\n",
"prompt = ChatPromptTemplate.from_template(\"What is 1 + {number}?\")\n",
"\n",
"chain = prompt | llm\n",
@@ -119,7 +119,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -133,7 +133,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -42,25 +42,31 @@
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Error in LoggingHandler.on_chain_start callback: AttributeError(\"'NoneType' object has no attribute 'get'\")\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Chain RunnableSequence started\n",
"Chain ChatPromptTemplate started\n",
"Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?')]\n",
"Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?', additional_kwargs={}, response_metadata={})]\n",
"Chat model started\n",
"Chat model ended, response: generations=[[ChatGeneration(text='1 + 2 = 3', message=AIMessage(content='1 + 2 = 3', response_metadata={'id': 'msg_01D8Tt5FdtBk5gLTfBPm2tac', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}}, id='run-bb0dddd8-85f3-4e6b-8553-eaa79f859ef8-0'))]] llm_output={'id': 'msg_01D8Tt5FdtBk5gLTfBPm2tac', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}} run=None\n",
"Chain ended, outputs: content='1 + 2 = 3' response_metadata={'id': 'msg_01D8Tt5FdtBk5gLTfBPm2tac', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}} id='run-bb0dddd8-85f3-4e6b-8553-eaa79f859ef8-0'\n"
"Chat model ended, response: generations=[[ChatGeneration(text='1 + 2 = 3', message=AIMessage(content='1 + 2 = 3', additional_kwargs={}, response_metadata={'id': 'msg_019ieJt8K32iC77qBbQmSa9m', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--2f596356-99c9-45ef-94ff-fb170072abdf-0', usage_metadata={'input_tokens': 16, 'output_tokens': 13, 'total_tokens': 29, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}))]] llm_output={'id': 'msg_019ieJt8K32iC77qBbQmSa9m', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} run=None type='LLMResult'\n",
"Chain ended, outputs: content='1 + 2 = 3' additional_kwargs={} response_metadata={'id': 'msg_019ieJt8K32iC77qBbQmSa9m', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'} id='run--2f596356-99c9-45ef-94ff-fb170072abdf-0' usage_metadata={'input_tokens': 16, 'output_tokens': 13, 'total_tokens': 29, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}}\n"
]
},
{
"data": {
"text/plain": [
"AIMessage(content='1 + 2 = 3', response_metadata={'id': 'msg_01D8Tt5FdtBk5gLTfBPm2tac', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 13}}, id='run-bb0dddd8-85f3-4e6b-8553-eaa79f859ef8-0')"
"AIMessage(content='1 + 2 = 3', additional_kwargs={}, response_metadata={'id': 'msg_019ieJt8K32iC77qBbQmSa9m', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 13, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--2f596356-99c9-45ef-94ff-fb170072abdf-0', usage_metadata={'input_tokens': 16, 'output_tokens': 13, 'total_tokens': 29, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})"
]
},
"execution_count": 4,
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
@@ -94,7 +100,7 @@
"\n",
"\n",
"callbacks = [LoggingHandler()]\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\")\n",
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\")\n",
"prompt = ChatPromptTemplate.from_template(\"What is 1 + {number}?\")\n",
"\n",
"chain = prompt | llm\n",
@@ -118,7 +124,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -132,7 +138,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.5"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -24,7 +24,7 @@
"\n",
":::tip\n",
"\n",
"The **default** implementation does **not** provide support for token-by-token streaming, but it ensures that the the model can be swapped in for any other model as it supports the same standard interface.\n",
"The **default** implementation does **not** provide support for token-by-token streaming, but it ensures that the model can be swapped in for any other model as it supports the same standard interface.\n",
"\n",
":::\n",
"\n",

View File

@@ -49,33 +49,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"My custom handler, token: Here\n",
"My custom handler, token: 's\n",
"My custom handler, token: a\n",
"My custom handler, token: bear\n",
"My custom handler, token: joke\n",
"My custom handler, token: for\n",
"My custom handler, token: you\n",
"My custom handler, token: :\n",
"My custom handler, token: \n",
"My custom handler, token: Why\n",
"My custom handler, token: don't bears wear shoes?\n",
"\n",
"Why\n",
"My custom handler, token: di\n",
"My custom handler, token: d the\n",
"My custom handler, token: bear\n",
"My custom handler, token: dissol\n",
"My custom handler, token: ve\n",
"My custom handler, token: in\n",
"My custom handler, token: water\n",
"My custom handler, token: ?\n",
"My custom handler, token: \n",
"Because\n",
"My custom handler, token: it\n",
"My custom handler, token: was\n",
"My custom handler, token: a\n",
"My custom handler, token: polar\n",
"My custom handler, token: bear\n",
"My custom handler, token: !\n"
"Because they\n",
"My custom handler, token: prefer to go bear-foot!\n",
"My custom handler, token: \n"
]
}
],
@@ -95,7 +75,7 @@
"# To enable streaming, we pass in `streaming=True` to the ChatModel constructor\n",
"# Additionally, we pass in our custom handler as a list to the callbacks parameter\n",
"model = ChatAnthropic(\n",
" model=\"claude-3-sonnet-20240229\", streaming=True, callbacks=[MyCustomHandler()]\n",
" model=\"claude-3-7-sonnet-20250219\", streaming=True, callbacks=[MyCustomHandler()]\n",
")\n",
"\n",
"chain = prompt | model\n",
@@ -119,7 +99,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -133,7 +113,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.5"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -30,7 +30,7 @@
"id": "e3cdb7bb-1f58-4a7a-af83-599443127834",
"metadata": {},
"source": [
"`DirectoryLoader` accepts a `loader_cls` kwarg, which defaults to [UnstructuredLoader](/docs/integrations/document_loaders/unstructured_file). [Unstructured](https://unstructured-io.github.io/unstructured/) supports parsing for a number of formats, such as PDF and HTML. Here we use it to read in a markdown (.md) file.\n",
"`DirectoryLoader` accepts a `loader_cls` kwarg, which defaults to [UnstructuredLoader](/docs/integrations/document_loaders/unstructured_file). [Unstructured](https://docs.unstructured.io/) supports parsing for a number of formats, such as PDF and HTML. Here we use it to read in a markdown (.md) file.\n",
"\n",
"We can use the `glob` parameter to control which files to load. Note that here it doesn't load the `.rst` file or the `.html` files."
]

View File

@@ -4,14 +4,14 @@
[JSON Lines](https://jsonlines.org/) is a file format where each line is a valid JSON value.
LangChain implements a [JSONLoader](https://python.langchain.com/api_reference/community/document_loaders/langchain_community.document_loaders.json_loader.JSONLoader.html)
to convert JSON and JSONL data into LangChain [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html#langchain_core.documents.base.Document)
objects. It uses a specified [jq schema](https://en.wikipedia.org/wiki/Jq_(programming_language)) to parse the JSON files, allowing for the extraction of specific fields into the content
LangChain implements a [JSONLoader](https://python.langchain.com/api_reference/community/document_loaders/langchain_community.document_loaders.json_loader.JSONLoader.html)
to convert JSON and JSONL data into LangChain [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html#langchain_core.documents.base.Document)
objects. It uses a specified [jq schema](https://en.wikipedia.org/wiki/Jq_(programming_language)) to parse the JSON files, allowing for the extraction of specific fields into the content
and metadata of the LangChain Document.
It uses the `jq` python package. Check out this [manual](https://stedolan.github.io/jq/manual/#Basicfilters) for a detailed documentation of the `jq` syntax.
Here we will demonstrate:
Here we will demonstrate:
- How to load JSON and JSONL data into the content of a LangChain `Document`;
- How to load JSON and JSONL data into metadata associated with a `Document`.
@@ -194,7 +194,7 @@ pprint(data)
### JSON file with jq schema `content_key`
To load documents from a JSON file using the content_key within the jq schema, set is_content_key_jq_parsable=True.
To load documents from a JSON file using the content_key within the jq schema, set is_content_key_jq_parsable=True.
Ensure that content_key is compatible and can be parsed using the jq schema.
```python

View File

@@ -2,14 +2,14 @@
The [Microsoft Office](https://www.office.com/) suite of productivity software includes Microsoft Word, Microsoft Excel, Microsoft PowerPoint, Microsoft Outlook, and Microsoft OneNote. It is available for Microsoft Windows and macOS operating systems. It is also available on Android and iOS.
This covers how to load commonly used file formats including `DOCX`, `XLSX` and `PPTX` documents into a LangChain
This covers how to load commonly used file formats including `DOCX`, `XLSX` and `PPTX` documents into a LangChain
[Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html#langchain_core.documents.base.Document)
object that we can use downstream.
## Loading DOCX, XLSX, PPTX with AzureAIDocumentIntelligenceLoader
[Azure AI Document Intelligence](https://aka.ms/doc-intelligence) (formerly known as `Azure Form Recognizer`) is machine-learning
[Azure AI Document Intelligence](https://aka.ms/doc-intelligence) (formerly known as `Azure Form Recognizer`) is machine-learning
based service that extracts texts (including handwriting), tables, document structures (e.g., titles, section headings, etc.) and key-value-pairs from
digital or scanned PDFs, images, Office and HTML files. Document Intelligence supports `PDF`, `JPEG/JPG`, `PNG`, `BMP`, `TIFF`, `HEIF`, `DOCX`, `XLSX`, `PPTX` and `HTML`.

View File

@@ -35,7 +35,7 @@
"\n",
"from langchain_anthropic import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\")"
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\")"
]
},
{
@@ -47,10 +47,10 @@
{
"data": {
"text/plain": [
"\"According to the context provided, Egypt's population in 2024 is estimated to be about 111 million.\""
"\"Egypt's population in 2024 is about 111 million.\""
]
},
"execution_count": 10,
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -142,13 +142,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"What\n",
" is\n",
" the\n",
" population\n",
" of\n",
" Egypt\n",
"?\n"
" is the population of Egypt?\n",
"\n"
]
}
],
@@ -168,9 +165,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "poetry-venv-2",
"display_name": "langchain",
"language": "python",
"name": "poetry-venv-2"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
@@ -182,7 +179,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -323,7 +323,7 @@
"source": [
"## RAG based approach\n",
"\n",
"Another simple idea is to chunk up the text, but instead of extracting information from every chunk, just focus on the the most relevant chunks.\n",
"Another simple idea is to chunk up the text, but instead of extracting information from every chunk, just focus on the most relevant chunks.\n",
"\n",
":::caution\n",
"It can be difficult to identify which chunks are relevant.\n",

View File

@@ -42,7 +42,7 @@
"\n",
"from langchain_anthropic.chat_models import ChatAnthropic\n",
"\n",
"model = ChatAnthropic(model_name=\"claude-3-sonnet-20240229\", temperature=0)"
"model = ChatAnthropic(model_name=\"claude-3-7-sonnet-20250219\", temperature=0)"
]
},
{
@@ -200,7 +200,7 @@
{
"data": {
"text/plain": [
"People(people=[Person(name='Anna', height_in_meters=1.83)])"
"People(people=[Person(name='Anna', height_in_meters=1.8288)])"
]
},
"execution_count": 5,
@@ -242,7 +242,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"id": "b1f11912-c1bb-4a2a-a482-79bf3996961f",
"metadata": {
"execution": {
@@ -359,14 +359,6 @@
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/bagatur/langchain/.venv/lib/python3.11/site-packages/pydantic/_internal/_fields.py:201: UserWarning: Field name \"schema\" in \"PromptInput\" shadows an attribute in parent \"BaseModel\"\n",
" warnings.warn(\n"
]
},
{
"data": {
"text/plain": [
@@ -397,7 +389,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -411,7 +403,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -23,11 +23,11 @@
{
"data": {
"text/plain": [
"[HumanMessage(content='example input', name='example_user', id='2'),\n",
" HumanMessage(content='real input', name='bob', id='4')]"
"[HumanMessage(content='example input', additional_kwargs={}, response_metadata={}, name='example_user', id='2'),\n",
" HumanMessage(content='real input', additional_kwargs={}, response_metadata={}, name='bob', id='4')]"
]
},
"execution_count": 1,
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -60,12 +60,12 @@
{
"data": {
"text/plain": [
"[SystemMessage(content='you are a good assistant', id='1'),\n",
" HumanMessage(content='real input', name='bob', id='4'),\n",
" AIMessage(content='real output', name='alice', id='5')]"
"[SystemMessage(content='you are a good assistant', additional_kwargs={}, response_metadata={}, id='1'),\n",
" HumanMessage(content='real input', additional_kwargs={}, response_metadata={}, name='bob', id='4'),\n",
" AIMessage(content='real output', additional_kwargs={}, response_metadata={}, name='alice', id='5')]"
]
},
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -83,12 +83,12 @@
{
"data": {
"text/plain": [
"[HumanMessage(content='example input', name='example_user', id='2'),\n",
" HumanMessage(content='real input', name='bob', id='4'),\n",
" AIMessage(content='real output', name='alice', id='5')]"
"[HumanMessage(content='example input', additional_kwargs={}, response_metadata={}, name='example_user', id='2'),\n",
" HumanMessage(content='real input', additional_kwargs={}, response_metadata={}, name='bob', id='4'),\n",
" AIMessage(content='real output', additional_kwargs={}, response_metadata={}, name='alice', id='5')]"
]
},
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -104,7 +104,7 @@
"source": [
"## Chaining\n",
"\n",
"`filter_messages` can be used in an imperatively (like above) or declaratively, making it easy to compose with other components in a chain:"
"`filter_messages` can be used imperatively (like above) or declaratively, making it easy to compose with other components in a chain:"
]
},
{
@@ -126,10 +126,10 @@
{
"data": {
"text/plain": [
"AIMessage(content=[], response_metadata={'id': 'msg_01Wz7gBHahAwkZ1KCBNtXmwA', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 16, 'output_tokens': 3}}, id='run-b5d8a3fe-004f-4502-a071-a6c025031827-0', usage_metadata={'input_tokens': 16, 'output_tokens': 3, 'total_tokens': 19})"
"AIMessage(content=[], additional_kwargs={}, response_metadata={'id': 'msg_01At8GtCiJ79M29yvNwCiQaB', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 16, 'output_tokens': 3, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--b3db2b91-0edf-4c48-99e7-35e641b8229d-0', usage_metadata={'input_tokens': 16, 'output_tokens': 3, 'total_tokens': 19, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})"
]
},
"execution_count": 4,
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -137,7 +137,7 @@
"source": [
"from langchain_anthropic import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)\n",
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\", temperature=0)\n",
"# Notice we don't pass in messages. This creates\n",
"# a RunnableLambda that takes messages as input\n",
"filter_ = filter_messages(exclude_names=[\"example_user\", \"example_assistant\"])\n",
@@ -164,8 +164,9 @@
{
"data": {
"text/plain": [
"[HumanMessage(content='real input', name='bob', id='4'),\n",
" AIMessage(content='real output', name='alice', id='5')]"
"[SystemMessage(content='you are a good assistant', additional_kwargs={}, response_metadata={}, id='1'),\n",
" HumanMessage(content='real input', additional_kwargs={}, response_metadata={}, name='bob', id='4'),\n",
" AIMessage(content='real output', additional_kwargs={}, response_metadata={}, name='alice', id='5')]"
]
},
"execution_count": 6,
@@ -190,9 +191,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "poetry-venv-2",
"display_name": "langchain",
"language": "python",
"name": "poetry-venv-2"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
@@ -204,7 +205,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -122,13 +122,13 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"from langchain_experimental.graph_transformers import LLMGraphTransformer\n",
"# from langchain_experimental.graph_transformers import LLMGraphTransformer\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"llm = ChatOpenAI(temperature=0, model_name=\"gpt-4-turbo\")\n",

View File

@@ -172,7 +172,7 @@ Indexing is the process of keeping your vectorstore in-sync with the underlying
### Tools
LangChain [Tools](/docs/concepts/tools) contain a description of the tool (to pass to the language model) as well as the implementation of the function to call. Refer [here](/docs/integrations/tools/) for a list of pre-built tools.
LangChain [Tools](/docs/concepts/tools) contain a description of the tool (to pass to the language model) as well as the implementation of the function to call. Refer [here](/docs/integrations/tools/) for a list of pre-built tools.
- [How to: create tools](/docs/how_to/custom_tools)
- [How to: use built-in tools and toolkits](/docs/how_to/tools_builtin)

View File

@@ -199,7 +199,7 @@
"outputs": [],
"source": [
"def _clear():\n",
" \"\"\"Hacky helper method to clear content. See the `full` mode section to to understand why it works.\"\"\"\n",
" \"\"\"Hacky helper method to clear content. See the `full` mode section to understand why it works.\"\"\"\n",
" index([], record_manager, vectorstore, cleanup=\"full\", source_id_key=\"source\")"
]
},

View File

@@ -88,7 +88,7 @@
"source": [
"## Chaining\n",
"\n",
"`merge_message_runs` can be used in an imperatively (like above) or declaratively, making it easy to compose with other components in a chain:"
"`merge_message_runs` can be used imperatively (like above) or declaratively, making it easy to compose with other components in a chain:"
]
},
{
@@ -97,20 +97,13 @@
"id": "6d5a0283-11f8-435b-b27b-7b18f7693592",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Note: you may need to restart the kernel to use updated packages.\n"
]
},
{
"data": {
"text/plain": [
"AIMessage(content=[], additional_kwargs={}, response_metadata={'id': 'msg_01KNGUMTuzBVfwNouLDpUMwf', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 84, 'output_tokens': 3}}, id='run-b908b198-9c24-450b-9749-9d4a8182937b-0', usage_metadata={'input_tokens': 84, 'output_tokens': 3, 'total_tokens': 87})"
"AIMessage(content='\\n\\nAs for the actual answer, LangChain is named for connecting (chaining) language models together with other components. And Harrison Chase is one of the co-founders of LangChain, not someone being chased! \\n\\nBut I like to think he\\'s running after runaway tokens that escaped from the embedding space. \"Come back here, you vectors!\"', additional_kwargs={}, response_metadata={'id': 'msg_018MF8xBrM1ztw69XTx3Uxcy', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 84, 'output_tokens': 80, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--caa1b9d6-a554-40ad-95cd-268938d8223b-0', usage_metadata={'input_tokens': 84, 'output_tokens': 80, 'total_tokens': 164, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})"
]
},
"execution_count": 9,
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -118,7 +111,7 @@
"source": [
"from langchain_anthropic import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)\n",
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\", temperature=0)\n",
"# Notice we don't pass in messages. This creates\n",
"# a RunnableLambda that takes messages as input\n",
"merger = merge_message_runs()\n",
@@ -150,7 +143,7 @@
" AIMessage(content='Well, I guess they thought \"WordRope\" and \"SentenceString\" just didn\\'t have the same ring to it!\\nWhy, he\\'s probably chasing after the last cup of coffee in the office!', additional_kwargs={}, response_metadata={})]"
]
},
"execution_count": 10,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -176,10 +169,10 @@
{
"data": {
"text/plain": [
"AIMessage(content='A convergent series is an infinite series whose partial sums approach a finite value as more terms are added. In other words, the sequence of partial sums has a limit.\\n\\nMore formally, an infinite series Σ an (where an are the terms of the series) is said to be convergent if the sequence of partial sums:\\n\\nS1 = a1\\nS2 = a1 + a2 \\nS3 = a1 + a2 + a3\\n...\\nSn = a1 + a2 + a3 + ... + an\\n...\\n\\nconverges to some finite number S as n goes to infinity. We write:\\n\\nlim n→∞ Sn = S\\n\\nThe finite number S is called the sum of the convergent infinite series.\\n\\nIf the sequence of partial sums does not approach any finite limit, the infinite series is said to be divergent.\\n\\nSome key properties:\\n- A series converges if and only if the sequence of its partial sums is a Cauchy sequence.\\n- Absolute/conditional convergence criteria help determine if a given series converges.\\n- Convergent series have many important applications in mathematics, physics, engineering etc.', additional_kwargs={}, response_metadata={'id': 'msg_01MfV6y2hep7ZNvDz24A36U4', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 29, 'output_tokens': 267}}, id='run-9d925f58-021e-4bd0-94fc-f8f5e91010a4-0', usage_metadata={'input_tokens': 29, 'output_tokens': 267, 'total_tokens': 296})"
"AIMessage(content=\"# Definition of a Convergent Series\\n\\nA series is a sum of terms in a sequence, typically written as:\\n\\n$$\\\\sum_{n=1}^{\\\\infty} a_n = a_1 + a_2 + a_3 + \\\\ldots$$\\n\\nA series is called **convergent** if the sequence of partial sums approaches a finite limit.\\n\\n## Formal Definition\\n\\nLet's define the sequence of partial sums:\\n$$S_N = \\\\sum_{n=1}^{N} a_n = a_1 + a_2 + \\\\ldots + a_N$$\\n\\nA series $\\\\sum_{n=1}^{\\\\infty} a_n$ is convergent if and only if:\\n- The limit of the partial sums exists and is finite\\n- That is, there exists a finite number $S$ such that $\\\\lim_{N \\\\to \\\\infty} S_N = S$\\n\\nIf this limit exists, we say the series converges to $S$, and we write:\\n$$\\\\sum_{n=1}^{\\\\infty} a_n = S$$\\n\\nIf the limit doesn't exist or is infinite, the series is called divergent.\", additional_kwargs={}, response_metadata={'id': 'msg_018ypyi2MTjV6S7jCydSqDn9', 'model': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 29, 'output_tokens': 273, 'server_tool_use': None, 'service_tier': 'standard'}, 'model_name': 'claude-3-7-sonnet-20250219'}, id='run--5de0ca29-d031-48f7-bc75-671eade20b74-0', usage_metadata={'input_tokens': 29, 'output_tokens': 273, 'total_tokens': 302, 'input_token_details': {'cache_read': 0, 'cache_creation': 0}})"
]
},
"execution_count": 14,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -203,7 +196,7 @@
"id": "51ba533a-43c7-4e5f-bd91-a4ec23ceeb34",
"metadata": {},
"source": [
"LangSmith Trace: https://smith.langchain.com/public/432150b6-9909-40a7-8ae7-944b7e657438/r/f4ad5fb2-4d38-42a6-b780-25f62617d53f"
"[LangSmith Trace](https://smith.langchain.com/public/432150b6-9909-40a7-8ae7-944b7e657438/r/f4ad5fb2-4d38-42a6-b780-25f62617d53f)"
]
},
{
@@ -213,15 +206,15 @@
"source": [
"## API reference\n",
"\n",
"For a complete description of all arguments head to the API reference: https://python.langchain.com/api_reference/core/messages/langchain_core.messages.utils.merge_message_runs.html"
"For a complete description of all arguments head to the [API reference](https://python.langchain.com/api_reference/core/messages/langchain_core.messages.utils.merge_message_runs.html)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "poetry-venv-2",
"display_name": "langchain",
"language": "python",
"name": "poetry-venv-2"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
@@ -233,7 +226,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -373,7 +373,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"id": "a0b91b29-dbd6-4c94-8f24-05471adc7598",
"metadata": {},
"outputs": [
@@ -397,7 +397,7 @@
"\n",
"\n",
"# Pass to LLM\n",
"llm = init_chat_model(\"google_genai:gemini-2.0-flash-001\")\n",
"llm = init_chat_model(\"google_genai:gemini-2.5-flash\")\n",
"\n",
"message = {\n",
" \"role\": \"user\",\n",

View File

@@ -23,17 +23,18 @@
{
"data": {
"text/plain": [
"{'token_usage': {'completion_tokens': 110,\n",
"{'token_usage': {'completion_tokens': 88,\n",
" 'prompt_tokens': 16,\n",
" 'total_tokens': 126,\n",
" 'total_tokens': 104,\n",
" 'completion_tokens_details': {'accepted_prediction_tokens': 0,\n",
" 'audio_tokens': 0,\n",
" 'reasoning_tokens': 0,\n",
" 'rejected_prediction_tokens': 0},\n",
" 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}},\n",
" 'model_name': 'gpt-4o-mini-2024-07-18',\n",
" 'system_fingerprint': 'fp_b8bc95a0ac',\n",
" 'id': 'chatcmpl-BDrISvLar6AqcZngBmhajFZXVc2u9',\n",
" 'system_fingerprint': 'fp_34a54ae93c',\n",
" 'id': 'chatcmpl-ByN1Qkvqb5fAGKKzXXxZ3rBlnqkWs',\n",
" 'service_tier': 'default',\n",
" 'finish_reason': 'stop',\n",
" 'logprobs': None}"
]
@@ -68,15 +69,17 @@
{
"data": {
"text/plain": [
"{'id': 'msg_01JHnvPqgERY7MZwrvfkmq52',\n",
" 'model': 'claude-3-5-sonnet-20241022',\n",
"{'id': 'msg_01NTWnqvbNKSjGfqQL7xikau',\n",
" 'model': 'claude-3-7-sonnet-20250219',\n",
" 'stop_reason': 'end_turn',\n",
" 'stop_sequence': None,\n",
" 'usage': {'cache_creation_input_tokens': 0,\n",
" 'cache_read_input_tokens': 0,\n",
" 'input_tokens': 17,\n",
" 'output_tokens': 221},\n",
" 'model_name': 'claude-3-5-sonnet-20241022'}"
" 'output_tokens': 197,\n",
" 'server_tool_use': None,\n",
" 'service_tier': 'standard'},\n",
" 'model_name': 'claude-3-7-sonnet-20250219'}"
]
},
"execution_count": 2,
@@ -87,7 +90,7 @@
"source": [
"from langchain_anthropic import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(model=\"claude-3-5-sonnet-latest\")\n",
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\")\n",
"msg = llm.invoke(\"What's the oldest known example of cuneiform\")\n",
"msg.response_metadata"
]
@@ -97,30 +100,22 @@
"id": "c1f24f69-18f6-43c1-8b26-3f88ec515259",
"metadata": {},
"source": [
"## Google VertexAI"
"## Google Generative AI"
]
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "39549336-25f5-4839-9846-f687cd77e59b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'is_blocked': False,\n",
" 'safety_ratings': [],\n",
" 'usage_metadata': {'prompt_token_count': 10,\n",
" 'candidates_token_count': 55,\n",
" 'total_token_count': 65,\n",
" 'prompt_tokens_details': [{'modality': 1, 'token_count': 10}],\n",
" 'candidates_tokens_details': [{'modality': 1, 'token_count': 55}],\n",
" 'cached_content_token_count': 0,\n",
" 'cache_tokens_details': []},\n",
"{'prompt_feedback': {'block_reason': 0, 'safety_ratings': []},\n",
" 'finish_reason': 'STOP',\n",
" 'avg_logprobs': -0.251378042047674,\n",
" 'model_name': 'gemini-2.0-flash-001'}"
" 'model_name': 'gemini-2.5-flash',\n",
" 'safety_ratings': []}"
]
},
"execution_count": 1,
@@ -129,9 +124,9 @@
}
],
"source": [
"from langchain_google_vertexai import ChatVertexAI\n",
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
"\n",
"llm = ChatVertexAI(model=\"gemini-2.0-flash-001\")\n",
"llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\")\n",
"msg = llm.invoke(\"What's the oldest known example of cuneiform\")\n",
"msg.response_metadata"
]
@@ -173,7 +168,7 @@
"source": [
"from langchain_aws import ChatBedrockConverse\n",
"\n",
"llm = ChatBedrockConverse(model=\"anthropic.claude-3-sonnet-20240229-v1:0\")\n",
"llm = ChatBedrockConverse(model=\"anthropic.claude-3-7-sonnet-20250219-v1:0\")\n",
"msg = llm.invoke(\"What's the oldest known example of cuneiform\")\n",
"msg.response_metadata"
]
@@ -196,14 +191,14 @@
"data": {
"text/plain": [
"{'token_usage': {'prompt_tokens': 13,\n",
" 'total_tokens': 219,\n",
" 'completion_tokens': 206},\n",
" 'total_tokens': 306,\n",
" 'completion_tokens': 293},\n",
" 'model_name': 'mistral-small-latest',\n",
" 'model': 'mistral-small-latest',\n",
" 'finish_reason': 'stop'}"
]
},
"execution_count": 5,
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
@@ -301,7 +296,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -315,7 +310,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -74,12 +74,12 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"id": "a88ff70c",
"metadata": {},
"outputs": [],
"source": [
"from langchain_experimental.text_splitter import SemanticChunker\n",
"# from langchain_experimental.text_splitter import SemanticChunker\n",
"from langchain_openai.embeddings import OpenAIEmbeddings\n",
"\n",
"text_splitter = SemanticChunker(OpenAIEmbeddings())"

View File

@@ -61,7 +61,7 @@
"if \"ANTHROPIC_API_KEY\" not in os.environ:\n",
" os.environ[\"ANTHROPIC_API_KEY\"] = getpass()\n",
"\n",
"model = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)"
"model = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\", temperature=0)"
]
},
{
@@ -93,7 +93,7 @@
{
"data": {
"text/plain": [
"\"Here's a bear joke for you:\\n\\nWhy did the bear dissolve in water?\\nBecause it was a polar bear!\""
"\"Why don't bears wear shoes?\\n\\nBecause they prefer to go bear-foot!\""
]
},
"execution_count": 3,
@@ -128,7 +128,7 @@
{
"data": {
"text/plain": [
"'Haha, that\\'s a clever play on words! Using \"polar\" to imply the bear dissolved or became polar/polarized when put in water. Not the most hilarious joke ever, but it has a cute, groan-worthy pun that makes it mildly amusing. I appreciate a good pun or wordplay joke.'"
"'Yes, that\\'s a funny joke! It\\'s a classic pun that plays on the homophone pair \"bare-foot\" and \"bear-foot.\" The humor comes from:\\n\\n1. The wordplay between \"barefoot\" (not wearing shoes) and \"bear-foot\" (the foot of a bear)\\n2. The logical connection to the setup (bears don\\'t wear shoes)\\n3. It\\'s family-friendly and accessible\\n4. It\\'s a simple, clean pun that creates an unexpected but satisfying punchline\\n\\nIt\\'s the kind of joke that might make you groan and smile at the same time - what people often call a \"dad joke.\"'"
]
},
"execution_count": 4,
@@ -161,7 +161,7 @@
{
"data": {
"text/plain": [
"\"Haha, that's a cute and punny joke! I like how it plays on the idea of beets blushing or turning red like someone blushing. Food puns can be quite amusing. While not a total knee-slapper, it's a light-hearted, groan-worthy dad joke that would make me chuckle and shake my head. Simple vegetable humor!\""
"'Yes, that\\'s a cute and funny joke! It works well because:\\n\\n1. It plays on the double meaning of \"roots\" - both the literal roots of the beet plant and the metaphorical sense of knowing one\\'s origins or foundation\\n2. It\\'s a simple, clean pun that doesn\\'t rely on offensive content\\n3. It has a satisfying logical connection (beets are root vegetables)\\n\\nIt\\'s the kind of wholesome food pun that might make people groan a little but also smile. Perfect for sharing in casual conversation or with kids!'"
]
},
"execution_count": 5,
@@ -205,7 +205,7 @@
{
"data": {
"text/plain": [
"\"I cannot reproduce any copyrighted material verbatim, but I can try to analyze the humor in the joke you provided without quoting it directly.\\n\\nThe joke plays on the idea that the Cylon raiders, who are the antagonists in the Battlestar Galactica universe, failed to locate the human survivors after attacking their home planets (the Twelve Colonies) due to using an outdated and poorly performing operating system (Windows Vista) for their targeting systems.\\n\\nThe humor stems from the juxtaposition of a futuristic science fiction setting with a relatable real-world frustration the use of buggy, slow, or unreliable software or technology. It pokes fun at the perceived inadequacies of Windows Vista, which was widely criticized for its performance issues and other problems when it was released.\\n\\nBy attributing the Cylons' failure to locate the humans to their use of Vista, the joke creates an amusing and unexpected connection between a fictional advanced race of robots and a familiar technological annoyance experienced by many people in the real world.\\n\\nOverall, the joke relies on incongruity and relatability to generate humor, but without reproducing any copyrighted material directly.\""
"\"This joke is moderately funny! It plays on Battlestar Galactica lore where Cylons are robots with 12 different models trying to infiltrate human society. The humor comes from the idea of a Cylon accidentally revealing their non-human nature through a pickup line that references their artificial origins. It's a decent nerd-culture joke that would land well with fans of the show, though someone unfamiliar with Battlestar Galactica might not get the reference. The punchline effectively highlights the contradiction in a Cylon trying to blend in while simultaneously revealing their true identity.\""
]
},
"execution_count": 6,
@@ -256,7 +256,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -270,7 +270,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -612,56 +612,11 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": null,
"id": "35ea904e-795f-411b-bef8-6484dbb6e35c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3m\n",
"Invoking: `python_repl_ast` with `{'query': \"df[['Age', 'Fare']].corr().iloc[0,1]\"}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m0.11232863699941621\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `python_repl_ast` with `{'query': \"df[['Fare', 'Survived']].corr().iloc[0,1]\"}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m0.2561785496289603\u001b[0m\u001b[32;1m\u001b[1;3mThe correlation between Age and Fare is approximately 0.112, and the correlation between Fare and Survival is approximately 0.256.\n",
"\n",
"Therefore, the correlation between Fare and Survival (0.256) is greater than the correlation between Age and Fare (0.112).\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': \"What's the correlation between age and fare? is that greater than the correlation between fare and survival?\",\n",
" 'output': 'The correlation between Age and Fare is approximately 0.112, and the correlation between Fare and Survival is approximately 0.256.\\n\\nTherefore, the correlation between Fare and Survival (0.256) is greater than the correlation between Age and Fare (0.112).'}"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_experimental.agents import create_pandas_dataframe_agent\n",
"\n",
"agent = create_pandas_dataframe_agent(\n",
" llm, df, agent_type=\"openai-tools\", verbose=True, allow_dangerous_code=True\n",
")\n",
"agent.invoke(\n",
" {\n",
" \"input\": \"What's the correlation between age and fare? is that greater than the correlation between fare and survival?\"\n",
" }\n",
")"
]
"outputs": [],
"source": "from langchain_experimental.agents import create_pandas_dataframe_agent\n\nagent = create_pandas_dataframe_agent(\n llm, df, agent_type=\"openai-tools\", verbose=True, allow_dangerous_code=True\n)\nagent.invoke(\n {\n \"input\": \"What's the correlation between age and fare? is that greater than the correlation between fare and survival?\"\n }\n)"
},
{
"cell_type": "markdown",
@@ -786,4 +741,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}

View File

@@ -79,18 +79,7 @@
"execution_count": 1,
"id": "f123bdcb-8c8b-440c-9bbd-aa5ed4e9cd17",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"outputs": [],
"source": [
"# | output: false\n",
"# | echo: false\n",
@@ -110,7 +99,7 @@
"\n",
"from langchain_anthropic import ChatAnthropic\n",
"\n",
"model = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)"
"model = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\", temperature=0)"
]
},
{
@@ -131,7 +120,14 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The| sky| appears| blue| during| the| day|.|"
"|The sky typically| appears blue during the day due to a phenomenon| called Rayleigh scattering, where| air molecules scatter sunlight, with| blue light being scattered more than other colors. However|, the sky's color can vary|:\n",
"\n",
"- At sunrise/sunset:| Red, orange, pink, or purple\n",
"-| During storms: Gray or dark blue|\n",
"- At night: Dark| blue to black\n",
"- In certain| atmospheric conditions: White, yellow, or green| (rare)\n",
"\n",
"The color we perceive depends| on weather conditions, time of day, pollution| levels, and our viewing angle.||"
]
}
],
@@ -160,7 +156,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The| sky| appears| blue| during| the| day|.|"
"|The sky typically| appears blue during the day due to a phenomenon called Rayleigh| scattering, where air molecules scatter sunlight,| with blue light being scattered more than other colors. However|, the sky's color can vary - appearing re|d, orange, or pink during sunrise and sunset,| gray on cloudy days, and black at night.| The color you see depends on the time of| day, weather conditions, and your location.||"
]
}
],
@@ -188,10 +184,10 @@
{
"data": {
"text/plain": [
"AIMessageChunk(content='The', id='run-b36bea64-5511-4d7a-b6a3-a07b3db0c8e7')"
"AIMessageChunk(content='', additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219'}, id='run--c4f01565-8bb4-4f07-9b23-acfe46cbeca3', usage_metadata={'input_tokens': 13, 'output_tokens': 0, 'total_tokens': 13, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})"
]
},
"execution_count": 4,
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -219,10 +215,10 @@
{
"data": {
"text/plain": [
"AIMessageChunk(content='The sky appears blue during', id='run-b36bea64-5511-4d7a-b6a3-a07b3db0c8e7')"
"AIMessageChunk(content='The sky typically appears blue during the day due to a phenomenon called Rayleigh scattering, where air molecules scatter sunlight, with blue light being scattered more than other colors. However', additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219'}, id='run--c4f01565-8bb4-4f07-9b23-acfe46cbeca3', usage_metadata={'input_tokens': 13, 'output_tokens': 0, 'total_tokens': 13, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})"
]
},
"execution_count": 5,
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@@ -259,17 +255,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Here|'s| a| joke| about| a| par|rot|:|\n",
"|Why| don't parrots use the internet?\n",
"\n",
"A man| goes| to| a| pet| shop| to| buy| a| par|rot|.| The| shop| owner| shows| him| two| stunning| pa|rr|ots| with| beautiful| pl|um|age|.|\n",
"\n",
"\"|There|'s| a| talking| par|rot| an|d a| non|-|talking| par|rot|,\"| the| owner| says|.| \"|The| talking| par|rot| costs| $|100|,| an|d the| non|-|talking| par|rot| is| $|20|.\"|\n",
"\n",
"The| man| says|,| \"|I|'ll| take| the| non|-|talking| par|rot| at| $|20|.\"|\n",
"\n",
"He| pays| an|d leaves| with| the| par|rot|.| As| he|'s| walking| down| the| street|,| the| par|rot| looks| up| at| him| an|d says|,| \"|You| know|,| you| really| are| a| stupi|d man|!\"|\n",
"\n",
"The| man| is| stun|ne|d an|d looks| at| the| par|rot| in| dis|bel|ief|.| The| par|rot| continues|,| \"|Yes|,| you| got| r|ippe|d off| big| time|!| I| can| talk| just| as| well| as| that| other| par|rot|,| an|d you| only| pai|d $|20| |for| me|!\"|"
"They|'re afraid of getting a virus from all the tweets|!||"
]
}
],
@@ -337,26 +325,14 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{}\n",
"{'countries': []}\n",
"{'countries': [{}]}\n",
"{'countries': [{'name': ''}]}\n",
"{'countries': [{'name': 'France'}]}\n",
"{'countries': [{'name': 'France', 'population': 67}]}\n",
"{'countries': [{'name': 'France', 'population': 67413}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': ''}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain'}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}, {}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}, {'name': ''}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}, {'name': 'Japan'}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}, {'name': 'Japan', 'population': 125}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}, {'name': 'Japan', 'population': 125584}]}\n",
"{'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351567}, {'name': 'Japan', 'population': 125584000}]}\n"
"{'countries': [{'name': 'France', 'population': 67750}]}\n",
"{'countries': [{'name': 'France', 'population': 67750000}, {}]}\n",
"{'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain'}]}\n",
"{'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {}]}\n",
"{'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan'}]}\n",
"{'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan', 'population': 125700000}]}\n"
]
}
],
@@ -539,11 +515,11 @@
{
"data": {
"text/plain": [
"[[Document(page_content='harrison worked at kensho'),\n",
" Document(page_content='harrison likes spicy food')]]"
"[[Document(id='2740a247-9738-48c4-8c8f-d879d4ed39f7', metadata={}, page_content='harrison worked at kensho'),\n",
" Document(id='1d3d012f-1cb0-4bee-928a-c8bf0f8b1b92', metadata={}, page_content='harrison likes spicy food')]]"
]
},
"execution_count": 10,
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
@@ -614,15 +590,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Base|d on| the| given| context|,| Harrison| worke|d at| K|ens|ho|.|\n",
"|Base|d on the provided context, Harrison worked at Kens|ho.\n",
"\n",
"Here| are| |3| |made| up| sentences| about| this| place|:|\n",
"Three made up sentences about Kens|ho:\n",
"\n",
"1|.| K|ens|ho| was| a| cutting|-|edge| technology| company| known| for| its| innovative| solutions| in| artificial| intelligence| an|d data| analytics|.|\n",
"1. Kensho is a| cutting-edge technology company that specializes in| AI and data analytics for financial institutions.\n",
"\n",
"2|.| The| modern| office| space| at| K|ens|ho| feature|d open| floor| plans|,| collaborative| work|sp|aces|,| an|d a| vib|rant| atmosphere| that| fos|tere|d creativity| an|d team|work|.|\n",
"2|. The Kensho office features| an open floor plan with panoramic views of the city| skyline, creating an inspiring environment for its| employees.\n",
"\n",
"3|.| With| its| prime| location| in| the| heart| of| the| city|,| K|ens|ho| attracte|d top| talent| from| aroun|d the| worl|d,| creating| a| diverse| an|d dynamic| work| environment|.|"
"3. At Kensho,| team members often collaborate in innovative brainstorming sessions while| enjoying complimentary gourmet coffee from| their in-house café.||"
]
}
],
@@ -763,38 +739,38 @@
" 'data': {'input': 'hello'},\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': [],\n",
" 'run_id': 'b18d016d-8b9b-49e7-a555-44db498fcf66',\n",
" 'run_id': 'c35a72be-a5af-4bd5-bd9b-206135c28ef6',\n",
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-sonnet-20240229',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'parent_ids': []},\n",
" {'event': 'on_chat_model_stream',\n",
" 'run_id': 'b18d016d-8b9b-49e7-a555-44db498fcf66',\n",
" 'run_id': 'c35a72be-a5af-4bd5-bd9b-206135c28ef6',\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': [],\n",
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-sonnet-20240229',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={}, id='run-b18d016d-8b9b-49e7-a555-44db498fcf66', usage_metadata={'input_tokens': 8, 'output_tokens': 4, 'total_tokens': 12, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})},\n",
" 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219'}, id='run--c35a72be-a5af-4bd5-bd9b-206135c28ef6', usage_metadata={'input_tokens': 8, 'output_tokens': 0, 'total_tokens': 8, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})},\n",
" 'parent_ids': []},\n",
" {'event': 'on_chat_model_stream',\n",
" 'run_id': 'b18d016d-8b9b-49e7-a555-44db498fcf66',\n",
" 'run_id': 'c35a72be-a5af-4bd5-bd9b-206135c28ef6',\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': [],\n",
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-sonnet-20240229',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'data': {'chunk': AIMessageChunk(content='Hello! How can', additional_kwargs={}, response_metadata={}, id='run-b18d016d-8b9b-49e7-a555-44db498fcf66')},\n",
" 'data': {'chunk': AIMessageChunk(content='Hello! How', additional_kwargs={}, response_metadata={}, id='run--c35a72be-a5af-4bd5-bd9b-206135c28ef6')},\n",
" 'parent_ids': []}]"
]
},
"execution_count": 14,
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
@@ -813,30 +789,30 @@
"data": {
"text/plain": [
"[{'event': 'on_chat_model_stream',\n",
" 'run_id': 'b18d016d-8b9b-49e7-a555-44db498fcf66',\n",
" 'run_id': 'c35a72be-a5af-4bd5-bd9b-206135c28ef6',\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': [],\n",
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-sonnet-20240229',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'stop_reason': 'end_turn', 'stop_sequence': None}, id='run-b18d016d-8b9b-49e7-a555-44db498fcf66', usage_metadata={'input_tokens': 0, 'output_tokens': 12, 'total_tokens': 12, 'input_token_details': {}})},\n",
" 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'stop_reason': 'end_turn', 'stop_sequence': None}, id='run--c35a72be-a5af-4bd5-bd9b-206135c28ef6', usage_metadata={'input_tokens': 0, 'output_tokens': 40, 'total_tokens': 40})},\n",
" 'parent_ids': []},\n",
" {'event': 'on_chat_model_end',\n",
" 'data': {'output': AIMessageChunk(content='Hello! How can I assist you today?', additional_kwargs={}, response_metadata={'stop_reason': 'end_turn', 'stop_sequence': None}, id='run-b18d016d-8b9b-49e7-a555-44db498fcf66', usage_metadata={'input_tokens': 8, 'output_tokens': 16, 'total_tokens': 24, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})},\n",
" 'run_id': 'b18d016d-8b9b-49e7-a555-44db498fcf66',\n",
" 'data': {'output': AIMessageChunk(content=\"Hello! How can I assist you today? Whether you have questions, need information, or just want to chat, I'm here to help. What would you like to talk about?\", additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219', 'stop_reason': 'end_turn', 'stop_sequence': None}, id='run--c35a72be-a5af-4bd5-bd9b-206135c28ef6', usage_metadata={'input_tokens': 8, 'output_tokens': 40, 'total_tokens': 48, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})},\n",
" 'run_id': 'c35a72be-a5af-4bd5-bd9b-206135c28ef6',\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': [],\n",
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-sonnet-20240229',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'parent_ids': []}]"
]
},
"execution_count": 15,
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
@@ -903,23 +879,34 @@
" 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'},\n",
" 'name': 'RunnableSequence',\n",
" 'tags': [],\n",
" 'run_id': '4765006b-16e2-4b1d-a523-edd9fd64cb92',\n",
" 'metadata': {}},\n",
" 'run_id': 'f859e56f-a760-4670-a24e-040e11bcd7fc',\n",
" 'metadata': {},\n",
" 'parent_ids': []},\n",
" {'event': 'on_chat_model_start',\n",
" 'data': {'input': {'messages': [[HumanMessage(content='output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`')]]}},\n",
" 'data': {'input': {'messages': [[HumanMessage(content='output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`', additional_kwargs={}, response_metadata={})]]}},\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': ['seq:step:1'],\n",
" 'run_id': '0320c234-7b52-4a14-ae4e-5f100949e589',\n",
" 'metadata': {}},\n",
" 'run_id': '2aa8c9e6-a5cd-4e94-b994-cb0e9bd8ab21',\n",
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'parent_ids': ['f859e56f-a760-4670-a24e-040e11bcd7fc']},\n",
" {'event': 'on_chat_model_stream',\n",
" 'data': {'chunk': AIMessageChunk(content='{', id='run-0320c234-7b52-4a14-ae4e-5f100949e589')},\n",
" 'run_id': '0320c234-7b52-4a14-ae4e-5f100949e589',\n",
" 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219'}, id='run--2aa8c9e6-a5cd-4e94-b994-cb0e9bd8ab21', usage_metadata={'input_tokens': 56, 'output_tokens': 0, 'total_tokens': 56, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})},\n",
" 'run_id': '2aa8c9e6-a5cd-4e94-b994-cb0e9bd8ab21',\n",
" 'name': 'ChatAnthropic',\n",
" 'tags': ['seq:step:1'],\n",
" 'metadata': {}}]"
" 'metadata': {'ls_provider': 'anthropic',\n",
" 'ls_model_name': 'claude-3-7-sonnet-20250219',\n",
" 'ls_model_type': 'chat',\n",
" 'ls_temperature': 0.0,\n",
" 'ls_max_tokens': 1024},\n",
" 'parent_ids': ['f859e56f-a760-4670-a24e-040e11bcd7fc']}]"
]
},
"execution_count": 18,
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
@@ -955,25 +942,25 @@
"output_type": "stream",
"text": [
"Chat model chunk: ''\n",
"Chat model chunk: '{'\n",
"Parser chunk: {}\n",
"Chat model chunk: '\\n \"countries'\n",
"Chat model chunk: '\": [\\n '\n",
"Chat model chunk: '```'\n",
"Chat model chunk: 'json\\n{\\n \"countries\": ['\n",
"Parser chunk: {'countries': []}\n",
"Chat model chunk: '{\\n \"'\n",
"Parser chunk: {'countries': [{}]}\n",
"Chat model chunk: 'name\": \"France'\n",
"Chat model chunk: '\\n {\\n \"name\": \"France\",'\n",
"Parser chunk: {'countries': [{'name': 'France'}]}\n",
"Chat model chunk: '\",\\n \"'\n",
"Chat model chunk: 'population\": 67'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67}]}\n",
"Chat model chunk: '413'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413}]}\n",
"Chat model chunk: '000\\n },'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}]}\n",
"Chat model chunk: '\\n {'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}, {}]}\n",
"Chat model chunk: '\\n \"name\":'\n",
"Chat model chunk: '\\n \"population\": 67750000\\n },'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}]}\n",
"Chat model chunk: '\\n {\\n \"name\": \"Spain\",'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain'}]}\n",
"Chat model chunk: '\\n \"population\": 47350'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350}]}\n",
"Chat model chunk: '000\\n },\\n {\\n \"'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {}]}\n",
"Chat model chunk: 'name\": \"Japan\",\\n \"population\":'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan'}]}\n",
"Chat model chunk: ' 125700000\\n }'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan', 'population': 125700000}]}\n",
"Chat model chunk: '\\n ]\\n}\\n```'\n",
"Chat model chunk: ''\n",
"...\n"
]
}
@@ -1033,18 +1020,16 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_parser_start', 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'}, 'name': 'my_parser', 'tags': ['seq:step:2'], 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'metadata': {}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': []}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France'}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67413}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67413000}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67413000}, {}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain'}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"{'event': 'on_parser_stream', 'run_id': '37ee9e85-481c-415e-863b-c9e132d24948', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47}]}}, 'parent_ids': ['5a0bc625-09fd-4bdf-9932-54909a9a8c29']}\n",
"...\n"
"{'event': 'on_parser_start', 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'}, 'name': 'my_parser', 'tags': ['seq:step:2'], 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'metadata': {}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': []}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France'}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67750}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67750000}, {}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain'}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan'}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_stream', 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan', 'population': 125700000}]}}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n",
"{'event': 'on_parser_end', 'data': {'output': {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan', 'population': 125700000}]}}, 'run_id': '781af9b6-31f8-47f2-ab79-52d17b000857', 'name': 'my_parser', 'tags': ['seq:step:2'], 'metadata': {}, 'parent_ids': ['82c918c6-d5f6-4d2d-b710-4668509fe2f0']}\n"
]
}
],
@@ -1086,17 +1071,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_chat_model_start', 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'}, 'name': 'model', 'tags': ['seq:step:1'], 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c', usage_metadata={'input_tokens': 56, 'output_tokens': 1, 'total_tokens': 57, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='{', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n \"countries', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\": [\\n ', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='{\\n \"', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='name\": \"France', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\",\\n \"', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='population\": 67', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='413', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='000\\n },', additional_kwargs={}, response_metadata={}, id='run-156c3e40-82fb-49ff-8e41-9e998061be8c')}, 'run_id': '156c3e40-82fb-49ff-8e41-9e998061be8c', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['7b927055-bc1b-4b50-a34c-10d3cfcb3899']}\n",
"{'event': 'on_chat_model_start', 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'}, 'name': 'model', 'tags': ['seq:step:1'], 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219'}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5', usage_metadata={'input_tokens': 56, 'output_tokens': 0, 'total_tokens': 56, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='```', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='json\\n{\\n \"countries\": [', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n {\\n \"name\": \"France\",', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n \"population\": 67750', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='000\\n },\\n {\\n \"', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='name\": \"Spain\",\\n \"population\":', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content=' 47350000\\n },', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n {\\n \"name\": \"Japan\",', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n \"population\": 125700', additional_kwargs={}, response_metadata={}, id='run--b7a08416-a629-4b42-b5d5-dbe48566e5d5')}, 'run_id': 'b7a08416-a629-4b42-b5d5-dbe48566e5d5', 'name': 'model', 'tags': ['seq:step:1'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['116a6506-5a19-4f60-a8c2-7b728d4b8248']}\n",
"...\n"
]
}
@@ -1144,17 +1129,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_chain_start', 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'}, 'name': 'RunnableSequence', 'tags': ['my_chain'], 'run_id': '58d1302e-36ce-4df7-a3cb-47cb73d57e44', 'metadata': {}, 'parent_ids': []}\n",
"{'event': 'on_chat_model_start', 'data': {'input': {'messages': [[HumanMessage(content='output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`', additional_kwargs={}, response_metadata={})]]}}, 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'run_id': '8222e8a1-d978-4f30-87fc-b2dba838774b', 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={}, id='run-8222e8a1-d978-4f30-87fc-b2dba838774b', usage_metadata={'input_tokens': 56, 'output_tokens': 1, 'total_tokens': 57, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})}, 'run_id': '8222e8a1-d978-4f30-87fc-b2dba838774b', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_parser_start', 'data': {}, 'name': 'JsonOutputParser', 'tags': ['seq:step:2', 'my_chain'], 'run_id': '75604c84-e1e6-494a-8b2a-950f45d932e8', 'metadata': {}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='{', additional_kwargs={}, response_metadata={}, id='run-8222e8a1-d978-4f30-87fc-b2dba838774b')}, 'run_id': '8222e8a1-d978-4f30-87fc-b2dba838774b', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_parser_stream', 'run_id': '75604c84-e1e6-494a-8b2a-950f45d932e8', 'name': 'JsonOutputParser', 'tags': ['seq:step:2', 'my_chain'], 'metadata': {}, 'data': {'chunk': {}}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_chain_stream', 'run_id': '58d1302e-36ce-4df7-a3cb-47cb73d57e44', 'name': 'RunnableSequence', 'tags': ['my_chain'], 'metadata': {}, 'data': {'chunk': {}}, 'parent_ids': []}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n \"countries', additional_kwargs={}, response_metadata={}, id='run-8222e8a1-d978-4f30-87fc-b2dba838774b')}, 'run_id': '8222e8a1-d978-4f30-87fc-b2dba838774b', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\": [\\n ', additional_kwargs={}, response_metadata={}, id='run-8222e8a1-d978-4f30-87fc-b2dba838774b')}, 'run_id': '8222e8a1-d978-4f30-87fc-b2dba838774b', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-sonnet-20240229', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_parser_stream', 'run_id': '75604c84-e1e6-494a-8b2a-950f45d932e8', 'name': 'JsonOutputParser', 'tags': ['seq:step:2', 'my_chain'], 'metadata': {}, 'data': {'chunk': {'countries': []}}, 'parent_ids': ['58d1302e-36ce-4df7-a3cb-47cb73d57e44']}\n",
"{'event': 'on_chain_stream', 'run_id': '58d1302e-36ce-4df7-a3cb-47cb73d57e44', 'name': 'RunnableSequence', 'tags': ['my_chain'], 'metadata': {}, 'data': {'chunk': {'countries': []}}, 'parent_ids': []}\n",
"{'event': 'on_chain_start', 'data': {'input': 'output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`'}, 'name': 'RunnableSequence', 'tags': ['my_chain'], 'run_id': '3e4f8c37-a44a-46b7-a7e5-75182d1cca31', 'metadata': {}, 'parent_ids': []}\n",
"{'event': 'on_chat_model_start', 'data': {'input': {'messages': [[HumanMessage(content='output a list of the countries france, spain and japan and their populations in JSON format. Use a dict with an outer key of \"countries\" which contains a list of countries. Each country should have the key `name` and `population`', additional_kwargs={}, response_metadata={})]]}}, 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'run_id': '778846c9-acd3-43b7-b9c0-ac718761b2bc', 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='', additional_kwargs={}, response_metadata={'model_name': 'claude-3-7-sonnet-20250219'}, id='run--778846c9-acd3-43b7-b9c0-ac718761b2bc', usage_metadata={'input_tokens': 56, 'output_tokens': 0, 'total_tokens': 56, 'input_token_details': {'cache_creation': 0, 'cache_read': 0}})}, 'run_id': '778846c9-acd3-43b7-b9c0-ac718761b2bc', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_parser_start', 'data': {}, 'name': 'JsonOutputParser', 'tags': ['seq:step:2', 'my_chain'], 'run_id': '2c46d24f-231c-4062-a7ab-b7954840986d', 'metadata': {}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='```', additional_kwargs={}, response_metadata={}, id='run--778846c9-acd3-43b7-b9c0-ac718761b2bc')}, 'run_id': '778846c9-acd3-43b7-b9c0-ac718761b2bc', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='json\\n{\\n \"countries\": [', additional_kwargs={}, response_metadata={}, id='run--778846c9-acd3-43b7-b9c0-ac718761b2bc')}, 'run_id': '778846c9-acd3-43b7-b9c0-ac718761b2bc', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_parser_stream', 'run_id': '2c46d24f-231c-4062-a7ab-b7954840986d', 'name': 'JsonOutputParser', 'tags': ['seq:step:2', 'my_chain'], 'metadata': {}, 'data': {'chunk': {'countries': []}}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_chain_stream', 'run_id': '3e4f8c37-a44a-46b7-a7e5-75182d1cca31', 'name': 'RunnableSequence', 'tags': ['my_chain'], 'metadata': {}, 'data': {'chunk': {'countries': []}}, 'parent_ids': []}\n",
"{'event': 'on_chat_model_stream', 'data': {'chunk': AIMessageChunk(content='\\n {\\n \"name\": \"France\",', additional_kwargs={}, response_metadata={}, id='run--778846c9-acd3-43b7-b9c0-ac718761b2bc')}, 'run_id': '778846c9-acd3-43b7-b9c0-ac718761b2bc', 'name': 'ChatAnthropic', 'tags': ['seq:step:1', 'my_chain'], 'metadata': {'ls_provider': 'anthropic', 'ls_model_name': 'claude-3-7-sonnet-20250219', 'ls_model_type': 'chat', 'ls_temperature': 0.0, 'ls_max_tokens': 1024}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_parser_stream', 'run_id': '2c46d24f-231c-4062-a7ab-b7954840986d', 'name': 'JsonOutputParser', 'tags': ['seq:step:2', 'my_chain'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France'}]}}, 'parent_ids': ['3e4f8c37-a44a-46b7-a7e5-75182d1cca31']}\n",
"{'event': 'on_chain_stream', 'run_id': '3e4f8c37-a44a-46b7-a7e5-75182d1cca31', 'name': 'RunnableSequence', 'tags': ['my_chain'], 'metadata': {}, 'data': {'chunk': {'countries': [{'name': 'France'}]}}, 'parent_ids': []}\n",
"...\n"
]
}
@@ -1271,32 +1256,27 @@
"output_type": "stream",
"text": [
"Chat model chunk: ''\n",
"Chat model chunk: '{'\n",
"Parser chunk: {}\n",
"Chat model chunk: '\\n \"countries'\n",
"Chat model chunk: '\": [\\n '\n",
"Chat model chunk: '```'\n",
"Chat model chunk: 'json\\n{\\n \"countries\": ['\n",
"Parser chunk: {'countries': []}\n",
"Chat model chunk: '{\\n \"'\n",
"Parser chunk: {'countries': [{}]}\n",
"Chat model chunk: 'name\": \"France'\n",
"Chat model chunk: '\\n {\\n \"name\": \"France\",'\n",
"Parser chunk: {'countries': [{'name': 'France'}]}\n",
"Chat model chunk: '\",\\n \"'\n",
"Chat model chunk: 'population\": 67'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67}]}\n",
"Chat model chunk: '413'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413}]}\n",
"Chat model chunk: '000\\n },'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}]}\n",
"Chat model chunk: '\\n {'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}, {}]}\n",
"Chat model chunk: '\\n \"name\":'\n",
"Chat model chunk: ' \"Spain\",'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain'}]}\n",
"Chat model chunk: '\\n \"population\":'\n",
"Chat model chunk: ' 47'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47}]}\n",
"Chat model chunk: '351'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67413000}, {'name': 'Spain', 'population': 47351}]}\n",
"Chat model chunk: '\\n \"population\": 67750'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750}]}\n",
"Chat model chunk: '000\\n },\\n {\\n \"'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {}]}\n",
"Chat model chunk: 'name\": \"Spain\",\\n \"population\":'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain'}]}\n",
"Chat model chunk: ' 47350000\\n },'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}]}\n",
"Chat model chunk: '\\n {\\n \"name\": \"Japan\",'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan'}]}\n",
"Chat model chunk: '\\n \"population\": 125700'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan', 'population': 125700}]}\n",
"Chat model chunk: '000\\n }\\n ]\\n}'\n",
"Parser chunk: {'countries': [{'name': 'France', 'population': 67750000}, {'name': 'Spain', 'population': 47350000}, {'name': 'Japan', 'population': 125700000}]}\n",
"Chat model chunk: '\\n```'\n",
"Chat model chunk: ''\n",
"...\n"
]
}
@@ -1350,10 +1330,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_tool_start', 'data': {'input': 'hello'}, 'name': 'bad_tool', 'tags': [], 'run_id': 'ea900472-a8f7-425d-b627-facdef936ee8', 'metadata': {}}\n",
"{'event': 'on_chain_start', 'data': {'input': 'hello'}, 'name': 'reverse_word', 'tags': [], 'run_id': '77b01284-0515-48f4-8d7c-eb27c1882f86', 'metadata': {}}\n",
"{'event': 'on_chain_end', 'data': {'output': 'olleh', 'input': 'hello'}, 'run_id': '77b01284-0515-48f4-8d7c-eb27c1882f86', 'name': 'reverse_word', 'tags': [], 'metadata': {}}\n",
"{'event': 'on_tool_end', 'data': {'output': 'olleh'}, 'run_id': 'ea900472-a8f7-425d-b627-facdef936ee8', 'name': 'bad_tool', 'tags': [], 'metadata': {}}\n"
"{'event': 'on_tool_start', 'data': {'input': 'hello'}, 'name': 'bad_tool', 'tags': [], 'run_id': 'b1c6b79d-f94b-432f-a289-1ea68a7c3cea', 'metadata': {}, 'parent_ids': []}\n",
"{'event': 'on_chain_start', 'data': {'input': 'hello'}, 'name': 'reverse_word', 'tags': [], 'run_id': 'e661c1ec-e6d2-4f9a-9620-b50645f2b194', 'metadata': {}, 'parent_ids': ['b1c6b79d-f94b-432f-a289-1ea68a7c3cea']}\n",
"{'event': 'on_chain_end', 'data': {'output': 'olleh', 'input': 'hello'}, 'run_id': 'e661c1ec-e6d2-4f9a-9620-b50645f2b194', 'name': 'reverse_word', 'tags': [], 'metadata': {}, 'parent_ids': ['b1c6b79d-f94b-432f-a289-1ea68a7c3cea']}\n",
"{'event': 'on_tool_end', 'data': {'output': 'olleh'}, 'run_id': 'b1c6b79d-f94b-432f-a289-1ea68a7c3cea', 'name': 'bad_tool', 'tags': [], 'metadata': {}, 'parent_ids': []}\n"
]
}
],
@@ -1397,10 +1377,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_tool_start', 'data': {'input': 'hello'}, 'name': 'correct_tool', 'tags': [], 'run_id': 'd5ea83b9-9278-49cc-9f1d-aa302d671040', 'metadata': {}}\n",
"{'event': 'on_chain_start', 'data': {'input': 'hello'}, 'name': 'reverse_word', 'tags': [], 'run_id': '44dafbf4-2f87-412b-ae0e-9f71713810df', 'metadata': {}}\n",
"{'event': 'on_chain_end', 'data': {'output': 'olleh', 'input': 'hello'}, 'run_id': '44dafbf4-2f87-412b-ae0e-9f71713810df', 'name': 'reverse_word', 'tags': [], 'metadata': {}}\n",
"{'event': 'on_tool_end', 'data': {'output': 'olleh'}, 'run_id': 'd5ea83b9-9278-49cc-9f1d-aa302d671040', 'name': 'correct_tool', 'tags': [], 'metadata': {}}\n"
"{'event': 'on_tool_start', 'data': {'input': 'hello'}, 'name': 'correct_tool', 'tags': [], 'run_id': '399c91f5-a40b-4173-943f-a9c583a04003', 'metadata': {}, 'parent_ids': []}\n",
"{'event': 'on_chain_start', 'data': {'input': 'hello'}, 'name': 'reverse_word', 'tags': [], 'run_id': 'e9cc7db1-4587-40af-9c35-2d787b3f0956', 'metadata': {}, 'parent_ids': ['399c91f5-a40b-4173-943f-a9c583a04003']}\n",
"{'event': 'on_chain_end', 'data': {'output': 'olleh', 'input': 'hello'}, 'run_id': 'e9cc7db1-4587-40af-9c35-2d787b3f0956', 'name': 'reverse_word', 'tags': [], 'metadata': {}, 'parent_ids': ['399c91f5-a40b-4173-943f-a9c583a04003']}\n",
"{'event': 'on_tool_end', 'data': {'output': 'olleh'}, 'run_id': '399c91f5-a40b-4173-943f-a9c583a04003', 'name': 'correct_tool', 'tags': [], 'metadata': {}, 'parent_ids': []}\n"
]
}
],
@@ -1433,11 +1413,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_chain_start', 'data': {'input': '1234'}, 'name': 'reverse_and_double', 'tags': [], 'run_id': '03b0e6a1-3e60-42fc-8373-1e7829198d80', 'metadata': {}}\n",
"{'event': 'on_chain_start', 'data': {'input': '1234'}, 'name': 'reverse_word', 'tags': [], 'run_id': '5cf26fc8-840b-4642-98ed-623dda28707a', 'metadata': {}}\n",
"{'event': 'on_chain_end', 'data': {'output': '4321', 'input': '1234'}, 'run_id': '5cf26fc8-840b-4642-98ed-623dda28707a', 'name': 'reverse_word', 'tags': [], 'metadata': {}}\n",
"{'event': 'on_chain_stream', 'data': {'chunk': '43214321'}, 'run_id': '03b0e6a1-3e60-42fc-8373-1e7829198d80', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}}\n",
"{'event': 'on_chain_end', 'data': {'output': '43214321'}, 'run_id': '03b0e6a1-3e60-42fc-8373-1e7829198d80', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}}\n"
"{'event': 'on_chain_start', 'data': {'input': '1234'}, 'name': 'reverse_and_double', 'tags': [], 'run_id': '04726e2e-f508-4f90-9d4f-f88e588f0b39', 'metadata': {}, 'parent_ids': []}\n",
"{'event': 'on_chain_stream', 'run_id': '04726e2e-f508-4f90-9d4f-f88e588f0b39', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}, 'data': {'chunk': '43214321'}, 'parent_ids': []}\n",
"{'event': 'on_chain_end', 'data': {'output': '43214321'}, 'run_id': '04726e2e-f508-4f90-9d4f-f88e588f0b39', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}, 'parent_ids': []}\n"
]
}
],
@@ -1475,11 +1453,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'event': 'on_chain_start', 'data': {'input': '1234'}, 'name': 'reverse_and_double', 'tags': [], 'run_id': '1bfcaedc-f4aa-4d8e-beee-9bba6ef17008', 'metadata': {}}\n",
"{'event': 'on_chain_start', 'data': {'input': '1234'}, 'name': 'reverse_word', 'tags': [], 'run_id': '64fc99f0-5d7d-442b-b4f5-4537129f67d1', 'metadata': {}}\n",
"{'event': 'on_chain_end', 'data': {'output': '4321', 'input': '1234'}, 'run_id': '64fc99f0-5d7d-442b-b4f5-4537129f67d1', 'name': 'reverse_word', 'tags': [], 'metadata': {}}\n",
"{'event': 'on_chain_stream', 'data': {'chunk': '43214321'}, 'run_id': '1bfcaedc-f4aa-4d8e-beee-9bba6ef17008', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}}\n",
"{'event': 'on_chain_end', 'data': {'output': '43214321'}, 'run_id': '1bfcaedc-f4aa-4d8e-beee-9bba6ef17008', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}}\n"
"{'event': 'on_chain_start', 'data': {'input': '1234'}, 'name': 'reverse_and_double', 'tags': [], 'run_id': '25f72976-aa79-408d-bb42-6d0f038cde52', 'metadata': {}, 'parent_ids': []}\n",
"{'event': 'on_chain_stream', 'run_id': '25f72976-aa79-408d-bb42-6d0f038cde52', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}, 'data': {'chunk': '43214321'}, 'parent_ids': []}\n",
"{'event': 'on_chain_end', 'data': {'output': '43214321'}, 'run_id': '25f72976-aa79-408d-bb42-6d0f038cde52', 'name': 'reverse_and_double', 'tags': [], 'metadata': {}, 'parent_ids': []}\n"
]
}
],
@@ -1513,7 +1489,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -1527,7 +1503,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -94,7 +94,7 @@
"\n",
"from langchain_anthropic import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)"
"llm = ChatAnthropic(model=\"claude-3-7-sonnet-20250219\", temperature=0)"
]
},
{
@@ -108,11 +108,12 @@
"text/plain": [
"[{'name': 'count_emails',\n",
" 'args': {'last_n_days': 5},\n",
" 'id': 'toolu_01QYZdJ4yPiqsdeENWHqioFW',\n",
" 'id': 'toolu_01XrE4AU9QLo4imbriDDkmXm',\n",
" 'type': 'tool_call',\n",
" 'output': 10}]"
]
},
"execution_count": 3,
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -299,7 +300,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
},
@@ -313,7 +314,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.10.16"
}
},
"nbformat": 4,

View File

@@ -19,7 +19,7 @@
"\n",
"Access Google's Generative AI models, including the Gemini family, directly via the Gemini API or experiment rapidly using Google AI Studio. The `langchain-google-genai` package provides the LangChain integration for these models. This is often the best starting point for individual developers.\n",
"\n",
"For information on the latest models, their features, context windows, etc. head to the [Google AI docs](https://ai.google.dev/gemini-api/docs/models/gemini). All examples use the `gemini-2.0-flash` model. Gemini 2.5 Pro and 2.5 Flash can be used via `gemini-2.5-pro-preview-03-25` and `gemini-2.5-flash-preview-04-17`. All model ids can be found in the [Gemini API docs](https://ai.google.dev/gemini-api/docs/models).\n",
"For information on the latest models, their features, context windows, etc. head to the [Google AI docs](https://ai.google.dev/gemini-api/docs/models/gemini). All model ids can be found in the [Gemini API docs](https://ai.google.dev/gemini-api/docs/models).\n",
"\n",
"### Integration details\n",
"\n",
@@ -117,7 +117,7 @@
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
"\n",
"llm = ChatGoogleGenerativeAI(\n",
" model=\"gemini-2.0-flash\",\n",
" model=\"gemini-2.5-flash\",\n",
" temperature=0,\n",
" max_tokens=None,\n",
" timeout=None,\n",
@@ -242,7 +242,7 @@
"\n",
"### Image Input\n",
"\n",
"Provide image inputs along with text using a `HumanMessage` with a list content format. The `gemini-2.0-flash` model can handle images."
"Provide image inputs along with text using a `HumanMessage` with a list content format. Make sure to use a model that supports image input, such as `gemini-2.5-flash`."
]
},
{
@@ -297,7 +297,7 @@
"\n",
"### Audio Input\n",
"\n",
"Provide audio file inputs along with text. Use a model like `gemini-2.0-flash`."
"Provide audio file inputs along with text."
]
},
{
@@ -340,7 +340,7 @@
"source": [
"### Video Input\n",
"\n",
"Provide video file inputs along with text. Use a model like `gemini-2.0-flash`."
"Provide video file inputs along with text."
]
},
{
@@ -384,7 +384,7 @@
"source": [
"### Image Generation (Multimodal Output)\n",
"\n",
"The `gemini-2.0-flash` model can generate text and images inline (image generation is experimental). You need to specify the desired `response_modalities`."
"Certain models (such as `gemini-2.0-flash-preview-image-generation`) can generate text and images inline. You need to specify the desired `response_modalities`. See more information on the [Gemini API docs](https://ai.google.dev/gemini-api/docs/image-generation) for details."
]
},
{
@@ -830,7 +830,7 @@
"source": [
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
"\n",
"llm = ChatGoogleGenerativeAI(model=\"gemini-2.0-flash\")\n",
"llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\")\n",
"\n",
"\n",
"async def run_async_calls():\n",
@@ -900,7 +900,7 @@
"source": [
"## API reference\n",
"\n",
"For detailed documentation of all ChatGoogleGenerativeAI features and configurations head to the API reference: https://python.langchain.com/api_reference/google_genai/chat_models/langchain_google_genai.chat_models.ChatGoogleGenerativeAI.html"
"For detailed documentation of all ChatGoogleGenerativeAI features and configurations head to the [API reference](https://python.langchain.com/api_reference/google_genai/chat_models/langchain_google_genai.chat_models.ChatGoogleGenerativeAI.html)."
]
}
],

View File

@@ -19,7 +19,7 @@
"\n",
"This page provides a quick overview for getting started with VertexAI [chat models](/docs/concepts/chat_models). For detailed documentation of all ChatVertexAI features and configurations head to the [API reference](https://python.langchain.com/api_reference/google_vertexai/chat_models/langchain_google_vertexai.chat_models.ChatVertexAI.html).\n",
"\n",
"ChatVertexAI exposes all foundational models available in Google Cloud, like `gemini-1.5-pro`, `gemini-1.5-flash`, etc. For a full and updated list of available models visit [VertexAI documentation](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/overview).\n",
"ChatVertexAI exposes all foundational models available in Google Cloud, like `gemini-2.5-pro`, `gemini-2.5-flash`, etc. For a full and updated list of available models visit [VertexAI documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/models).\n",
"\n",
":::info Google Cloud VertexAI vs Google PaLM\n",
"\n",
@@ -45,7 +45,7 @@
"\n",
"### Credentials\n",
"\n",
"To use the integration you must:\n",
"To use the integration you must either:\n",
"- Have credentials configured for your environment (gcloud, workload identity, etc...)\n",
"- Store the path to a service account JSON file as the GOOGLE_APPLICATION_CREDENTIALS environment variable\n",
"\n",
@@ -60,7 +60,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "a15d341e-3e26-4ca3-830b-5aab30ed66de",
"metadata": {},
"outputs": [],
@@ -109,7 +109,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae",
"metadata": {},
"outputs": [],
@@ -117,7 +117,7 @@
"from langchain_google_vertexai import ChatVertexAI\n",
"\n",
"llm = ChatVertexAI(\n",
" model=\"gemini-1.5-flash-001\",\n",
" model=\"gemini-2.5-flash\",\n",
" temperature=0,\n",
" max_tokens=None,\n",
" max_retries=6,\n",
@@ -210,7 +210,7 @@
"source": [
"from langchain_google_vertexai import ChatVertexAI\n",
"\n",
"llm = ChatVertexAI(model=\"gemini-2.0-flash-001\").bind_tools([{\"google_search\": {}}])\n",
"llm = ChatVertexAI(model=\"gemini-2.5-flash\").bind_tools([{\"google_search\": {}}])\n",
"\n",
"response = llm.invoke(\"What is today's news?\")"
]
@@ -237,7 +237,7 @@
"source": [
"from langchain_google_vertexai import ChatVertexAI\n",
"\n",
"llm = ChatVertexAI(model=\"gemini-2.0-flash-001\").bind_tools([{\"code_execution\": {}}])\n",
"llm = ChatVertexAI(model=\"gemini-2.5-flash\").bind_tools([{\"code_execution\": {}}])\n",
"\n",
"response = llm.invoke(\"What is 3^3?\")"
]

View File

@@ -0,0 +1,298 @@
{
"cells": [
{
"cell_type": "raw",
"id": "afaf8039",
"metadata": {
"vscode": {
"languageId": "raw"
}
},
"source": [
"---\n",
"sidebar_label: DigitalOcean Gradient\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "e49f1e0d",
"metadata": {},
"source": [
"# ChatGradient\n",
"\n",
"This will help you getting started with DigitalOcean Gradient Chat Models.\n",
"\n",
"## Overview\n",
"### Integration details\n",
"\n",
"| Class | Package | Package downloads | Package latest |\n",
"| :--- | :--- | :---: | :---: |\n",
"| [DigitalOcean Gradient](https://python.langchain.com/docs/api_reference/llms/langchain_gradient.llms.LangchainGradient/) | [langchain-gradient](https://python.langchain.com/docs/api_reference/langchain-gradient_api_reference/) | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain-gradient?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain-gradient?style=flat-square&label=%20) |\n",
"\n",
"\n",
"## Setup\n",
"\n",
"langchain-gradient uses DigitalOcean Gradient Platform. \n",
"\n",
"Create an account on DigitalOcean, acquire a `DIGITALOCEAN_INFERENCE_KEY` API key from the Gradient Platform, and install the `langchain-gradient` integration package.\n",
"\n",
"### Credentials\n",
"\n",
"Head to [DigitalOcean Login](https://cloud.digitalocean.com/login) \n",
"\n",
"1. Sign up/Login to DigitalOcean Cloud Console\n",
"2. Go to the Gradient Platform and navigate to Serverless Inference.\n",
"3. Click on Create model access key, enter a name, and create the key.\n",
"\n",
"Once you've done this set the `DIGITALOCEAN_INFERENCE_KEY` environment variable:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "433e8d2b-9519-4b49-b2c4-7ab65b046c94",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"if not os.getenv(\"DIGITALOCEAN_INFERENCE_KEY\"):\n",
" os.environ[\"DIGITALOCEAN_INFERENCE_KEY\"] = getpass.getpass(\n",
" \"Enter your DIGITALOCEAN_INFERENCE_KEY API key: \"\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "72ee0c4b-9764-423a-9dbf-95129e185210",
"metadata": {},
"source": [
"If you want to get automated tracing of your model calls you can also set your [LangSmith](https://docs.smith.langchain.com/) API key by uncommenting below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a15d341e-3e26-4ca3-830b-5aab30ed66de",
"metadata": {},
"outputs": [],
"source": [
"# os.environ[\"LANGSMITH_TRACING\"] = \"true\"\n",
"# os.environ[\"LANGSMITH_API_KEY\"] = getpass.getpass(\"Enter your LangSmith API key: \")"
]
},
{
"cell_type": "markdown",
"id": "0730d6a1-c893-4840-9817-5e5251676d5d",
"metadata": {},
"source": [
"### Installation\n",
"\n",
"The DigitalOcean Gradient integration lives in the `langchain-gradient` package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "652d6238-1f87-422a-b135-f5abbb8652fc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip3.12 install --upgrade pip\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip install -qU langchain-gradient"
]
},
{
"cell_type": "markdown",
"id": "a38cde65-254d-4219-a441-068766c0d4b5",
"metadata": {},
"source": [
"## Instantiation\n",
"\n",
"Now we can instantiate our model object and generate chat completions:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae",
"metadata": {},
"outputs": [],
"source": [
"from langchain_gradient import ChatGradient\n",
"\n",
"llm = ChatGradient(\n",
" model=\"llama3.3-70b-instruct\",\n",
" # other params...\n",
")"
]
},
{
"cell_type": "markdown",
"id": "2b4f3e15",
"metadata": {},
"source": [
"## Invocation"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "62e0dbc3",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"...that had been hidden away for centuries, nestled amongst the twisted roots of an ancient tree. As soon as Mira's fingers made contact with the stone, she felt an sudden surge of energy course through her veins, like a river bursting its banks. The stone, which had been dull and lifeless just moments before, now pulsed with a soft, ethereal light, as if it had been awakened by Mira's touch.\\n\\nIntrigued, Mira turned the stone over in her hand, studying it from every angle. The light emanating from it cast eerie shadows on the trees around her, making her feel as though she was standing at the threshold of a secret world. As she gazed deeper into the stone, she began to notice that the glow was not just a random color, but a deep, rich blue that seemed to be calling to her.\\n\\nWithout thinking, Mira felt an overwhelming urge to follow the stone's gentle glow, which seemed to be leading her deeper into the mysterious forest. The trees loomed above her, their branches creaking and swaying in the wind, as if they too were urging her onward. The air was filled with the sweet scent of wildflowers and the soft hooting of owls, creating a sense of enchantment that was both exhilarating and unsettling.\\n\\nAs Mira wandered deeper into the forest, the stone's light grew brighter, illuminating a winding path that was all but invisible in the fading light of day. The trees grew taller and closer together here, forming a tunnel of foliage that seemed to be guiding her towards a hidden destination. Mira's heart pounded with excitement and a hint of fear, as she realized that she was being drawn into a world that was both magical and unknown.\\n\\nSuddenly, the trees parted, and Mira found herself standing at the edge of a clearing, surrounded by a ring of towering mushrooms that glowed with a soft, luminescent light. The air was filled with a faint humming noise, like the buzzing of a thousand bees, and the stone in her hand pulsed with an otherworldly energy. In the center of the clearing stood an enormous tree, its trunk twisted and gnarled with age, its branches reaching up towards the stars like a Nature's own cathedral.\\n\\nMira felt a sense of awe wash over her, as she approached the tree, the stone still clutched in her hand. She could feel the magic of the forest pulsing through her, calling to her, drawing her closer to the heart of the mystery. And as she reached out to touch the trunk of the tree, the stone's glow surged to a brilliant intensity, illuminating a doorway that had been hidden in the trunk all along...\", additional_kwargs={}, response_metadata={'finish_reason': 'stop'}, id='run--593a6940-4c76-413b-bed9-1fd94f91c6c1-0', usage_metadata={'input_tokens': 82, 'output_tokens': 555, 'total_tokens': 637})"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" (\n",
" \"system\",\n",
" \"You are a creative storyteller. Continue any story prompt you receive in an engaging and imaginative way.\",\n",
" ),\n",
" (\n",
" \"human\",\n",
" \"Once upon a time, in a village at the edge of a mysterious forest, a young girl named Mira found a glowing stone...\",\n",
" ),\n",
"]\n",
"ai_msg = llm.invoke(messages)\n",
"ai_msg"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d86145b3-bfef-46e8-b227-4dda5c9c2705",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"...that had been hidden away for centuries, nestled amongst the twisted roots of an ancient tree. As soon as Mira's fingers made contact with the stone, she felt an sudden surge of energy course through her veins, like a river bursting its banks. The stone, which had been dull and lifeless just moments before, now pulsed with a soft, ethereal light, as if it had been awakened by Mira's touch.\n",
"\n",
"Intrigued, Mira turned the stone over in her hand, studying it from every angle. The light emanating from it cast eerie shadows on the trees around her, making her feel as though she was standing at the threshold of a secret world. As she gazed deeper into the stone, she began to notice that the glow was not just a random color, but a deep, rich blue that seemed to be calling to her.\n",
"\n",
"Without thinking, Mira felt an overwhelming urge to follow the stone's gentle glow, which seemed to be leading her deeper into the mysterious forest. The trees loomed above her, their branches creaking and swaying in the wind, as if they too were urging her onward. The air was filled with the sweet scent of wildflowers and the soft hooting of owls, creating a sense of enchantment that was both exhilarating and unsettling.\n",
"\n",
"As Mira wandered deeper into the forest, the stone's light grew brighter, illuminating a winding path that was all but invisible in the fading light of day. The trees grew taller and closer together here, forming a tunnel of foliage that seemed to be guiding her towards a hidden destination. Mira's heart pounded with excitement and a hint of fear, as she realized that she was being drawn into a world that was both magical and unknown.\n",
"\n",
"Suddenly, the trees parted, and Mira found herself standing at the edge of a clearing, surrounded by a ring of towering mushrooms that glowed with a soft, luminescent light. The air was filled with a faint humming noise, like the buzzing of a thousand bees, and the stone in her hand pulsed with an otherworldly energy. In the center of the clearing stood an enormous tree, its trunk twisted and gnarled with age, its branches reaching up towards the stars like a Nature's own cathedral.\n",
"\n",
"Mira felt a sense of awe wash over her, as she approached the tree, the stone still clutched in her hand. She could feel the magic of the forest pulsing through her, calling to her, drawing her closer to the heart of the mystery. And as she reached out to touch the trunk of the tree, the stone's glow surged to a brilliant intensity, illuminating a doorway that had been hidden in the trunk all along...\n"
]
}
],
"source": [
"print(ai_msg.content)"
]
},
{
"cell_type": "markdown",
"id": "18e2bfc0-7e78-4528-a73f-499ac150dca8",
"metadata": {},
"source": [
"## Chaining\n",
"\n",
"We can chain our model with a prompt template like so:\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "e197d1d7-a070-4c96-9f8a-a0e86d046e0b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='The Eiffel Tower was designed by Gustave Eiffel\\'s engineering company and was completed in 1889. (Sentence: \"It was designed by Gustave Eiffel\\'s engineering company. The tower is one of the most recognizable structures in the world. ... The Eiffel Tower is located in Paris and was completed in 1889.\")', additional_kwargs={}, response_metadata={'finish_reason': 'stop'}, id='run--c23ffab6-06ae-4130-87b1-d5b2e7744906-0', usage_metadata={'input_tokens': 153, 'output_tokens': 74, 'total_tokens': 227})"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.prompts import ChatPromptTemplate\n",
"\n",
"prompt = ChatPromptTemplate(\n",
" [\n",
" (\n",
" \"system\",\n",
" 'You are a knowledgeable assistant. Carefully read the provided context and answer the user\\'s question. If the answer is present in the context, cite the relevant sentence. If not, reply with \"Not found in context.\"',\n",
" ),\n",
" (\"human\", \"Context: {context}\\nQuestion: {question}\"),\n",
" ]\n",
")\n",
"\n",
"chain = prompt | llm\n",
"chain.invoke(\n",
" {\n",
" \"context\": (\n",
" \"The Eiffel Tower is located in Paris and was completed in 1889. \"\n",
" \"It was designed by Gustave Eiffel's engineering company. \"\n",
" \"The tower is one of the most recognizable structures in the world. \"\n",
" \"The Statue of Liberty was a gift from France to the United States.\"\n",
" ),\n",
" \"question\": \"Who designed the Eiffel Tower and when was it completed?\",\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"id": "8a6660e4",
"metadata": {},
"source": [
"## API reference\n",
"\n",
"For detailed documentation of all ChatGradient features and configurations head to the API reference."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.12.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -52,7 +52,7 @@
"\n",
"| Class | Package | Local | Serializable | JS support | Package downloads | Package latest |\n",
"| :--- | :--- | :---: | :---: | :---: | :---: | :---: |\n",
"| [ChatHuggingFace](https://python.langchain.com/api_reference/huggingface/chat_models/langchain_huggingface.chat_models.huggingface.ChatHuggingFace.html) | [langchain_huggingface](https://python.langchain.com/api_reference/huggingface/index.html) | ✅ | ❌ | ❌ | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain_huggingface?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain_huggingface?style=flat-square&label=%20) |\n",
"| [ChatHuggingFace](https://python.langchain.com/api_reference/huggingface/chat_models/langchain_huggingface.chat_models.huggingface.ChatHuggingFace.html) | [langchain-huggingface](https://python.langchain.com/api_reference/huggingface/index.html) | ✅ | ❌ | ❌ | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain_huggingface?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain_huggingface?style=flat-square&label=%20) |\n",
"\n",
"### Model features\n",
"| [Tool calling](/docs/how_to/tool_calling) | [Structured output](/docs/how_to/structured_output/) | JSON mode | [Image input](/docs/how_to/multimodal_inputs/) | Audio input | Video input | [Token-level streaming](/docs/how_to/chat_streaming/) | Native async | [Token usage](/docs/how_to/chat_token_usage_tracking/) | [Logprobs](/docs/how_to/logprobs/) |\n",
@@ -61,7 +61,7 @@
"\n",
"## Setup\n",
"\n",
"To access `langchain_huggingface` models you'll need to create a/an `Hugging Face` account, get an API key, and install the `langchain_huggingface` integration package.\n",
"To access `langchain_huggingface` models you'll need to create a `Hugging Face` account, get an API key, and install the `langchain-huggingface` integration package.\n",
"\n",
"### Credentials\n",
"\n",

View File

@@ -37,4 +37,4 @@ import { CategoryTable, IndexTable } from "@theme/FeatureTables";
## All chat models
<IndexTable />
<IndexTable />

View File

@@ -24,7 +24,7 @@
"\n",
"| Class | Package | Local | Serializable | [JS support](https://js.langchain.com/docs/integrations/chat/mistral) | Package downloads | Package latest |\n",
"| :--- | :--- | :---: | :---: | :---: | :---: | :---: |\n",
"| [ChatMistralAI](https://python.langchain.com/api_reference/mistralai/chat_models/langchain_mistralai.chat_models.ChatMistralAI.html) | [langchain_mistralai](https://python.langchain.com/api_reference/mistralai/index.html) | ❌ | beta | ✅ | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain_mistralai?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain_mistralai?style=flat-square&label=%20) |\n",
"| [ChatMistralAI](https://python.langchain.com/api_reference/mistralai/chat_models/langchain_mistralai.chat_models.ChatMistralAI.html) | [langchain-mistralai](https://python.langchain.com/api_reference/mistralai/index.html) | ❌ | beta | ✅ | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain_mistralai?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain_mistralai?style=flat-square&label=%20) |\n",
"\n",
"### Model features\n",
"| [Tool calling](/docs/how_to/tool_calling) | [Structured output](/docs/how_to/structured_output/) | JSON mode | [Image input](/docs/how_to/multimodal_inputs/) | Audio input | Video input | [Token-level streaming](/docs/how_to/chat_streaming/) | Native async | [Token usage](/docs/how_to/chat_token_usage_tracking/) | [Logprobs](/docs/how_to/logprobs/) |\n",
@@ -34,7 +34,7 @@
"## Setup\n",
"\n",
"\n",
"To access `ChatMistralAI` models you'll need to create a Mistral account, get an API key, and install the `langchain_mistralai` integration package.\n",
"To access `ChatMistralAI` models you'll need to create a Mistral account, get an API key, and install the `langchain-mistralai` integration package.\n",
"\n",
"### Credentials\n",
"\n",
@@ -80,7 +80,7 @@
"source": [
"### Installation\n",
"\n",
"The LangChain Mistral integration lives in the `langchain_mistralai` package:"
"The LangChain Mistral integration lives in the `langchain-mistralai` package:"
]
},
{
@@ -90,7 +90,7 @@
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain_mistralai"
"%pip install -qU langchain-mistralai"
]
},
{

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More