Compare commits

..

135 Commits

Author SHA1 Message Date
Bagatur
3b5db8ab06 nav_depth, copy_source, collapse_nav 2024-02-05 14:11:28 -08:00
Bagatur
66e45e8ab7 community[patch]: chat model mypy fixes (#17061)
Related to #17048
2024-02-05 13:42:59 -08:00
Bagatur
d93de71d08 community[patch]: chat message history mypy fixes (#17059)
Related to #17048
2024-02-05 13:13:25 -08:00
Bagatur
af5ae24af2 community[patch]: callbacks mypy fixes (#17058)
Related to #17048
2024-02-05 12:37:27 -08:00
Vadim Kudlay
75b6fa1134 nvidia-ai-endpoints[patch]: Support User-Agent metadata and minor fixes. (#16942)
- **Description:** Several meta/usability updates, including User-Agent.
  - **Issue:** 
- User-Agent metadata for tracking connector engagement. @milesial
please check and advise.
- Better error messages. Tries harder to find a request ID. @milesial
requested.
- Client-side image resizing for multimodal models. Hope to upgrade to
Assets API solution in around a month.
- `client.payload_fn` allows you to modify payload before network
request. Use-case shown in doc notebook for kosmos_2.
- `client.last_inputs` put back in to allow for advanced
support/debugging.
  - **Dependencies:** 
- Attempts to pull in PIL for image resizing. If not installed, prints
out "please install" message, warns it might fail, and then tries
without resizing. We are waiting on a more permanent solution.

For LC viz: @hinthornw 
For NV viz: @fciannella @milesial @vinaybagade

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2024-02-05 12:24:53 -08:00
Nuno Campos
ae56fd020a Fix condition on custom root type in runnable history (#17017)
<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-02-05 12:15:11 -08:00
Nuno Campos
f0ffebb944 Shield callback methods from cancellation: Fix interrupted runs marked as pending forever (#17010)
<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-02-05 12:09:47 -08:00
Bagatur
e7b3290d30 community[patch]: fix agent_toolkits mypy (#17050)
Related to #17048
2024-02-05 11:56:24 -08:00
Erick Friis
6ffd5b15bc pinecone: init pkg (#16556)
<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-02-05 11:55:01 -08:00
Erick Friis
1183769cf7 template: tool-retrieval-fireworks (#17052)
- Initial commit oss-tool-retrieval-agent
- README update
- lint
- lock
- format imports
- Rename to retrieval-agent-fireworks
- cr

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->

---------

Co-authored-by: Taqi Jaffri <tjaffri@docugami.com>
2024-02-05 11:50:17 -08:00
Harrison Chase
4eda647fdd infra: add -p to mkdir in lint steps (#17013)
Previously, if this did not find a mypy cache then it wouldnt run

this makes it always run

adding mypy ignore comments with existing uncaught issues to unblock other prs

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
Co-authored-by: Bagatur <22008038+baskaryan@users.noreply.github.com>
2024-02-05 11:22:06 -08:00
Erick Friis
db6af21395 docs: exa contents (#16555) 2024-02-05 11:15:06 -08:00
Eugene Yurtsev
fb245451d2 core[patch]: Add langsmith to printed sys information (#16899) 2024-02-05 11:13:30 -08:00
Mikhail Khludnev
2145636f1d Nvidia trt model name for stop_stream() (#16997)
just removing some legacy leftover.
2024-02-05 10:45:06 -08:00
Christophe Bornet
2ef69fe11b Add async methods to BaseChatMessageHistory and BaseMemory (#16728)
Adds:
   * async methods to BaseChatMessageHistory
   * async methods to ChatMessageHistory
   * async methods to BaseMemory
   * async methods to BaseChatMemory
   * async methods to ConversationBufferMemory
   * tests of ConversationBufferMemory's async methods

  **Twitter handle:** cbornet_
2024-02-05 13:20:28 -05:00
Ryan Kraus
b3c3b58f2c core[patch]: Fixed bug in dict to message conversion. (#17023)
- **Description**: We discovered a bug converting dictionaries to
messages where the ChatMessageChunk message type isn't handled. This PR
adds support for that message type.
- **Issue**: #17022 
- **Dependencies**: None
- **Twitter handle**: None
2024-02-05 10:13:25 -08:00
Nicolas Grenié
54fcd476bb docs: Update ollama examples with new community libraries (#17007)
- **Description:** Updating one line code sample for Ollama with new
**langchain_community** package
  - **Issue:**
  - **Dependencies:** none
  - **Twitter handle:**  @picsoung
2024-02-04 15:13:29 -08:00
Killinsun - Ryota Takeuchi
bcfce146d8 community[patch]: Correct the calling to collection_name in qdrant (#16920)
## Description

In #16608, the calling `collection_name` was wrong.
I made a fix for it. 
Sorry for the inconvenience!

## Issue

https://github.com/langchain-ai/langchain/issues/16962

## Dependencies

N/A



<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->

---------

Co-authored-by: Kumar Shivendu <kshivendu1@gmail.com>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-02-04 10:45:35 -08:00
Erick Friis
849051102a google-genai[patch]: fix new core typing (#16988) 2024-02-03 17:45:44 -08:00
Bagatur
35446c814e openai[patch]: rm tiktoken model warning (#16964) 2024-02-03 16:36:57 -08:00
ccurme
0826d87ecd langchain_mistralai[patch]: Invoke callback prior to yielding token (#16986)
- **Description:** Invoke callback prior to yielding token in stream and
astream methods for ChatMistralAI.
- **Issue:** https://github.com/langchain-ai/langchain/issues/16913
2024-02-03 16:30:50 -08:00
Bagatur
267e71606e docs: Update README.md (#16966) 2024-02-02 16:50:58 -08:00
Erick Friis
2b7e47a668 infra: install integration deps for test linting (#16963)
<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-02-02 15:59:10 -08:00
Erick Friis
afdd636999 docs: partner packages (#16960) 2024-02-02 15:12:21 -08:00
Erick Friis
06660bc78c core[patch]: handle some optional cases in tools (#16954)
primary problem in pydantic still exists, where `Optional[str]` gets
turned to `string` in the jsonschema `.schema()`

Also fixes the `SchemaSchema` naming issue

---------

Co-authored-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2024-02-02 15:05:54 -08:00
Mohammad Mohtashim
f8943e8739 core[patch]: Add doc-string to RunnableEach (#16892)
Add doc-string to Runnable Each
---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Eugene Yurtsev <eugene@langchain.dev>
2024-02-02 14:11:09 -08:00
Ashley Xu
66adb95284 docs: BigQuery Vector Search went public review and updated docs (#16896)
Update the docs for BigQuery Vector Search
2024-02-02 10:26:44 -08:00
Massimiliano Pronesti
71f9ea33b6 docs: add quantization to vllm and update API (#16950)
- **Description:** Update vLLM docs to include instructions on how to
use quantized models, as well as to replace the deprecated methods.
2024-02-02 10:24:49 -08:00
Bagatur
2a510c71a0 core[patch]: doc init positional args (#16854) 2024-02-02 10:24:16 -08:00
Bagatur
d80c612c92 core[patch]: Message content as positional arg (#16921) 2024-02-02 10:24:02 -08:00
Bagatur
c29e9b6412 core[patch]: fix chat prompt partial messages placeholder var (#16918) 2024-02-02 10:23:37 -08:00
Radhakrishnan
3b0fa9079d docs: Updated integration doc for aleph alpha (#16844)
Description: Updated doc for llm/aleph_alpha with new functions: invoke.
Changed structure of the document to match the required one.
Issue: https://github.com/langchain-ai/langchain/issues/15664
Dependencies: None
Twitter handle: None

---------

Co-authored-by: Radhakrishnan Iyer <radhakrishnan.iyer@ibm.com>
2024-02-02 09:28:06 -08:00
hmasdev
cc17334473 core[minor]: add validation error handler to BaseTool (#14007)
- **Description:** add a ValidationError handler as a field of
[`BaseTool`](https://github.com/langchain-ai/langchain/blob/master/libs/core/langchain_core/tools.py#L101)
and add unit tests for the code change.
- **Issue:** #12721 #13662
- **Dependencies:** None
- **Tag maintainer:** 
- **Twitter handle:** @hmdev3
- **NOTE:**
  - I'm wondering if the update of document is required.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2024-02-01 20:09:19 -08:00
William FH
bdacfafa05 core[patch]: Remove deep copying of run prior to submitting it to LangChain Tracing (#16904) 2024-02-01 18:46:05 -08:00
William FH
e02efd513f core[patch]: Hide aliases when serializing (#16888)
Currently, if you dump an object initialized with an alias, we'll still
dump the secret values since they're retained in the kwargs
2024-02-01 17:55:37 -08:00
William FH
131c043864 Fix loading of ImagePromptTemplate (#16868)
We didn't override the namespace of the ImagePromptTemplate, so it is
listed as being in langchain.schema

This updates the mapping to let the loader deserialize.

Alternatively, we could make a slight breaking change and update the
namespace of the ImagePromptTemplate since we haven't broadly
publicized/documented it yet..
2024-02-01 17:54:04 -08:00
Erick Friis
6fc2835255 docs: fix broken links (#16855) 2024-02-01 17:29:38 -08:00
Eugene Yurtsev
a265878d71 langchain_openai[patch]: Invoke callback prior to yielding token (#16909)
All models should be calling the callback for new token prior to
yielding the token.

Not doing this can cause callbacks for downstream steps to be called
prior to the callback for the new token; causing issues in
astream_events APIs and other things that depend in callback ordering
being correct.

We need to make this change for all chat models.
2024-02-01 16:43:10 -08:00
Erick Friis
b1a847366c community: revert SQL Stores (#16912)
This reverts commit cfc225ecb3.


https://github.com/langchain-ai/langchain/pull/15909#issuecomment-1922418097

These will have existed in langchain-community 0.0.16 and 0.0.17.
2024-02-01 16:37:40 -08:00
akira wu
f7c709b40e doc: fix typo in message_history.ipynb (#16877)
- **Description:** just fixed a small typo in the documentation in the
`expression_language/how_to/message_history` session
[here](https://python.langchain.com/docs/expression_language/how_to/message_history)
2024-02-01 13:30:29 -08:00
Leonid Ganeline
c2ca6612fe refactor langchain.prompts.example_selector (#15369)
The `langchain.prompts.example_selector` [still holds several
artifacts](https://api.python.langchain.com/en/latest/langchain_api_reference.html#module-langchain.prompts)
that belongs to `community`. If they moved to
`langchain_community.example_selectors`, the `langchain.prompts`
namespace would be effectively removed which is great.
- moved a class and afunction to `langchain_community`

Note:
- Previously, the `langchain.prompts.example_selector` artifacts were
moved into the `langchain_core.exampe_selectors`. See the flattened
namespace (`.prompts` was removed)!
Similar flattening was implemented for the `langchain_core` as the
`langchain_core.exampe_selectors`.

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2024-02-01 12:05:57 -08:00
Erick Friis
13a6756067 infra: ci naming 2 (#16893) 2024-02-01 11:39:00 -08:00
Lance Martin
b1e7130d8a Minor update to Nomic cookbook (#16886)
<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-02-01 11:28:58 -08:00
Shorthills AI
0bca0f4c24 Docs: Fixed grammatical mistake (#16858)
Co-authored-by: Vishal <141389263+VishalYadavShorthillsAI@users.noreply.github.com>
Co-authored-by: Sanskar Tanwar <142409040+SanskarTanwarShorthillsAI@users.noreply.github.com>
Co-authored-by: UpneetShorthillsAI <144228282+UpneetShorthillsAI@users.noreply.github.com>
Co-authored-by: HarshGuptaShorthillsAI <144897987+HarshGuptaShorthillsAI@users.noreply.github.com>
Co-authored-by: AdityaKalraShorthillsAI <143726711+AdityaKalraShorthillsAI@users.noreply.github.com>
Co-authored-by: SakshiShorthillsAI <144228183+SakshiShorthillsAI@users.noreply.github.com>
Co-authored-by: AashiGuptaShorthillsAI <144897730+AashiGuptaShorthillsAI@users.noreply.github.com>
Co-authored-by: ShamshadAhmedShorthillsAI <144897733+ShamshadAhmedShorthillsAI@users.noreply.github.com>
Co-authored-by: ManpreetShorthillsAI <142380984+ManpreetShorthillsAI@users.noreply.github.com>
Co-authored-by: Aayush <142384656+AayushShorthillsAI@users.noreply.github.com>
Co-authored-by: BajrangBishnoiShorthillsAi <148060486+BajrangBishnoiShorthillsAi@users.noreply.github.com>
2024-02-01 11:28:15 -08:00
Erick Friis
5b3fc86cfd infra: ci naming (#16890)
Make it clearer how to run equivalent commands locally

Not a perfect 1:1, but will help people get started

![Screenshot 2024-02-01 at 10 53
34 AM](https://github.com/langchain-ai/langchain/assets/9557659/da271aaf-d5db-41e3-9379-cb1d8a0232c5)
2024-02-01 11:09:37 -08:00
Qihui Xie
c5b01ac621 community[patch]: support LIKE comparator (full text match) in Qdrant (#12769)
**Description:** 
Support [Qdrant full text match
filtering](https://qdrant.tech/documentation/concepts/filtering/#full-text-match)
by adding Comparator.LIKE to QdrantTranslator.
2024-02-01 11:03:25 -08:00
Christophe Bornet
9d458d089a community: Factorize AstraDB components constructors (#16779)
* Adds `AstraDBEnvironment` class and use it in `AstraDBLoader`,
`AstraDBCache`, `AstraDBSemanticCache`, `AstraDBBaseStore` and
`AstraDBChatMessageHistory`
* Create an `AsyncAstraDB` if we only have an `AstraDB` and vice-versa
so:
  * we always have an instance of `AstraDB`
* we always have an instance of `AsyncAstraDB` for recent versions of
astrapy
* Create collection if not exists in `AstraDBBaseStore`
* Some typing improvements

Note: `AstraDB` `VectorStore` not using `AstraDBEnvironment` at the
moment. This will be done after the `langchain-astradb` package is out.
2024-02-01 10:51:07 -08:00
Harel Gal
93366861c7 docs: Indicated Guardrails for Amazon Bedrock preview status (#16769)
Added notification about limited preview status of Guardrails for Amazon
Bedrock feature to code example.

---------

Co-authored-by: Piyush Jain <piyushjain@duck.com>
2024-02-01 10:41:48 -08:00
Christophe Bornet
78a1af4848 langchain[patch]: Add async methods to MultiVectorRetriever (#16878)
Adds async support to multi vector retriever
2024-02-01 10:33:06 -08:00
Bagatur
7d03d8f586 docs: fix docstring examples (#16889) 2024-02-01 10:17:26 -08:00
Bagatur
c2d09fb151 infra: bump exp min test reqs (#16884) 2024-02-01 08:35:21 -08:00
Bagatur
65ba5c220b experimental[patch]: Release 0.0.50 (#16883) 2024-02-01 08:27:39 -08:00
Bagatur
9e7d9f9390 infra: bump langchain min test reqs (#16882) 2024-02-01 08:16:30 -08:00
Bagatur
db442c635b langchain[patch]: Release 0.1.5 (#16881) 2024-02-01 08:10:29 -08:00
Bagatur
2b4abed25c commmunity[patch]: Release 0.0.17 (#16871) 2024-02-01 07:33:34 -08:00
Bagatur
bb73251146 core[patch]: Release 0.1.18 (#16870) 2024-02-01 07:33:15 -08:00
Christophe Bornet
a0ec045495 Add async methods to BaseStore (#16669)
- **Description:**

The BaseStore methods are currently blocking. Some implementations
(AstraDBStore, RedisStore) would benefit from having async methods.
Also once we have async methods for BaseStore, we can implement the
async `aembed_documents` in CacheBackedEmbeddings to cache the
embeddings asynchronously.

* adds async methods amget, amset, amedelete and ayield_keys to
BaseStore
  * implements the async methods for InMemoryStore
  * adds tests for InMemoryStore async methods

- **Twitter handle:** cbornet_
2024-01-31 17:10:47 -08:00
Erick Friis
17e886388b nomic: init pkg (#16853)
Co-authored-by: Lance Martin <lance@langchain.dev>
2024-01-31 16:46:35 -08:00
Eugene Yurtsev
2e5949b6f8 core(minor): Add bulk add messages to BaseChatMessageHistory interface (#15709)
* Add bulk add_messages method to the interface.
* Update documentation for add_ai_message and add_human_message to
denote them as being marked for deprecation. We should stop using them
as they create more incorrect (inefficient) ways of doing things
2024-01-31 11:59:39 -08:00
Christophe Bornet
af8c5c185b langchain[minor],community[minor]: Add async methods in BaseLoader (#16634)
Adds:
* methods `aload()` and `alazy_load()` to interface `BaseLoader`
* implementation for class `MergedDataLoader `
* support for class `BaseLoader` in async function `aindex()` with unit
tests

Note: this is compatible with existing `aload()` methods that some
loaders already had.

**Twitter handle:** @cbornet_

---------

Co-authored-by: Eugene Yurtsev <eugene@langchain.dev>
2024-01-31 11:08:11 -08:00
Erick Friis
c37ca45825 nvidia-trt: remove tritonclient all extra dep (#16749) 2024-01-30 16:06:19 -08:00
Erick Friis
36c0392dbe infra: remove unnecessary tests on partner packages (#16808) 2024-01-30 16:01:47 -08:00
Erick Friis
bb3b6bde33 openai[minor]: change to secretstr (#16803) 2024-01-30 15:49:56 -08:00
Raphael
bf9068516e community[minor]: add the ability to load existing transcripts from AssemblyAI by their id. (#16051)
- **Description:** the existing AssemblyAI API allows to pass a path or
an url to transcribe an audio file and turn in into Langchain Documents,
this PR allows to get existing transcript by their transcript id and
turn them into Documents.
  - **Issue:** not related to an existing issue
  - **Dependencies:** requests

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-30 13:47:45 -08:00
Bagatur
daf820c77b community[patch]: undo create_sql_agent breaking (#16797) 2024-01-30 10:00:52 -08:00
Eugene Yurtsev
ef2bd745cb docs: Update doc-string in base callback managers (#15885)
Update doc-strings with a comment about on_llm_start vs.
on_chat_model_start.
2024-01-30 09:51:45 -08:00
William FH
881dc28d2c Fix Dep Recommendation (#16793)
Tools are different than functions
2024-01-30 09:40:28 -08:00
Bagatur
b0347f3e2b docs: add csv use case (#16756) 2024-01-30 09:39:46 -08:00
Alexander Conway
4acd2654a3 Report which file was errored on in DirectoryLoader (#16790)
The current implementation leaves it up to the particular file loader
implementation to report the file on which an error was encountered - in
my case pdfminer was simply saying it could not parse a file as a PDF,
but I didn't know which of my hundreds of files it was failing on.

No reason not to log the particular item on which an error was
encountered, and it should be an immense debugging assistant.

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-01-30 09:14:58 -08:00
Erick Friis
a372b23675 robocorp: release 0.0.3 (#16789) 2024-01-30 07:15:25 -08:00
Rihards Gravis
442fa52b30 [partners]: langchain-robocorp ease dependency version (#16765) 2024-01-30 08:13:54 -07:00
Jacob Lee
c6724a39f4 Fix rephrase step in chatbot use case (#16763) 2024-01-29 23:25:25 -08:00
Bob Lin
546b757303 community: Add ChatGLM3 (#15265)
Add [ChatGLM3](https://github.com/THUDM/ChatGLM3) and updated
[chatglm.ipynb](https://python.langchain.com/docs/integrations/llms/chatglm)

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-29 20:30:52 -08:00
Marina Pliusnina
a1ce7ab672 adding parameter for changing the language in SpacyEmbeddings (#15743)
Description: Added the parameter for a possibility to change a language
model in SpacyEmbeddings. The default value is still the same:
"en_core_web_sm", so it shouldn't affect a code which previously did not
specify this parameter, but it is not hard-coded anymore and easy to
change in case you want to use it with other languages or models.

Issue: At Barcelona Supercomputing Center in Aina project
(https://github.com/projecte-aina), a project for Catalan Language
Models and Resources, we would like to use Langchain for one of our
current projects and we would like to comment that Langchain, while
being a very powerful and useful open-source tool, is pretty much
focused on English language. We would like to contribute to make it a
bit more adaptable for using with other languages.

Dependencies: This change requires the Spacy library and a language
model, specified in the model parameter.

Tag maintainer: @dev2049

Twitter handle: @projecte_aina

---------

Co-authored-by: Marina Pliusnina <marina.pliusnina@bsc.es>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-29 20:30:34 -08:00
Christophe Bornet
744070ee85 Add async methods for the AstraDB VectorStore (#16391)
- **Description**: fully async versions are available for astrapy 0.7+.
For older astrapy versions or if the user provides a sync client without
an async one, the async methods will call the sync ones wrapped in
`run_in_executor`
  - **Twitter handle:** cbornet_
2024-01-29 20:22:25 -08:00
baichuan-assistant
f8f2649f12 community: Add Baichuan LLM to community (#16724)
Replace this entire comment with:
- **Description:** Add Baichuan LLM to integration/llm, also updated
related docs.

Co-authored-by: BaiChuanHelper <wintergyc@WinterGYCs-MacBook-Pro.local>
2024-01-29 20:08:24 -08:00
thiswillbeyourgithub
1d082359ee community: add support for callable filters in FAISS (#16190)
- **Description:**
Filtering in a FAISS vectorstores is very inflexible and doesn't allow
that many use case. I think supporting callable like this enables a lot:
regular expressions, condition on multiple keys etc. **Note** I had to
manually alter a test. I don't understand if it was falty to begin with
or if there is something funky going on.
- **Issue:** None
- **Dependencies:** None
- **Twitter handle:** None

Signed-off-by: thiswillbeyourgithub <26625900+thiswillbeyourgithub@users.noreply.github.com>
2024-01-29 20:05:56 -08:00
Yudhajit Sinha
1703fe2361 core[patch]: preserve inspect.iscoroutinefunction with @beta decorator (#16440)
Adjusted deprecate decorator to make sure decorated async functions are
still recognized as "coroutinefunction" by inspect

Addresses #16402

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-29 20:01:11 -08:00
Killinsun - Ryota Takeuchi
52f4ad8216 community: Add new fields in metadata for qdrant vector store (#16608)
## Description

The PR is to return the ID and collection name from qdrant client to
metadata field in `Document` class.

## Issue

The motivation is almost same to
[11592](https://github.com/langchain-ai/langchain/issues/11592)

Returning ID is useful to update existing records in a vector store, but
we cannot know them if we use some retrievers.

In order to avoid any conflicts, breaking changes, the new fields in
metadata have a prefix `_`

## Dependencies

N/A

## Twitter handle

@kill_in_sun

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-01-29 19:59:54 -08:00
hulitaitai
32cad38ec6 <langchain_community\llms\chatglm.py>: <Correcting "history"> (#16729)
Use the real "history" provided by the original program instead of
putting "None" in the history.

- **Description:** I change one line in the code to make it return the
"history" of the chat model.
- **Issue:** At the moment it returns only the answers of the chat
model. However the chat model himself provides a history more complet
with the questions of the user.
  - **Dependencies:** no dependencies required for this change,
2024-01-29 19:50:31 -08:00
Jacob Lee
4a027e622f docs[patch]: Lower temperature in chatbot usecase notebooks for consistency (#16750)
CC @baskaryan
2024-01-29 17:27:13 -08:00
Jacob Lee
12d2b2ebcf docs[minor]: LCEL rewrite of chatbot use-case (#16414)
CC @baskaryan @hwchase17

TODO:
- [x] Draft of main quickstart
- [x] Index intro page
- [x] Add subpage guide for Memory management
- [x] Add subpage guide for Retrieval
- [x] Add subpage guide for Tool usage
- [x] Add LangSmith traces illustrating query transformation
2024-01-29 17:08:54 -08:00
Bassem Yacoube
85e93e05ed community[minor]: Update OctoAI LLM, Embedding and documentation (#16710)
This PR includes updates for OctoAI integrations:
- The LLM class was updated to fix a bug that occurs with multiple
sequential calls
- The Embedding class was updated to support the new GTE-Large endpoint
released on OctoAI lately
- The documentation jupyter notebook was updated to reflect using the
new LLM sdk
Thank you!
2024-01-29 13:57:17 -08:00
Hank
6d6226d96d docs: Remove accidental extra ``` in QuickStart doc. (#16740)
Description: One too many set of triple-ticks in a sample code block in
the QuickStart doc was causing "\`\`\`shell" to appear in the shell
command that was being demonstrated. I just deleted the extra "```".
Issue: Didn't see one
Dependencies: None
2024-01-29 13:55:26 -08:00
Shay Ben Elazar
84ebfb5b9d openai[patch]: Added annotations support to azure openai (#13704)
- **Description:** Added Azure OpenAI Annotations (content filtering
results) to ChatResult

  - **Issue:** 13090

  - **Twitter handle:** ElazarShay

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-29 13:31:09 -08:00
Volodymyr Machula
32c5be8b73 community[minor]: Connery Tool and Toolkit (#14506)
## Summary

This PR implements the "Connery Action Tool" and "Connery Toolkit".
Using them, you can integrate Connery actions into your LangChain agents
and chains.

Connery is an open-source plugin infrastructure for AI.

With Connery, you can easily create a custom plugin with a set of
actions and seamlessly integrate them into your LangChain agents and
chains. Connery will handle the rest: runtime, authorization, secret
management, access management, audit logs, and other vital features.
Additionally, Connery and our community offer a wide range of
ready-to-use open-source plugins for your convenience.

Learn more about Connery:

- GitHub: https://github.com/connery-io/connery-platform
- Documentation: https://docs.connery.io
- Twitter: https://twitter.com/connery_io

## TODOs

- [x] API wrapper
   - [x] Integration tests
- [x] Connery Action Tool
   - [x] Docs
   - [x] Example
   - [x] Integration tests
- [x] Connery Toolkit
  - [x] Docs
  - [x] Example
- [x] Formatting (`make format`)
- [x] Linting (`make lint`)
- [x] Testing (`make test`)
2024-01-29 12:45:03 -08:00
Harrison Chase
8457c31c04 community[patch]: activeloop ai tql deprecation (#14634)
Co-authored-by: AdkSarsen <adilkhan@activeloop.ai>
2024-01-29 12:43:54 -08:00
Neli Hateva
c95facc293 langchain[minor], community[minor]: Implement Ontotext GraphDB QA Chain (#16019)
- **Description:** Implement Ontotext GraphDB QA Chain
  - **Issue:** N/A
  - **Dependencies:** N/A
  - **Twitter handle:** @OntotextGraphDB
2024-01-29 12:25:53 -08:00
chyroc
a08f9a7ff9 langchain[patch]: support OpenAIAssistantRunnable async (#15302)
fix https://github.com/langchain-ai/langchain/issues/15299

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-29 12:19:47 -08:00
Elliot
39eb00d304 community[patch]: Adapt more parameters related to MemorySearchPayload for the search method of ZepChatMessageHistory (#15441)
- **Description:** To adapt more parameters related to
MemorySearchPayload for the search method of ZepChatMessageHistory,
  - **Issue:** None,
  - **Dependencies:** None,
  - **Twitter handle:** None
2024-01-29 11:45:55 -08:00
Kirushikesh DB
47bd58dc11 docs: Added illustration of using RetryOutputParser with LLMChain (#16722)
**Description:**
Updated the retry.ipynb notebook, it contains the illustrations of
RetryOutputParser in LangChain. But the notebook lacks to explain the
compatibility of RetryOutputParser with existing chains. This changes
adds some code to illustrate the workflow of using RetryOutputParser
with the user chain.

Changes:
1. Changed RetryWithErrorOutputParser with RetryOutputParser, as the
markdown text says so.
2. Added code at the last of the notebook to define a chain which passes
the LLM completions to the retry parser, which can be customised for
user needs.

**Issue:** 
Since RetryOutputParser/RetryWithErrorOutputParser does not implement
the parse function it cannot be used with LLMChain directly like
[this](https://python.langchain.com/docs/expression_language/cookbook/prompt_llm_parser#prompttemplate-llm-outputparser).
This also raised various issues #15133 #12175 #11719 still open, instead
of adding new features/code changes its best to explain the "how to
integrate LLMChain with retry parsers" clearly with an example in the
corresponding notebook.

Inspired from:
https://github.com/langchain-ai/langchain/issues/15133#issuecomment-1868972580

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-29 11:24:52 -08:00
Jael Gu
a1aa3a657c community[patch]: Milvus supports add & delete texts by ids (#16256)
# Description

To support [langchain
indexing](https://python.langchain.com/docs/modules/data_connection/indexing)
as requested by users, vectorstore Milvus needs to support:
- document addition by id (`add_documents` method with `ids` argument)
- delete by id (`delete` method with `ids` argument)

Example usage:

```python
from langchain.indexes import SQLRecordManager, index
from langchain.schema import Document
from langchain_community.vectorstores import Milvus
from langchain_openai import OpenAIEmbeddings

collection_name = "test_index"
embedding = OpenAIEmbeddings()
vectorstore = Milvus(embedding_function=embedding, collection_name=collection_name)

namespace = f"milvus/{collection_name}"
record_manager = SQLRecordManager(
    namespace, db_url="sqlite:///record_manager_cache.sql"
)
record_manager.create_schema()

doc1 = Document(page_content="kitty", metadata={"source": "kitty.txt"})
doc2 = Document(page_content="doggy", metadata={"source": "doggy.txt"})

index(
    [doc1, doc1, doc2],
    record_manager,
    vectorstore,
    cleanup="incremental",  # None, "incremental", or "full"
    source_id_key="source",
)
```

# Fix issues

Fix https://github.com/milvus-io/milvus/issues/30112

---------

Signed-off-by: Jael Gu <mengjia.gu@zilliz.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-29 11:19:50 -08:00
Michard Hugo
e9d3527b79 community[patch]: Add missing async similarity_distance_threshold handling in RedisVectorStoreRetriever (#16359)
Add missing async similarity_distance_threshold handling in
RedisVectorStoreRetriever

- **Description:** added method `_aget_relevant_documents` to
`RedisVectorStoreRetriever` that overrides parent method to add support
of `similarity_distance_threshold` in async mode (as for sync mode)
  - **Issue:** #16099
  - **Dependencies:** N/A
  - **Twitter handle:** N/A
2024-01-29 11:19:30 -08:00
Jarod Stewart
7c6a2a8384 templates: Ionic Shopping Assistant (#16648)
- **Description:** This is a template for creating shopping assistant
chat bots
- **Issue:** Example for creating a shopping assistant with OpenAI Tools
Agent
- **Dependencies:** Ionic
https://github.com/ioniccommerce/ionic_langchain
  - **Twitter handle:** @ioniccommerce

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2024-01-29 11:08:24 -08:00
Bagatur
7237dc67d4 core[patch]: Release 0.1.17 (#16737) 2024-01-29 11:02:29 -08:00
Anthony Bernabeu
2db79ab111 community[patch]: Implement TTL for DynamoDBChatMessageHistory (#15478)
- **Description:** Implement TTL for DynamoDBChatMessageHistory, 
  - **Issue:** see #15477,
  - **Dependencies:** N/A,

---------

Co-authored-by: Piyush Jain <piyushjain@duck.com>
2024-01-29 10:22:46 -08:00
Massimiliano Pronesti
1bc8d9a943 experimental[patch]: missing resolution strategy in anonymization (#16653)
- **Description:** Presidio-based anonymizers are not working because
`_remove_conflicts_and_get_text_manipulation_data` was being called
without a conflict resolution strategy. This PR fixes this issue. In
addition, it removes some mutable default arguments (antipattern).
 
To reproduce the issue, just run the very first cell of this
[notebook](https://python.langchain.com/docs/guides/privacy/2/) from
langchain's documentation.

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-01-29 09:56:16 -08:00
Abhinav
8e44363ec9 langchain_community: Update documentation for installing llama-cpp-python on windows (#16666)
**Description** : This PR updates the documentation for installing
llama-cpp-python on Windows.

- Updates install command to support pyproject.toml
- Makes CPU/GPU install instructions clearer
- Adds reinstall with GPU support command

**Issue**: Existing
[documentation](https://python.langchain.com/docs/integrations/llms/llamacpp#compiling-and-installing)
lists the following commands for installing llama-cpp-python
```
python setup.py clean
python setup.py install
````
The current version of the repo does not include a `setup.py` and uses a
`pyproject.toml` instead.
This can be replaced with
```
python -m pip install -e .
```
As explained in
https://github.com/abetlen/llama-cpp-python/issues/965#issuecomment-1837268339
**Dependencies**: None
**Twitter handle**: None

---------

Co-authored-by: blacksmithop <angstycoder101@gmaii.com>
2024-01-29 08:41:29 -08:00
taimo
d3d9244fee langchain-community: fix unicode escaping issue with SlackToolkit (#16616)
- **Description:** fix unicode escaping issue with SlackToolkit
  - **Issue:**  #16610
2024-01-29 08:38:12 -08:00
Benito Geordie
f3fdc5c5da community: Added integrations for ThirdAI's NeuralDB with Retriever and VectorStore frameworks (#15280)
**Description:** Adds ThirdAI NeuralDB retriever and vectorstore
integration. NeuralDB is a CPU-friendly and fine-tunable text retrieval
engine.
2024-01-29 08:35:42 -08:00
Jonathan Bennion
815896ff13 langchain: pubmed tool path update in doc (#16716)
- **Description:** The current pubmed tool documentation is referencing
the path to langchain core not the path to the tool in community. The
old tool redirects anyways, but for efficiency of using the more direct
path, just adding this documentation so it references the new path
  - **Issue:** doesn't fix an issue
  - **Dependencies:** no dependencies
  - **Twitter handle:** rooftopzen
2024-01-29 08:25:29 -08:00
Lance Martin
1bfadecdd2 Update Slack agent toolkit (#16732)
Co-authored-by: taimoOptTech <132860814+taimo3810@users.noreply.github.com>
2024-01-29 08:03:44 -08:00
Pashva Mehta
22d90800c8 community: Fixed schema discrepancy in from_texts function for weaviate vectorstore (#16693)
* Description: Fixed schema discrepancy in **from_texts** function for
weaviate vectorstore which created a redundant property "key" inside a
class.
* Issue: Fixed: https://github.com/langchain-ai/langchain/issues/16692
* Twitter handle: @pashvamehta1
2024-01-28 16:53:31 -08:00
Choi JaeHun
ba70630829 docs: Syntax correction according to langchain version update in 'Retry Parser' tutorial example (#16699)
- **Description:** Syntax correction according to langchain version
update in 'Retry Parser' tutorial example,
- **Issue:** #16698

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-28 16:53:04 -08:00
ccurme
ec0ae23645 core: expand docstring for RunnableGenerator (#16672)
- **Description:** expand docstring for RunnableGenerator
  - **Issue:** https://github.com/langchain-ai/langchain/issues/16631
2024-01-28 16:47:08 -08:00
Bob Lin
0866a984fe Update n_gpu_layers"s description (#16685)
The `n_gpu_layers` parameter in `llama.cpp` supports the use of `-1`,
which means to offload all layers to the GPU, so the document has been
updated.

Ref:
35918873b4/llama_cpp/server/settings.py (L29C22-L29C117)


35918873b4/llama_cpp/llama.py (L125)
2024-01-28 16:46:50 -08:00
Daniel Erenrich
0600998f38 community: Wikidata tool support (#16691)
- **Description:** Adds Wikidata support to langchain. Can read out
documents from Wikidata.
  - **Issue:** N/A
- **Dependencies:** Adds implicit dependencies for
`wikibase-rest-api-client` (for turning items into docs) and
`mediawikiapi` (for hitting the search endpoint)
  - **Twitter handle:** @derenrich

You can see an example of this tool used in a chain
[here](https://nbviewer.org/urls/d.erenrich.net/upload/Wikidata_Langchain.ipynb)
or
[here](https://nbviewer.org/urls/d.erenrich.net/upload/Wikidata_Lars_Kai_Hansen.ipynb)

<!-- Thank you for contributing to LangChain!


Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-01-28 16:45:21 -08:00
Tze Min
6ef718c5f4 Core: fix Anthropic json issue in streaming (#16670)
**Description:** fix ChatAnthropic json issue in streaming 
**Issue:** https://github.com/langchain-ai/langchain/issues/16423
**Dependencies:** n/a

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-28 16:41:17 -08:00
Owen Sims
e451c8adc1 Community: Update Ionic Shopping Docs (#16700)
- **Description:** Update to docs as originally introduced in
https://github.com/langchain-ai/langchain/pull/16649 (reviewed by
@baskaryan),
- **Twitter handle:**
[@ioniccommerce](https://twitter.com/ioniccommerce)
2024-01-28 16:39:49 -08:00
Christophe Bornet
2e3af04080 Use Postponed Evaluation of Annotations in Astra and Cassandra doc loaders (#16694)
Minor/cosmetic change
2024-01-28 16:39:27 -08:00
Yelin Zhang
bc7607a4e9 docs: remove iprogress warnings (#16697)
- **Description:** removes iprogress warning texts from notebooks,
resulting in a little nicer to read documentation
2024-01-28 16:38:14 -08:00
Erick Friis
0255c5808b infra: move release workflow back (#16707) 2024-01-28 12:11:23 -07:00
Erick Friis
88e3129587 robocorp: release 0.0.2 (#16706) 2024-01-28 11:28:58 -07:00
Christophe Bornet
36e432672a community[minor]: Add async methods to AstraDBLoader (#16652) 2024-01-27 17:05:41 -08:00
William FH
38425c99d2 core[minor]: Image prompt template (#14263)
Builds on Bagatur's (#13227). See unit test for example usage (below)

```python
def test_chat_tmpl_from_messages_multipart_image() -> None:
    base64_image = "abcd123"
    other_base64_image = "abcd123"
    template = ChatPromptTemplate.from_messages(
        [
            ("system", "You are an AI assistant named {name}."),
            (
                "human",
                [
                    {"type": "text", "text": "What's in this image?"},
                    # OAI supports all these structures today
                    {
                        "type": "image_url",
                        "image_url": "data:image/jpeg;base64,{my_image}",
                    },
                    {
                        "type": "image_url",
                        "image_url": {"url": "data:image/jpeg;base64,{my_image}"},
                    },
                    {"type": "image_url", "image_url": "{my_other_image}"},
                    {
                        "type": "image_url",
                        "image_url": {"url": "{my_other_image}", "detail": "medium"},
                    },
                    {
                        "type": "image_url",
                        "image_url": {"url": "https://www.langchain.com/image.png"},
                    },
                    {
                        "type": "image_url",
                        "image_url": {"url": "data:image/jpeg;base64,foobar"},
                    },
                ],
            ),
        ]
    )
    messages = template.format_messages(
        name="R2D2", my_image=base64_image, my_other_image=other_base64_image
    )
    expected = [
        SystemMessage(content="You are an AI assistant named R2D2."),
        HumanMessage(
            content=[
                {"type": "text", "text": "What's in this image?"},
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"},
                },
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/jpeg;base64,{other_base64_image}"
                    },
                },
                {
                    "type": "image_url",
                    "image_url": {"url": f"{other_base64_image}"},
                },
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"{other_base64_image}",
                        "detail": "medium",
                    },
                },
                {
                    "type": "image_url",
                    "image_url": {"url": "https://www.langchain.com/image.png"},
                },
                {
                    "type": "image_url",
                    "image_url": {"url": "data:image/jpeg;base64,foobar"},
                },
            ]
        ),
    ]
    assert messages == expected
```

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Brace Sproul <braceasproul@gmail.com>
2024-01-27 17:04:29 -08:00
ARKA1112
3c387bc12d docs: Error when importing packages from pydantic [docs] (#16564)
URL : https://python.langchain.com/docs/use_cases/extraction

Desc: 
<b> While the following statement executes successfully, it throws an
error which is described below when we use the imported packages</b>
 ```py 
from pydantic import BaseModel, Field, validator
```
Code: 
```python
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import (
    PromptTemplate,
)
from langchain_openai import OpenAI
from pydantic import BaseModel, Field, validator

# Define your desired data structure.
class Joke(BaseModel):
    setup: str = Field(description="question to set up a joke")
    punchline: str = Field(description="answer to resolve the joke")

    # You can add custom validation logic easily with Pydantic.
    @validator("setup")
    def question_ends_with_question_mark(cls, field):
        if field[-1] != "?":
            raise ValueError("Badly formed question!")
        return field
```

Error:
```md
PydanticUserError: The `field` and `config` parameters are not available
in Pydantic V2, please use the `info` parameter instead.

For further information visit
https://errors.pydantic.dev/2.5/u/validator-field-config-info
```

Solution:
Instead of doing:
```py
from pydantic import BaseModel, Field, validator
```
We should do:
```py
from langchain_core.pydantic_v1 import BaseModel, Field, validator
```
Thanks.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-27 16:46:48 -08:00
Rashedul Hasan Rijul
481493dbce community[patch]: apply embedding functions during query if defined (#16646)
**Description:** This update ensures that the user-defined embedding
function specified during vector store creation is applied during
queries. Previously, even if a custom embedding function was defined at
the time of store creation, Bagel DB would default to using the standard
embedding function during query execution. This pull request addresses
this issue by consistently using the user-defined embedding function for
queries if one has been specified earlier.
2024-01-27 16:46:33 -08:00
Serena Ruan
f01fb47597 community[patch]: MLflowCallbackHandler -- Move textstat and spacy as optional dependency (#16657)
Signed-off-by: Serena Ruan <serena.rxy@gmail.com>
2024-01-27 16:15:07 -08:00
Zhuoyun(John) Xu
508bde7f40 community[patch]: Ollama - Pass headers to post request in async method (#16660)
# Description
A previous PR (https://github.com/langchain-ai/langchain/pull/15881)
added option to pass headers to ollama endpoint, but headers are not
pass to the async method.
2024-01-27 16:11:32 -08:00
Leonid Ganeline
5e73603e8a docs: DeepInfra provider page update (#16665)
- added description, links
- consistent formatting
- added links to the example pages
2024-01-27 16:05:29 -08:00
João Carlos Ferra de Almeida
3e87b67a3c community[patch]: Add Cookie Support to Fetch Method (#16673)
- **Description:** This change allows the `_fetch` method in the
`WebBaseLoader` class to utilize cookies from an existing
`requests.Session`. It ensures that when the `fetch` method is used, any
cookies in the provided session are included in the request. This
enhancement maintains compatibility with existing functionality while
extending the utility of the `fetch` method for scenarios where cookie
persistence is necessary.
- **Issue:** Not applicable (new feature),
- **Dependencies:** Requires `aiohttp` and `requests` libraries (no new
dependencies introduced),
- **Twitter handle:** N/A

Co-authored-by: Joao Almeida <joao.almeida@mercedes-benz.io>
2024-01-27 16:03:53 -08:00
Daniel Erenrich
c314137f5b docs: Fix broken link in CONTRIBUTING.md (#16681)
- **Description:** link in CONTRIBUTING.md is broken
  - **Issue:** N/A
  - **Dependencies:** N/A
  - **Twitter handle:** @derenrich
2024-01-27 15:43:44 -08:00
Harrison Chase
27665e3546 [community] fix anthropic streaming (#16682) 2024-01-27 15:16:22 -08:00
Bagatur
5975bf39ec infra: delete old CI workflows (#16680) 2024-01-27 14:14:53 -08:00
Christophe Bornet
4915c3cd86 [Fix] Fix Cassandra Document loader default page content mapper (#16273)
We can't use `json.dumps` by default as many types returned by the
cassandra driver are not serializable. It's safer to use `str` and let
users define their own custom `page_content_mapper` if needed.
2024-01-27 11:23:02 -08:00
Nuno Campos
e86fd946c8 In stream_event and stream_log handle closed streams (#16661)
if eg. the stream iterator is interrupted then adding more events to the
send_stream will raise an exception that we should catch (and handle
where appropriate)

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

Replace this entire comment with:
  - **Description:** a description of the change, 
  - **Issue:** the issue # it fixes if applicable,
  - **Dependencies:** any dependencies required for this change,
- **Twitter handle:** we announce bigger features on Twitter. If your PR
gets announced, and you'd like a mention, we'll gladly shout you out!

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
2. an example notebook showing its use. It lives in
`docs/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2024-01-27 08:09:29 -08:00
Jarod Stewart
0bc397957b docs: document Ionic Tool (#16649)
- **Description:** Documentation for the Ionic Tool. A shopping
assistant tool that effortlessly adds e-commerce capabilities to your
Agent.
2024-01-26 16:02:07 -08:00
Nuno Campos
52ccae3fb1 Accept message-like things in Chat models, LLMs and MessagesPlaceholder (#16418) 2024-01-26 15:44:28 -08:00
Seungwoo Ryu
570b4f8e66 docs: Update openai_tools.ipynb (#16618)
typo
2024-01-26 15:26:27 -08:00
Pasha
4e189cd89a community[patch]: youtube loader transcript format (#16625)
- **Description**: YoutubeLoader right now returns one document that
contains the entire transcript. I think it would be useful to add an
option to return multiple documents, where each document would contain
one line of transcript with the start time and duration in the metadata.
For example,
[AssemblyAIAudioTranscriptLoader](https://github.com/langchain-ai/langchain/blob/master/libs/community/langchain_community/document_loaders/assemblyai.py)
is implemented in a similar way, it allows you to choose between the
format to use for the document loader.
2024-01-26 15:26:09 -08:00
yin1991
a936472512 docs: Update documentation to use 'model_id' rather than 'model_name' to match actual API (#16615)
- **Description:** Replace 'model_name' with 'model_id' for accuracy 
- **Issue:**
[link-to-issue](https://github.com/langchain-ai/langchain/issues/16577)
  - **Dependencies:** 
  - **Twitter handle:**
2024-01-26 15:01:12 -08:00
Micah Parker
6543e585a5 community[patch]: Added support for Ollama's num_predict option in ChatOllama (#16633)
Just a simple default addition to the options payload for a ollama
generate call to support a max_new_tokens parameter.

Should fix issue: https://github.com/langchain-ai/langchain/issues/14715
2024-01-26 15:00:19 -08:00
Callum
6a75ef74ca docs: Fix typo in XML agent documentation (#16645)
This is a tiny PR that just replacer "moduels" with "modules" in the
documentation for XML agents.
2024-01-26 14:59:46 -08:00
baichuan-assistant
70ff54eace community[minor]: Add Baichuan Text Embedding Model and Baichuan Inc introduction (#16568)
- **Description:** Adding Baichuan Text Embedding Model and Baichuan Inc
introduction.

Baichuan Text Embedding ranks #1 in C-MTEB leaderboard:
https://huggingface.co/spaces/mteb/leaderboard

Co-authored-by: BaiChuanHelper <wintergyc@WinterGYCs-MacBook-Pro.local>
2024-01-26 12:57:26 -08:00
Bagatur
5b5115c408 google-vertexai[patch]: streaming bug (#16603)
Fixes errors seen here
https://github.com/langchain-ai/langchain/actions/runs/7661680517/job/20881556592#step:9:229
2024-01-26 09:45:34 -08:00
457 changed files with 24428 additions and 5040 deletions

View File

@@ -13,7 +13,7 @@ There are many ways to contribute to LangChain. Here are some common ways people
- [**Documentation**](https://python.langchain.com/docs/contributing/documentation): Help improve our docs, including this one!
- [**Code**](https://python.langchain.com/docs/contributing/code): Help us write code, fix bugs, or improve our infrastructure.
- [**Integrations**](https://python.langchain.com/docs/contributing/integration): Help us integrate with your favorite vendors and tools.
- [**Integrations**](https://python.langchain.com/docs/contributing/integrations): Help us integrate with your favorite vendors and tools.
### 🚩GitHub Issues

View File

@@ -36,13 +36,7 @@ if __name__ == "__main__":
elif "libs/partners" in file:
partner_dir = file.split("/")[2]
if os.path.isdir(f"libs/partners/{partner_dir}"):
dirs_to_run.update(
(
f"libs/partners/{partner_dir}",
"libs/langchain",
"libs/experimental",
)
)
dirs_to_run.add(f"libs/partners/{partner_dir}")
# Skip if the directory was deleted
elif "libs/langchain" in file:
dirs_to_run.update(("libs/langchain", "libs/experimental"))

View File

@@ -36,30 +36,35 @@ env:
jobs:
lint:
name: "-"
uses: ./.github/workflows/_lint.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
test:
name: "-"
uses: ./.github/workflows/_test.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
compile-integration-tests:
name: "-"
uses: ./.github/workflows/_compile_integration_test.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
dependencies:
name: "-"
uses: ./.github/workflows/_dependencies.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
extended-tests:
name: "make extended_tests #${{ matrix.python-version }}"
runs-on: ubuntu-latest
strategy:
matrix:
@@ -68,7 +73,6 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
name: Python ${{ matrix.python-version }} extended tests
defaults:
run:
working-directory: ${{ inputs.working-directory }}

View File

@@ -24,7 +24,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
name: Python ${{ matrix.python-version }}
name: "poetry run pytest -m compile tests/integration_tests #${{ matrix.python-version }}"
steps:
- uses: actions/checkout@v4

View File

@@ -28,7 +28,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
name: dependencies - Python ${{ matrix.python-version }}
name: dependency checks ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v4

View File

@@ -56,6 +56,7 @@ jobs:
GOOGLE_SEARCH_API_KEY: ${{ secrets.GOOGLE_SEARCH_API_KEY }}
GOOGLE_CSE_ID: ${{ secrets.GOOGLE_CSE_ID }}
EXA_API_KEY: ${{ secrets.EXA_API_KEY }}
NOMIC_API_KEY: ${{ secrets.NOMIC_API_KEY }}
run: |
make integration_tests

View File

@@ -21,6 +21,7 @@ env:
jobs:
build:
name: "make lint #${{ matrix.python-version }}"
runs-on: ubuntu-latest
strategy:
matrix:
@@ -85,7 +86,7 @@ jobs:
with:
path: |
${{ env.WORKDIR }}/.mypy_cache
key: mypy-lint-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ inputs.working-directory }}-${{ hashFiles(format('{0}/poetry.lock', env.WORKDIR)) }}
key: mypy-lint-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ inputs.working-directory }}-${{ hashFiles(format('{0}/poetry.lock', inputs.working-directory)) }}
- name: Analysing the code with our lint
@@ -113,7 +114,7 @@ jobs:
with:
path: |
${{ env.WORKDIR }}/.mypy_cache_test
key: mypy-test-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ inputs.working-directory }}-${{ hashFiles(format('{0}/poetry.lock', env.WORKDIR)) }}
key: mypy-test-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ inputs.working-directory }}-${{ hashFiles(format('{0}/poetry.lock', inputs.working-directory)) }}
- name: Analysing the code with our lint
working-directory: ${{ inputs.working-directory }}

View File

@@ -175,6 +175,7 @@ jobs:
GOOGLE_SEARCH_API_KEY: ${{ secrets.GOOGLE_SEARCH_API_KEY }}
GOOGLE_CSE_ID: ${{ secrets.GOOGLE_CSE_ID }}
EXA_API_KEY: ${{ secrets.EXA_API_KEY }}
NOMIC_API_KEY: ${{ secrets.NOMIC_API_KEY }}
run: make integration_tests
working-directory: ${{ inputs.working-directory }}

View File

@@ -28,7 +28,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
name: Python ${{ matrix.python-version }}
name: "make test #${{ matrix.python-version }}"
steps:
- uses: actions/checkout@v4

View File

@@ -1,5 +1,5 @@
---
name: Check library diffs
name: CI
on:
push:
@@ -32,6 +32,7 @@ jobs:
outputs:
dirs-to-run: ${{ steps.set-matrix.outputs.dirs-to-run }}
ci:
name: cd ${{ matrix.working-directory }}
needs: [ build ]
strategy:
matrix:

View File

@@ -1,5 +1,5 @@
---
name: Codespell
name: CI / cd . / make spell_check
on:
push:
@@ -12,7 +12,7 @@ permissions:
jobs:
codespell:
name: Check for spelling errors
name: (Check for spelling errors)
runs-on: ubuntu-latest
steps:

View File

@@ -1,5 +1,5 @@
---
name: Docs, templates, cookbook lint
name: CI / cd .
on:
push:
@@ -15,6 +15,7 @@ on:
jobs:
check:
name: Check for "from langchain import x" imports
runs-on: ubuntu-latest
steps:
@@ -28,6 +29,7 @@ jobs:
git grep 'from langchain import' {docs/docs,templates,cookbook} | grep -vE 'from langchain import (hub)' && exit 1 || exit 0
lint:
name: "-"
uses:
./.github/workflows/_lint.yml
with:

View File

@@ -1,13 +0,0 @@
---
name: libs/cli Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_release.yml
with:
working-directory: libs/cli
secrets: inherit

View File

@@ -1,13 +0,0 @@
---
name: libs/community Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_release.yml
with:
working-directory: libs/community
secrets: inherit

View File

@@ -1,13 +0,0 @@
---
name: libs/core Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_release.yml
with:
working-directory: libs/core
secrets: inherit

View File

@@ -1,13 +0,0 @@
---
name: libs/experimental Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_release.yml
with:
working-directory: libs/experimental
secrets: inherit

View File

@@ -1,13 +0,0 @@
---
name: Experimental Test Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_test_release.yml
with:
working-directory: libs/experimental
secrets: inherit

View File

@@ -1,13 +0,0 @@
---
name: libs/core Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_release.yml
with:
working-directory: libs/core
secrets: inherit

View File

@@ -1,27 +0,0 @@
---
name: libs/langchain Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_release.yml
with:
working-directory: libs/langchain
secrets: inherit
# N.B.: It's possible that PyPI doesn't make the new release visible / available
# immediately after publishing. If that happens, the docker build might not
# create a new docker image for the new release, since it won't see it.
#
# If this ends up being a problem, add a check to the end of the `_release.yml`
# workflow that prevents the workflow from finishing until the new release
# is visible and installable on PyPI.
release-docker:
needs:
- release
uses:
./.github/workflows/langchain_release_docker.yml
secrets: inherit

View File

@@ -1,13 +0,0 @@
---
name: Test Release
on:
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
jobs:
release:
uses:
./.github/workflows/_test_release.yml
with:
working-directory: libs/langchain
secrets: inherit

View File

@@ -1,36 +0,0 @@
---
name: templates CI
on:
push:
branches: [ master ]
pull_request:
paths:
- '.github/actions/poetry_setup/action.yml'
- '.github/tools/**'
- '.github/workflows/_lint.yml'
- '.github/workflows/templates_ci.yml'
- 'templates/**'
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
# If another push to the same PR or branch happens while this workflow is still running,
# cancel the earlier run in favor of the next run.
#
# There's no point in testing an outdated version of the code. GitHub only allows
# a limited number of job runners to be active at the same time, so it's better to cancel
# pointless jobs early so that more useful jobs can run sooner.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
POETRY_VERSION: "1.7.1"
WORKDIR: "templates"
jobs:
lint:
uses:
./.github/workflows/_lint.yml
with:
working-directory: templates
secrets: inherit

View File

@@ -1,6 +1,6 @@
# 🦜️🔗 LangChain
⚡ Building applications with LLMs through composability
⚡ Build context-aware reasoning applications
[![Release Notes](https://img.shields.io/github/release/langchain-ai/langchain)](https://github.com/langchain-ai/langchain/releases)
[![CI](https://github.com/langchain-ai/langchain/actions/workflows/check_diffs.yml/badge.svg)](https://github.com/langchain-ai/langchain/actions/workflows/check_diffs.yml)

File diff suppressed because one or more lines are too long

View File

@@ -670,8 +670,6 @@ local_llm = HuggingFacePipeline(pipeline=pipe)
<CodeOutputBlock lang="python">
```
/workspace/langchain/.venv/lib/python3.9/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
Loading checkpoint shards: 100%|██████████| 8/8 [00:32<00:00, 4.11s/it]
```

View File

@@ -16,7 +16,8 @@ cp ../cookbook/README.md src/pages/cookbook.mdx
mkdir -p docs/templates
cp ../templates/docs/INDEX.md docs/templates/index.md
poetry run python scripts/copy_templates.py
wget https://raw.githubusercontent.com/langchain-ai/langserve/main/README.md -O docs/langserve.md
wget -q https://raw.githubusercontent.com/langchain-ai/langserve/main/README.md -O docs/langserve.md
wget -q https://raw.githubusercontent.com/langchain-ai/langgraph/main/README.md -O docs/langgraph.md
yarn

View File

@@ -132,6 +132,8 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
#
html_theme = "scikit-learn-modern"
html_theme_path = ["themes"]
html_theme_options = {"navigation_depth": 2, "collapse_navigation": True}
html_copy_source = False
# redirects dictionary maps from old links to new links
html_additional_pages = {}

File diff suppressed because one or more lines are too long

View File

@@ -37,7 +37,7 @@ from langchain_community.llms import integration_class_REPLACE_ME
## Text Embedding Models
See a [usage example](/docs/integrations/text_embedding/INCLUDE_REAL_NAME)
See a [usage example](/docs/integrations/text_embedding/INCLUDE_REAL_NAME).
```python
from langchain_community.embeddings import integration_class_REPLACE_ME
@@ -45,7 +45,7 @@ from langchain_community.embeddings import integration_class_REPLACE_ME
## Chat models
See a [usage example](/docs/integrations/chat/INCLUDE_REAL_NAME)
See a [usage example](/docs/integrations/chat/INCLUDE_REAL_NAME).
```python
from langchain_community.chat_models import integration_class_REPLACE_ME

View File

@@ -7,7 +7,7 @@
"source": [
"# Add message history (memory)\n",
"\n",
"The `RunnableWithMessageHistory` let's us add message history to certain types of chains.\n",
"The `RunnableWithMessageHistory` let us add message history to certain types of chains.\n",
"\n",
"Specifically, it can be used for any Runnable that takes as input one of\n",
"\n",

View File

@@ -93,6 +93,3 @@ Head to the reference section for full documentation of all classes and methods
### [Developer's guide](/docs/contributing)
Check out the developer's guide for guidelines on contributing and help getting your dev environment set up.
### [Community](/docs/community)
Head to the [Community navigator](/docs/community) to find places to ask questions, share feedback, meet other developers, and dream about the future of LLMs.

View File

@@ -184,7 +184,6 @@ A Retriever can be backed by anything - a SQL table, the internet, etc - but in
First, we need to load the data that we want to index. In order to do this, we will use the WebBaseLoader. This requires installing [BeautifulSoup](https://beautiful-soup-4.readthedocs.io/en/latest/):
```
```shell
pip install beautifulsoup4
```

View File

@@ -98,7 +98,7 @@ The LLM landscape is evolving at an unprecedented pace, with new libraries and m
### Model composition
Deploying systems like LangChain demands the ability to piece together different models and connect them via logic. Take the example of building a natural language input SQL query engine. Querying an LLM and obtaining the SQL command is only part of the system. You need to extract metadata from the connected database, construct a prompt for the LLM, run the SQL query on an engine, collect and feed back the response to the LLM as the query runs, and present the results to the user. This demonstrates the need to seamlessly integrate various complex components built in Python into a dynamic chain of logical blocks that can be served together.
Deploying systems like LangChain demands the ability to piece together different models and connect them via logic. Take the example of building a natural language input SQL query engine. Querying an LLM and obtaining the SQL command is only part of the system. You need to extract metadata from the connected database, construct a prompt for the LLM, run the SQL query on an engine, collect and feedback the response to the LLM as the query runs, and present the results to the user. This demonstrates the need to seamlessly integrate various complex components built in Python into a dynamic chain of logical blocks that can be served together.
## Cloud providers

View File

@@ -51,10 +51,18 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"or you can set `api_key` in your environment variables\n",
"```bash\n",
"export BAICHUAN_API_KEY=YOUR_API_KEY\n",
"```"
"Alternatively, you can set your API key with:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ[\"BAICHUAN_API_KEY\"] = \"YOUR_API_KEY\""
]
},
{

View File

@@ -26,8 +26,6 @@
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 22.0.4; however, version 23.3.1 is available.\n",
"You should consider upgrading via the '/Users/jacoblee/langchain/langchain/libs/langchain/.venv/bin/python -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n",
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
}
@@ -56,16 +54,7 @@
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/jacoblee/langchain/langchain/libs/langchain/.venv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
}
],
"outputs": [],
"source": [
"import os\n",
"\n",

View File

@@ -19,7 +19,19 @@
"\n",
"This notebook covers how to get started with MistralAI chat models, via their [API](https://docs.mistral.ai/api/).\n",
"\n",
"A valid [API key](https://console.mistral.ai/users/api-keys/) is needed to communicate with the API."
"A valid [API key](https://console.mistral.ai/users/api-keys/) is needed to communicate with the API.\n",
"\n",
"You will need the `langchain-mistralai` package to use the API. You can install it via pip:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb978a7e",
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-core langchain-mistralai"
]
},
{

File diff suppressed because one or more lines are too long

View File

@@ -27,17 +27,17 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 1,
"id": "0cb0f937-b610-42a2-b765-336eed037031",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdin",
"name": "stdout",
"output_type": "stream",
"text": [
" ········\n"
"········\n"
]
}
],
@@ -51,21 +51,20 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 2,
"id": "6fb585dd",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.chains import LLMChain\n",
"from langchain.prompts import PromptTemplate\n",
"from langchain_community.llms import AlephAlpha"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 3,
"id": "f81a230d",
"metadata": {
"tags": []
@@ -81,7 +80,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 4,
"id": "f0d26e48",
"metadata": {
"tags": []
@@ -98,19 +97,19 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 5,
"id": "6811d621",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"llm_chain = LLMChain(prompt=prompt, llm=llm)"
"llm_chain = prompt | llm"
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 8,
"id": "3058e63f",
"metadata": {
"tags": []
@@ -119,10 +118,10 @@
{
"data": {
"text/plain": [
"' Artificial Intelligence (AI) is the simulation of human intelligence processes by machines, especially computer systems.\\n'"
"' Artificial Intelligence is the simulation of human intelligence processes by machines.\\n\\n'"
]
},
"execution_count": 10,
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@@ -130,8 +129,16 @@
"source": [
"question = \"What is AI?\"\n",
"\n",
"llm_chain.run(question)"
"llm_chain.invoke({\"question\": question})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a3544eff",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@@ -150,7 +157,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.9.12"
},
"vscode": {
"interpreter": {

View File

@@ -0,0 +1,97 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Baichuan LLM\n",
"Baichuan Inc. (https://www.baichuan-ai.com/) is a Chinese startup in the era of AGI, dedicated to addressing fundamental human needs: Efficiency, Health, and Happiness."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prerequisite\n",
"An API key is required to access Baichuan LLM API. Visit https://platform.baichuan-ai.com/ to get your API key."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Use Baichuan LLM"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ[\"BAICHUAN_API_KEY\"] = \"YOUR_API_KEY\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.llms import BaichuanLLM\n",
"\n",
"# Load the model\n",
"llm = BaichuanLLM()\n",
"\n",
"res = llm(\"What's your name?\")\n",
"print(res)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"res = llm.generate(prompts=[\"你好!\"])\n",
"res"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for res in llm.stream(\"Who won the second world war?\"):\n",
" print(res)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"\n",
"\n",
"async def run_aio_stream():\n",
" async for res in llm.astream(\"Write a poem about the sun.\"):\n",
" print(res)\n",
"\n",
"\n",
"asyncio.run(run_aio_stream())"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -111,8 +111,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Guardrails for Amazon Bedrock example \n",
"\n",
"## Guardrails for Amazon Bedrock (Preview) \n",
"[Guardrails for Amazon Bedrock](https://aws.amazon.com/bedrock/guardrails/) evaluates user inputs and model responses based on use case specific policies, and provides an additional layer of safeguards regardless of the underlying model. Guardrails can be applied across models, including Anthropic Claude, Meta Llama 2, Cohere Command, AI21 Labs Jurassic, and Amazon Titan Text, as well as fine-tuned models.\n",
"**Note**: Guardrails for Amazon Bedrock is currently in preview and not generally available. Reach out through your usual AWS Support contacts if youd like access to this feature.\n",
"In this section, we are going to set up a Bedrock language model with specific guardrails that include tracing capabilities. "
]
},

View File

@@ -11,7 +11,102 @@
"\n",
"[ChatGLM2-6B](https://github.com/THUDM/ChatGLM2-6B) is the second-generation version of the open-source bilingual (Chinese-English) chat model ChatGLM-6B. It retains the smooth conversation flow and low deployment threshold of the first-generation model, while introducing the new features like better performance, longer context and more efficient inference.\n",
"\n",
"This example goes over how to use LangChain to interact with ChatGLM2-6B Inference for text completion.\n",
"[ChatGLM3](https://github.com/THUDM/ChatGLM3) is a new generation of pre-trained dialogue models jointly released by Zhipu AI and Tsinghua KEG. ChatGLM3-6B is the open-source model in the ChatGLM3 series"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Install required dependencies\n",
"\n",
"%pip install -qU langchain langchain-community"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ChatGLM3\n",
"\n",
"This examples goes over how to use LangChain to interact with ChatGLM3-6B Inference for text completion."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains import LLMChain\n",
"from langchain.prompts import PromptTemplate\n",
"from langchain.schema.messages import AIMessage\n",
"from langchain_community.llms.chatglm3 import ChatGLM3"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"template = \"\"\"{question}\"\"\"\n",
"prompt = PromptTemplate(template=template, input_variables=[\"question\"])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"endpoint_url = \"http://127.0.0.1:8000/v1/chat/completions\"\n",
"\n",
"messages = [\n",
" AIMessage(content=\"我将从美国到中国来旅游,出行前希望了解中国的城市\"),\n",
" AIMessage(content=\"欢迎问我任何问题。\"),\n",
"]\n",
"\n",
"llm = ChatGLM3(\n",
" endpoint_url=endpoint_url,\n",
" max_tokens=80000,\n",
" prefix_messages=messages,\n",
" top_p=0.9,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'北京和上海是中国两个不同的城市,它们在很多方面都有所不同。\\n\\n北京是中国的首都,也是历史悠久的城市之一。它有着丰富的历史文化遗产,如故宫、颐和园等,这些景点吸引着众多游客前来观光。北京也是一个政治、文化和教育中心,有很多政府机构和学术机构总部设在北京。\\n\\n上海则是一个现代化的城市,它是中国的经济中心之一。上海拥有许多高楼大厦和国际化的金融机构,是中国最国际化的城市之一。上海也是一个美食和购物天堂,有许多著名的餐厅和购物中心。\\n\\n北京和上海的气候也不同。北京属于温带大陆性气候,冬季寒冷干燥,夏季炎热多风;而上海属于亚热带季风气候,四季分明,春秋宜人。\\n\\n北京和上海有很多不同之处,但都是中国非常重要的城市,每个城市都有自己独特的魅力和特色。'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_chain = LLMChain(prompt=prompt, llm=llm)\n",
"question = \"北京和上海两座城市有什么不同?\"\n",
"\n",
"llm_chain.run(question)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ChatGLM and ChatGLM2\n",
"\n",
"The following example shows how to use LangChain to interact with the ChatGLM2-6B Inference to complete text.\n",
"ChatGLM-6B and ChatGLM2-6B has the same api specs, so this example should work with both."
]
},
@@ -106,7 +201,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "langchain-dev",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -120,9 +215,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View File

@@ -144,24 +144,40 @@
"git clone --recursive -j8 https://github.com/abetlen/llama-cpp-python.git\n",
"```\n",
"\n",
"2. Open up command Prompt (or anaconda prompt if you have it installed), set up environment variables to install. Follow this if you do not have a GPU, you must set both of the following variables.\n",
"2. Open up a command Prompt and set the following environment variables.\n",
"\n",
"\n",
"```\n",
"set FORCE_CMAKE=1\n",
"set CMAKE_ARGS=-DLLAMA_CUBLAS=OFF\n",
"```\n",
"You can ignore the second environment variable if you have an NVIDIA GPU.\n",
"If you have an NVIDIA GPU make sure `DLLAMA_CUBLAS` is set to `ON`\n",
"\n",
"#### Compiling and installing\n",
"\n",
"In the same command prompt (anaconda prompt) you set the variables, you can `cd` into `llama-cpp-python` directory and run the following commands.\n",
"Now you can `cd` into the `llama-cpp-python` directory and install the package\n",
"\n",
"```\n",
"python setup.py clean\n",
"python setup.py install\n",
"python -m pip install -e .\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**IMPORTANT**: If you have already installed a cpu only version of the package, you need to reinstall it from scratch: consider the following command: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install -e . --force-reinstall --no-cache-dir"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -415,7 +431,7 @@
"metadata": {},
"outputs": [],
"source": [
"n_gpu_layers = 40 # Change this value based on your model and your GPU VRAM pool.\n",
"n_gpu_layers = -1 # The number of layers to put on the GPU. The rest will be on the CPU. If you don't know how many layers there are, you can use -1 to move all to GPU.\n",
"n_batch = 512 # Should be between 1 and n_ctx, consider the amount of VRAM in your GPU.\n",
"\n",
"# Make sure the model path is correct for your system!\n",
@@ -501,7 +517,7 @@
"metadata": {},
"outputs": [],
"source": [
"n_gpu_layers = 1 # Change this value based on your model and your GPU VRAM pool.\n",
"n_gpu_layers = 1 # The number of layers to put on the GPU. The rest will be on the CPU. If you don't know how many layers there are, you can use -1 to move all to GPU.\n",
"n_batch = 512 # Should be between 1 and n_ctx, consider the amount of RAM of your Apple Silicon Chip.\n",
"# Make sure the model path is correct for your system!\n",
"llm = LlamaCpp(\n",
@@ -559,7 +575,7 @@
"metadata": {},
"outputs": [],
"source": [
"n_gpu_layers = 1 # Metal set to 1 is enough.\n",
"n_gpu_layers = 1 # The number of layers to put on the GPU. The rest will be on the CPU. If you don't know how many layers there are, you can use -1 to move all to GPU.\n",
"n_batch = 512 # Should be between 1 and n_ctx, consider the amount of RAM of your Apple Silicon Chip.\n",
"# Make sure the model path is correct for your system!\n",
"llm = LlamaCpp(\n",

View File

@@ -69,11 +69,9 @@
"metadata": {},
"outputs": [
{
"name": "stderr",
"name": "stdout",
"output_type": "stream",
"text": [
"/home/noamgat/envs/langchain_experimental/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n",
"Downloading shards: 100%|██████████| 2/2 [00:00<00:00, 3.58it/s]\n",
"Loading checkpoint shards: 100%|██████████| 2/2 [05:32<00:00, 166.35s/it]\n",
"Downloading (…)okenizer_config.json: 100%|██████████| 1.62k/1.62k [00:00<00:00, 4.87MB/s]\n"

View File

@@ -26,19 +26,19 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ[\"OCTOAI_API_TOKEN\"] = \"OCTOAI_API_TOKEN\"\n",
"os.environ[\"ENDPOINT_URL\"] = \"https://mpt-7b-demo-f1kzsig6xes9.octoai.run/generate\""
"os.environ[\"ENDPOINT_URL\"] = \"https://text.octoai.run/v1/chat/completions\""
]
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@@ -56,7 +56,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
@@ -66,36 +66,40 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"llm = OctoAIEndpoint(\n",
" model_kwargs={\n",
" \"max_new_tokens\": 200,\n",
" \"temperature\": 0.75,\n",
" \"top_p\": 0.95,\n",
" \"repetition_penalty\": 1,\n",
" \"seed\": None,\n",
" \"stop\": [],\n",
" \"model\": \"llama-2-13b-chat-fp16\",\n",
" \"max_tokens\": 128,\n",
" \"presence_penalty\": 0,\n",
" \"temperature\": 0.1,\n",
" \"top_p\": 0.9,\n",
" \"messages\": [\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant. Keep your responses limited to one short paragraph if possible.\",\n",
" },\n",
" ],\n",
" },\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 31,
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'\\nLeonardo da Vinci was an Italian polymath and painter regarded by many as one of the greatest painters of all time. He is best known for his masterpieces including Mona Lisa, The Last Supper, and The Virgin of the Rocks. He was a draftsman, sculptor, architect, and one of the most important figures in the history of science. Da Vinci flew gliders, experimented with water turbines and windmills, and invented the catapult and a joystick-type human-powered aircraft control. He may have pioneered helicopters. As a scholar, he was interested in anatomy, geology, botany, engineering, mathematics, and astronomy.\\nOther painters and patrons claimed to be more talented, but Leonardo da Vinci was an incredibly productive artist, sculptor, engineer, anatomist, and scientist.'"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
"name": "stdout",
"output_type": "stream",
"text": [
" Sure thing! Here's my response:\n",
"\n",
"Leonardo da Vinci was a true Renaissance man - an Italian polymath who excelled in various fields, including painting, sculpture, engineering, mathematics, anatomy, and geology. He is widely considered one of the greatest painters of all time, and his inventive and innovative works continue to inspire and influence artists and thinkers to this day. Some of his most famous works include the Mona Lisa, The Last Supper, and Vitruvian Man. \n"
]
}
],
"source": [
@@ -103,7 +107,7 @@
"\n",
"llm_chain = LLMChain(prompt=prompt, llm=llm)\n",
"\n",
"llm_chain.run(question)"
"print(llm_chain.run(question))"
]
}
],
@@ -123,7 +127,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.11.7"
},
"vscode": {
"interpreter": {

View File

@@ -82,7 +82,7 @@
" temperature=0.8,\n",
")\n",
"\n",
"print(llm(\"What is the capital of France ?\"))"
"print(llm.invoke(\"What is the capital of France ?\"))"
]
},
{
@@ -117,8 +117,7 @@
"1. The first Pokemon game was released in 1996.\n",
"2. The president was Bill Clinton.\n",
"3. Clinton was president from 1993 to 2001.\n",
"4. The answer is Clinton.\n",
"\n"
"4. The answer is Clinton.\n"
]
},
{
@@ -142,7 +141,7 @@
"\n",
"question = \"Who was the US president in the year the first Pokemon game was released?\"\n",
"\n",
"print(llm_chain.run(question))"
"print(llm_chain.invoke(question))"
]
},
{
@@ -172,7 +171,36 @@
" trust_remote_code=True, # mandatory for hf models\n",
")\n",
"\n",
"llm(\"What is the future of AI?\")"
"llm.invoke(\"What is the future of AI?\")"
]
},
{
"cell_type": "markdown",
"id": "d6ca8fd911d25faa",
"metadata": {
"collapsed": false
},
"source": [
"## Quantization\n",
"\n",
"vLLM supports `awq` quantization. To enable it, pass `quantization` to `vllm_kwargs`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2cada3174c46a0ea",
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"llm_q = VLLM(\n",
" model=\"TheBloke/Llama-2-7b-Chat-AWQ\",\n",
" trust_remote_code=True,\n",
" max_new_tokens=512,\n",
" vllm_kwargs={\"quantization\": \"awq\"},\n",
")"
]
},
{
@@ -216,7 +244,7 @@
" model_name=\"tiiuae/falcon-7b\",\n",
" model_kwargs={\"stop\": [\".\"]},\n",
")\n",
"print(llm(\"Rome is\"))"
"print(llm.invoke(\"Rome is\"))"
]
}
],

View File

@@ -207,15 +207,11 @@ from langchain_community.vectorstores import MatchingEngine
> [Google BigQuery](https://cloud.google.com/bigquery),
> BigQuery is a serverless and cost-effective enterprise data warehouse in Google Cloud.
>
> Google BigQuery Vector Search
> [Google BigQuery Vector Search](https://cloud.google.com/bigquery/docs/vector-search-intro)
> BigQuery vector search lets you use GoogleSQL to do semantic search, using vector indexes for fast but approximate results, or using brute force for exact results.
> It can calculate Euclidean or Cosine distance. With LangChain, we default to use Euclidean distance.
> This is a private preview (experimental) feature. Please submit this
> [enrollment form](https://docs.google.com/forms/d/18yndSb4dTf2H0orqA9N7NAchQEDQekwWiD5jYfEkGWk/viewform?edit_requested=true)
> if you want to enroll BigQuery Vector Search Experimental.
We need to install several python packages.
```bash

View File

@@ -0,0 +1,22 @@
# Providers
LangChain integrates with many providers
## Partner Packages
- [OpenAI](/docs/integrations/platforms/openai)
- [Anthropic](/docs/integrations/platforms/anthropic)
- [Google](/docs/integrations/platforms/google)
- [MistralAI](/docs/integrations/providers/mistralai)
- [NVIDIA AI](/docs/integrations/providers/nvidia)
- [Together AI](/docs/integrations/providers/together)
- [Robocorp](/docs/integrations/providers/robocorp)
- [Exa Search](/docs/integrations/providers/exa_search)
- [Nomic](/docs/integrations/providers/nomic)
## Featured Community Providers
- [AWS](/docs/integrations/platforms/aws)
- [Hugging Face](/docs/integrations/platforms/huggingface)
- [Microsoft](/docs/integrations/platforms/microsoft)

View File

@@ -0,0 +1,16 @@
# Baichuan
>[Baichuan Inc.](https://www.baichuan-ai.com/) is a Chinese startup in the era of AGI, dedicated to addressing fundamental human needs: Efficiency, Health, and Happiness.
## Visit Us
Visit us at https://www.baichuan-ai.com/.
Register and get an API key if you are trying out our APIs.
## Baichuan LLM Endpoint
An example is available at [example](/docs/integrations/llms/baichuan)
## Baichuan Chat Model
An example is available at [example](/docs/integrations/chat/baichuan).
## Baichuan Text Embedding Model
An example is available at [example](/docs/integrations/text_embedding/baichuan)

View File

@@ -1,45 +1,52 @@
# DeepInfra
This page covers how to use the DeepInfra ecosystem within LangChain.
>[DeepInfra](https://deepinfra.com/docs) allows us to run the
> [latest machine learning models](https://deepinfra.com/models) with ease.
> DeepInfra takes care of all the heavy lifting related to running, scaling and monitoring
> the models. Users can focus on your application and integrate the models with simple REST API calls.
>DeepInfra provides [examples](https://deepinfra.com/docs/advanced/langchain) of integration with LangChain.
This page covers how to use the `DeepInfra` ecosystem within `LangChain`.
It is broken into two parts: installation and setup, and then references to specific DeepInfra wrappers.
## Installation and Setup
- Get your DeepInfra api key from this link [here](https://deepinfra.com/).
- Get an DeepInfra api key and set it as an environment variable (`DEEPINFRA_API_TOKEN`)
## Available Models
DeepInfra provides a range of Open Source LLMs ready for deployment.
You can list supported models for
You can see supported models for
[text-generation](https://deepinfra.com/models?type=text-generation) and
[embeddings](https://deepinfra.com/models?type=embeddings).
google/flan\* models can be viewed [here](https://deepinfra.com/models?type=text2text-generation).
You can view a [list of request and response parameters](https://deepinfra.com/meta-llama/Llama-2-70b-chat-hf/api).
Chat models [follow openai api](https://deepinfra.com/meta-llama/Llama-2-70b-chat-hf/api?example=openai-http)
## Wrappers
### LLM
## LLM
There exists an DeepInfra LLM wrapper, which you can access with
See a [usage example](/docs/integrations/llms/deepinfra).
```python
from langchain_community.llms import DeepInfra
```
### Embeddings
## Embeddings
There is also an DeepInfra Embeddings wrapper, you can access with
See a [usage example](/docs/integrations/text_embedding/deepinfra).
```python
from langchain_community.embeddings import DeepInfraEmbeddings
```
### Chat Models
## Chat Models
There is a chat-oriented wrapper as well, accessible with
See a [usage example](/docs/integrations/chat/deepinfra).
```python
from langchain_community.chat_models import ChatDeepInfra

View File

@@ -0,0 +1,77 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Exa Search\n",
"\n",
"Exa's search integration exists in its own [partner package](https://pypi.org/project/langchain-exa/). You can install it with:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-exa"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order to use the package, you will also need to set the `EXA_API_KEY` environment variable to your Exa API key.\n",
"\n",
"## Retriever\n",
"\n",
"You can use the [`ExaSearchRetriever`](/docs/integrations/tools/exa_search#using-exasearchretriever) in a standard retrieval pipeline. You can import it as follows"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "y8ku6X96sebl"
},
"outputs": [],
"source": [
"from langchain_exa import ExaSearchRetriever"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tools\n",
"\n",
"You can use Exa as an agent tool as described in the [Exa tool calling docs](/docs/integrations/tools/exa_search#using-the-exa-sdk-as-langchain-agent-tools).\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@@ -0,0 +1,78 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# MistralAI\n",
"\n",
"Mistral AI is a platform that offers hosting for their powerful open source models.\n",
"\n",
"You can access them via their [API](https://docs.mistral.ai/api/).\n",
"\n",
"A valid [API key](https://console.mistral.ai/users/api-keys/) is needed to communicate with the API.\n",
"\n",
"You will also need the `langchain-mistralai` package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-core langchain-mistralai"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "y8ku6X96sebl"
},
"outputs": [],
"source": [
"from langchain_mistralai import ChatMistralAI, MistralAIEmbeddings"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"See the docs for their\n",
"\n",
"- [Chat Model](/docs/integrations/chat/mistralai)\n",
"- [Embeddings Model](/docs/integrations/text_embedding/mistralai)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@@ -0,0 +1,69 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Nomic\n",
"\n",
"Nomic currently offers two products:\n",
"\n",
"- Atlas: their Visual Data Engine\n",
"- GPT4All: their Open Source Edge Language Model Ecosystem\n",
"\n",
"The Nomic integration exists in its own [partner package](https://pypi.org/project/langchain-nomic/). You can install it with:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-nomic"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Currently, you can import their hosted [embedding model](/docs/integrations/text_embedding/nomic) as follows:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "y8ku6X96sebl"
},
"outputs": [],
"source": [
"from langchain_nomic import NomicEmbeddings"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@@ -21,7 +21,7 @@ To use, you should set up the environment variables `ANYSCALE_API_BASE` and
## LLM
```python
from langchain.llms import Ollama
from langchain_community.llms import Ollama
```
See the notebook example [here](/docs/integrations/llms/ollama).
@@ -31,7 +31,7 @@ See the notebook example [here](/docs/integrations/llms/ollama).
### Chat Ollama
```python
from langchain.chat_models import ChatOllama
from langchain_community.chat_models import ChatOllama
```
See the notebook example [here](/docs/integrations/chat/ollama).
@@ -47,7 +47,7 @@ See the notebook example [here](/docs/integrations/chat/ollama_functions).
## Embedding models
```python
from langchain.embeddings import OllamaEmbeddings
from langchain_community.embeddings import OllamaEmbeddings
```
See the notebook example [here](/docs/integrations/text_embedding/ollama).

View File

@@ -0,0 +1,21 @@
# Ontotext GraphDB
>[Ontotext GraphDB](https://graphdb.ontotext.com/) is a graph database and knowledge discovery tool compliant with RDF and SPARQL.
## Dependencies
Install the [rdflib](https://github.com/RDFLib/rdflib) package with
```bash
pip install rdflib==7.0.0
```
## Graph QA Chain
Connect your GraphDB Database with a chat model to get insights on your data.
See the notebook example [here](/docs/use_cases/graph/graph_ontotext_graphdb_qa).
```python
from langchain_community.graphs import OntotextGraphDBGraph
from langchain.chains import OntotextGraphDBQAChain
```

View File

@@ -0,0 +1,78 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Together AI\n",
"\n",
"> The Together API makes it easy to fine-tune or run leading open-source models with a couple lines of code. We have integrated the worlds leading open-source models, including Llama-2, RedPajama, Falcon, Alpaca, Stable Diffusion XL, and more. Read more: https://together.ai\n",
"\n",
"To use, you'll need an API key which you can find here:\n",
"https://api.together.xyz/settings/api-keys. This can be passed in as init param\n",
"``together_api_key`` or set as environment variable ``TOGETHER_API_KEY``.\n",
"\n",
"Together API reference: https://docs.together.ai/reference/inference\n",
"\n",
"You will also need to install the `langchain-together` integration package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install --upgrade --quiet langchain-together"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "y8ku6X96sebl"
},
"outputs": [],
"source": [
"from __module_name__ import (\n",
" Together, # LLM\n",
" TogetherEmbeddings,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"See the docs for their\n",
"\n",
"- [LLM](/docs/integrations/llms/together)\n",
"- [Embeddings Model](/docs/integrations/text_embedding/together)"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@@ -1,186 +0,0 @@
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"---\n",
"sidebar_label: SQL\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SQLStore\n",
"\n",
"The `SQLStrStore` and `SQLDocStore` implement remote data access and persistence to store strings or LangChain documents in your SQL instance."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['value1', 'value2']\n",
"['key2']\n",
"['key2']\n"
]
}
],
"source": [
"from langchain_community.storage import SQLStrStore\n",
"\n",
"# simple example using an SQLStrStore to store strings\n",
"# same as you would use in \"InMemoryStore\" but using SQL persistence\n",
"CONNECTION_STRING = \"postgresql+psycopg2://user:pass@localhost:5432/db\"\n",
"COLLECTION_NAME = \"test_collection\"\n",
"\n",
"store = SQLStrStore(\n",
" collection_name=COLLECTION_NAME,\n",
" connection_string=CONNECTION_STRING,\n",
")\n",
"store.mset([(\"key1\", \"value1\"), (\"key2\", \"value2\")])\n",
"print(store.mget([\"key1\", \"key2\"]))\n",
"# ['value1', 'value2']\n",
"store.mdelete([\"key1\"])\n",
"print(list(store.yield_keys()))\n",
"# ['key2']\n",
"print(list(store.yield_keys(prefix=\"k\")))\n",
"# ['key2']\n",
"# delete the COLLECTION_NAME collection"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Integration with ParentRetriever and PGVector\n",
"\n",
"When using PGVector, you already have a SQL instance running. Here is a convenient way of using this instance to store documents associated to vectors. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Prepare the PGVector vectorestore with something like this:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.vectorstores import PGVector\n",
"from langchain_openai import OpenAIEmbeddings"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"embeddings = OpenAIEmbeddings()\n",
"vector_db = PGVector.from_existing_index(\n",
" embedding=embeddings,\n",
" collection_name=COLLECTION_NAME,\n",
" connection_string=CONNECTION_STRING,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then create the parent retiever using `SQLDocStore` to persist the documents"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.document_loaders import TextLoader\n",
"from langchain.retrievers import ParentDocumentRetriever\n",
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"from langchain_community.storage import SQLDocStore\n",
"\n",
"CONNECTION_STRING = \"postgresql+psycopg2://user:pass@localhost:5432/db\"\n",
"COLLECTION_NAME = \"state_of_the_union_test\"\n",
"docstore = SQLDocStore(\n",
" collection_name=COLLECTION_NAME,\n",
" connection_string=CONNECTION_STRING,\n",
")\n",
"\n",
"loader = TextLoader(\"./state_of_the_union.txt\")\n",
"documents = loader.load()\n",
"\n",
"parent_splitter = RecursiveCharacterTextSplitter(chunk_size=400)\n",
"child_splitter = RecursiveCharacterTextSplitter(chunk_size=50)\n",
"\n",
"retriever = ParentDocumentRetriever(\n",
" vectorstore=vector_db,\n",
" docstore=docstore,\n",
" child_splitter=child_splitter,\n",
" parent_splitter=parent_splitter,\n",
")\n",
"retriever.add_documents(documents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Delete a collection"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.storage import SQLStrStore\n",
"\n",
"# delete the COLLECTION_NAME collection\n",
"CONNECTION_STRING = \"postgresql+psycopg2://user:pass@localhost:5432/db\"\n",
"COLLECTION_NAME = \"test_collection\"\n",
"store = SQLStrStore(\n",
" collection_name=COLLECTION_NAME,\n",
" connection_string=CONNECTION_STRING,\n",
")\n",
"store.delete_collection()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,102 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Baichuan Text Embeddings\n",
"\n",
"As of today (Jan 25th, 2024) BaichuanTextEmbeddings ranks #1 in C-MTEB (Chinese Multi-Task Embedding Benchmark) leaderboard.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Leaderboard (Under Overall -> Chinese section): https://huggingface.co/spaces/mteb/leaderboard"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Official Website: https://platform.baichuan-ai.com/docs/text-Embedding\n",
"\n",
"An API key is required to use this embedding model. You can get one by registering at https://platform.baichuan-ai.com/docs/text-Embedding."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"BaichuanTextEmbeddings support 512 token window and preduces vectors with 1024 dimensions. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Please NOTE that BaichuanTextEmbeddings only supports Chinese text embedding. Multi-language support is coming soon."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.embeddings import BaichuanTextEmbeddings\n",
"\n",
"embeddings = BaichuanTextEmbeddings(baichuan_api_key=\"sk-*\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Alternatively, you can set API key this way:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ[\"BAICHUAN_API_KEY\"] = \"YOUR_API_KEY\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"text_1 = \"今天天气不错\"\n",
"text_2 = \"今天阳光很好\"\n",
"\n",
"query_result = embeddings.embed_query(text_1)\n",
"query_result"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"doc_result = embeddings.embed_documents([text_1, text_2])\n",
"doc_result"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,132 @@
{
"cells": [
{
"cell_type": "raw",
"id": "afaf8039",
"metadata": {},
"source": [
"---\n",
"sidebar_label: Nomic\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "e49f1e0d",
"metadata": {},
"source": [
"# NomicEmbeddings\n",
"\n",
"This notebook covers how to get started with Nomic embedding models.\n",
"\n",
"## Installation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4c3bef91",
"metadata": {},
"outputs": [],
"source": [
"# install package\n",
"!pip install -U langchain-nomic"
]
},
{
"cell_type": "markdown",
"id": "2b4f3e15",
"metadata": {},
"source": [
"## Environment Setup\n",
"\n",
"Make sure to set the following environment variables:\n",
"\n",
"- `NOMIC_API_KEY`\n",
"\n",
"## Usage"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "62e0dbc3",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain_nomic.embeddings import NomicEmbeddings\n",
"\n",
"embeddings = NomicEmbeddings(model=\"nomic-embed-text-v1\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "12fcfb4b",
"metadata": {},
"outputs": [],
"source": [
"embeddings.embed_query(\"My query to look up\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1f2e6104",
"metadata": {},
"outputs": [],
"source": [
"embeddings.embed_documents(\n",
" [\"This is a content of the document\", \"This is another document\"]\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46739f68",
"metadata": {},
"outputs": [],
"source": [
"# async embed query\n",
"await embeddings.aembed_query(\"My query to look up\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e48632ea",
"metadata": {},
"outputs": [],
"source": [
"# async embed documents\n",
"await embeddings.aembed_documents(\n",
" [\"This is a content of the document\", \"This is another document\"]\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -52,7 +52,7 @@
"metadata": {},
"outputs": [],
"source": [
"embedder = SpacyEmbeddings()"
"embedder = SpacyEmbeddings(model_name=\"en_core_web_sm\")"
]
},
{

View File

@@ -0,0 +1,136 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Connery Toolkit\n",
"\n",
"Using this toolkit, you can integrate Connery Actions into your LangChain agent.\n",
"\n",
"If you want to use only one particular Connery Action in your agent,\n",
"check out the [Connery Action Tool](/docs/integrations/tools/connery) documentation.\n",
"\n",
"## What is Connery?\n",
"\n",
"Connery is an open-source plugin infrastructure for AI.\n",
"\n",
"With Connery, you can easily create a custom plugin with a set of actions and seamlessly integrate them into your LangChain agent.\n",
"Connery will take care of critical aspects such as runtime, authorization, secret management, access management, audit logs, and other vital features.\n",
"\n",
"Furthermore, Connery, supported by our community, provides a diverse collection of ready-to-use open-source plugins for added convenience.\n",
"\n",
"Learn more about Connery:\n",
"\n",
"- GitHub: https://github.com/connery-io/connery\n",
"- Documentation: https://docs.connery.io\n",
"\n",
"## Prerequisites\n",
"\n",
"To use Connery Actions in your LangChain agent, you need to do some preparation:\n",
"\n",
"1. Set up the Connery runner using the [Quickstart](https://docs.connery.io/docs/runner/quick-start/) guide.\n",
"2. Install all the plugins with the actions you want to use in your agent.\n",
"3. Set environment variables `CONNERY_RUNNER_URL` and `CONNERY_RUNNER_API_KEY` so the toolkit can communicate with the Connery Runner.\n",
"\n",
"## Example of using Connery Toolkit\n",
"\n",
"In the example below, we create an agent that uses two Connery Actions to summarize a public webpage and send the summary by email:\n",
"\n",
"1. **Summarize public webpage** action from the [Summarization](https://github.com/connery-io/summarization-plugin) plugin.\n",
"2. **Send email** action from the [Gmail](https://github.com/connery-io/gmail) plugin.\n",
"\n",
"You can see a LangSmith trace of this example [here](https://smith.langchain.com/public/4af5385a-afe9-46f6-8a53-57fe2d63c5bc/r)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"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: `CA72DFB0AB4DF6C830B43E14B0782F70` with `{'publicWebpageUrl': 'http://www.paulgraham.com/vb.html'}`\n",
"\n",
"\n",
"\u001b[0m\u001b[33;1m\u001b[1;3m{'summary': 'The author reflects on the concept of life being short and how having children made them realize the true brevity of life. They discuss how time can be converted into discrete quantities and how limited certain experiences are. The author emphasizes the importance of prioritizing and eliminating unnecessary things in life, as well as actively pursuing meaningful experiences. They also discuss the negative impact of getting caught up in online arguments and the need to be aware of how time is being spent. The author suggests pruning unnecessary activities, not waiting to do things that matter, and savoring the time one has.'}\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `CABC80BB79C15067CA983495324AE709` with `{'recipient': 'test@example.com', 'subject': 'Summary of the webpage', 'body': 'Here is a short summary of the webpage http://www.paulgraham.com/vb.html:\\n\\nThe author reflects on the concept of life being short and how having children made them realize the true brevity of life. They discuss how time can be converted into discrete quantities and how limited certain experiences are. The author emphasizes the importance of prioritizing and eliminating unnecessary things in life, as well as actively pursuing meaningful experiences. They also discuss the negative impact of getting caught up in online arguments and the need to be aware of how time is being spent. The author suggests pruning unnecessary activities, not waiting to do things that matter, and savoring the time one has.\\n\\nYou can find the full webpage [here](http://www.paulgraham.com/vb.html).'}`\n",
"\n",
"\n",
"\u001b[0m\u001b[33;1m\u001b[1;3m{'messageId': '<2f04b00e-122d-c7de-c91e-e78e0c3276d6@gmail.com>'}\u001b[0m\u001b[32;1m\u001b[1;3mI have sent the email with the summary of the webpage to test@example.com. Please check your inbox.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n",
"I have sent the email with the summary of the webpage to test@example.com. Please check your inbox.\n"
]
}
],
"source": [
"import os\n",
"\n",
"from langchain.agents import AgentType, initialize_agent\n",
"from langchain.chat_models import ChatOpenAI\n",
"from langchain_community.agent_toolkits.connery import ConneryToolkit\n",
"from langchain_community.tools.connery import ConneryService\n",
"\n",
"# Specify your Connery Runner credentials.\n",
"os.environ[\"CONNERY_RUNNER_URL\"] = \"\"\n",
"os.environ[\"CONNERY_RUNNER_API_KEY\"] = \"\"\n",
"\n",
"# Specify OpenAI API key.\n",
"os.environ[\"OPENAI_API_KEY\"] = \"\"\n",
"\n",
"# Specify your email address to receive the email with the summary from example below.\n",
"recepient_email = \"test@example.com\"\n",
"\n",
"# Create a Connery Toolkit with all the available actions from the Connery Runner.\n",
"connery_service = ConneryService()\n",
"connery_toolkit = ConneryToolkit.create_instance(connery_service)\n",
"\n",
"# Use OpenAI Functions agent to execute the prompt using actions from the Connery Toolkit.\n",
"llm = ChatOpenAI(temperature=0)\n",
"agent = initialize_agent(\n",
" connery_toolkit.get_tools(), llm, AgentType.OPENAI_FUNCTIONS, verbose=True\n",
")\n",
"result = agent.run(\n",
" f\"\"\"Make a short summary of the webpage http://www.paulgraham.com/vb.html in three sentences\n",
"and send it to {recepient_email}. Include the link to the webpage into the body of the email.\"\"\"\n",
")\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"NOTE: Connery Action is a structured tool, so you can only use it in the agents supporting structured tools."
]
}
],
"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.10.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -13,30 +13,65 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {},
"outputs": [],
"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;49m23.3.2\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;49mpip install --upgrade pip\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n",
"\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;49m23.3.2\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;49mpip install --upgrade pip\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n",
"\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;49m23.3.2\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;49mpip install --upgrade pip\u001b[0m\n",
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip install --upgrade --quiet slack_sdk > /dev/null\n",
"%pip install --upgrade --quiet beautifulsoup4 > /dev/null # This is optional but is useful for parsing HTML messages"
"%pip install --upgrade --quiet beautifulsoup4 > /dev/null # This is optional but is useful for parsing HTML messages\n",
"%pip install --upgrade --quiet python-dotenv > /dev/null # This is for loading environmental variables from a .env file"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Assign Environmental Variables\n",
"## Set Environmental Variables\n",
"\n",
"The toolkit will read the SLACK_USER_TOKEN environmental variable to authenticate the user so you need to set them here. You will also need to set your OPENAI_API_KEY to use the agent later."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Set environmental variables here"
"# Set environmental variables here\n",
"# In this example, you set environmental variables by loading a .env file.\n",
"import dotenv\n",
"\n",
"dotenv.load_dotenv()"
]
},
{
@@ -50,9 +85,23 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"[SlackGetChannel(client=<slack_sdk.web.client.WebClient object at 0x11eba6a00>),\n",
" SlackGetMessage(client=<slack_sdk.web.client.WebClient object at 0x11eba69d0>),\n",
" SlackScheduleMessage(client=<slack_sdk.web.client.WebClient object at 0x11eba65b0>),\n",
" SlackSendMessage(client=<slack_sdk.web.client.WebClient object at 0x11eba6790>)]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_community.agent_toolkits import SlackToolkit\n",
"\n",
@@ -65,31 +114,122 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Use within an Agent"
"## Use within an ReAct Agent"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"from langchain.agents import AgentType, initialize_agent\n",
"from langchain_openai import OpenAI"
"from langchain import hub\n",
"from langchain.agents import AgentExecutor, create_react_agent\n",
"from langchain_openai import ChatOpenAI"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"llm = OpenAI(temperature=0)\n",
"agent = initialize_agent(\n",
"llm = ChatOpenAI(temperature=0, model=\"gpt-4\")\n",
"prompt = hub.pull(\"hwchase17/react\")\n",
"agent = create_react_agent(\n",
" tools=toolkit.get_tools(),\n",
" llm=llm,\n",
" verbose=False,\n",
" agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,\n",
" prompt=prompt,\n",
")\n",
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"agent_executor.invoke(\n",
" {\"input\": \"Send a greeting to my coworkers in the #general channel.\"}\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3mI need to get the list of channels in the workspace.\n",
"Action: get_channelid_name_dict\n",
"Action Input: {}\u001b[0m\u001b[36;1m\u001b[1;3m[{\"id\": \"C052SCUP4UD\", \"name\": \"general\", \"created\": 1681297313, \"num_members\": 1}, {\"id\": \"C052VBBU4M8\", \"name\": \"test-bots\", \"created\": 1681297343, \"num_members\": 2}, {\"id\": \"C053805TNUR\", \"name\": \"random\", \"created\": 1681297313, \"num_members\": 2}]\u001b[0m\u001b[32;1m\u001b[1;3mI now have the list of channels and their names.\n",
"Final Answer: There are 3 channels in the workspace. Their names are \"general\", \"test-bots\", and \"random\".\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': 'How many channels are in the workspace? Please list out their names.',\n",
" 'output': 'There are 3 channels in the workspace. Their names are \"general\", \"test-bots\", and \"random\".'}"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agent_executor.invoke(\n",
" {\"input\": \"How many channels are in the workspace? Please list out their names.\"}\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3mFirst, I need to identify the channel ID for the #introductions channel.\n",
"Action: get_channelid_name_dict\n",
"Action Input: None\u001b[0m\u001b[36;1m\u001b[1;3m[{\"id\": \"C052SCUP4UD\", \"name\": \"general\", \"created\": 1681297313, \"num_members\": 1}, {\"id\": \"C052VBBU4M8\", \"name\": \"test-bots\", \"created\": 1681297343, \"num_members\": 2}, {\"id\": \"C053805TNUR\", \"name\": \"random\", \"created\": 1681297313, \"num_members\": 2}]\u001b[0m\u001b[32;1m\u001b[1;3mThe #introductions channel is not listed in the observed channels. I need to inform the user that the #introductions channel does not exist or is not accessible.\n",
"Final Answer: The #introductions channel does not exist or is not accessible.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': 'Tell me the number of messages sent in the #introductions channel from the past month.',\n",
" 'output': 'The #introductions channel does not exist or is not accessible.'}"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agent_executor.invoke(\n",
" {\n",
" \"input\": \"Tell me the number of messages sent in the #introductions channel from the past month.\"\n",
" }\n",
")"
]
},
@@ -98,29 +238,7 @@
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"agent.run(\"Send a greeting to my coworkers in the #general channel.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"agent.run(\"How many channels are in the workspace? Please list out their names.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"agent.run(\n",
" \"Tell me the number of messages sent in the #introductions channel from the past month.\"\n",
")"
]
"source": []
}
],
"metadata": {
@@ -139,7 +257,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.9.6"
}
},
"nbformat": 4,

View File

@@ -0,0 +1,165 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Connery Action Tool\n",
"\n",
"Using this tool, you can integrate individual Connery Action into your LangChain agent.\n",
"\n",
"If you want to use more than one Connery Action in your agent,\n",
"check out the [Connery Toolkit](/docs/integrations/toolkits/connery) documentation.\n",
"\n",
"## What is Connery?\n",
"\n",
"Connery is an open-source plugin infrastructure for AI.\n",
"\n",
"With Connery, you can easily create a custom plugin with a set of actions and seamlessly integrate them into your LangChain agent.\n",
"Connery will take care of critical aspects such as runtime, authorization, secret management, access management, audit logs, and other vital features.\n",
"\n",
"Furthermore, Connery, supported by our community, provides a diverse collection of ready-to-use open-source plugins for added convenience.\n",
"\n",
"Learn more about Connery:\n",
"\n",
"- GitHub: https://github.com/connery-io/connery\n",
"- Documentation: https://docs.connery.io\n",
"\n",
"## Prerequisites\n",
"\n",
"To use Connery Actions in your LangChain agent, you need to do some preparation:\n",
"\n",
"1. Set up the Connery runner using the [Quickstart](https://docs.connery.io/docs/runner/quick-start/) guide.\n",
"2. Install all the plugins with the actions you want to use in your agent.\n",
"3. Set environment variables `CONNERY_RUNNER_URL` and `CONNERY_RUNNER_API_KEY` so the toolkit can communicate with the Connery Runner.\n",
"\n",
"## Example of using Connery Action Tool\n",
"\n",
"In the example below, we fetch action by its ID from the Connery Runner and then call it with the specified parameters.\n",
"\n",
"Here, we use the ID of the **Send email** action from the [Gmail](https://github.com/connery-io/gmail) plugin."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"from langchain.agents import AgentType, initialize_agent\n",
"from langchain.chat_models import ChatOpenAI\n",
"from langchain_community.tools.connery import ConneryService\n",
"\n",
"# Specify your Connery Runner credentials.\n",
"os.environ[\"CONNERY_RUNNER_URL\"] = \"\"\n",
"os.environ[\"CONNERY_RUNNER_API_KEY\"] = \"\"\n",
"\n",
"# Specify OpenAI API key.\n",
"os.environ[\"OPENAI_API_KEY\"] = \"\"\n",
"\n",
"# Specify your email address to receive the emails from examples below.\n",
"recepient_email = \"test@example.com\"\n",
"\n",
"# Get the SendEmail action from the Connery Runner by ID.\n",
"connery_service = ConneryService()\n",
"send_email_action = connery_service.get_action(\"CABC80BB79C15067CA983495324AE709\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Run the action manually."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"manual_run_result = send_email_action.run(\n",
" {\n",
" \"recipient\": recepient_email,\n",
" \"subject\": \"Test email\",\n",
" \"body\": \"This is a test email sent from Connery.\",\n",
" }\n",
")\n",
"print(manual_run_result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Run the action using the OpenAI Functions agent.\n",
"\n",
"You can see a LangSmith trace of this example [here](https://smith.langchain.com/public/a37d216f-c121-46da-a428-0e09dc19b1dc/r)."
]
},
{
"cell_type": "code",
"execution_count": 15,
"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: `CABC80BB79C15067CA983495324AE709` with `{'recipient': 'test@example.com', 'subject': 'Late for Meeting', 'body': 'Dear Team,\\n\\nI wanted to inform you that I will be late for the meeting today. I apologize for any inconvenience caused. Please proceed with the meeting without me and I will join as soon as I can.\\n\\nBest regards,\\n[Your Name]'}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m{'messageId': '<d34a694d-50e0-3988-25da-e86b4c51d7a7@gmail.com>'}\u001b[0m\u001b[32;1m\u001b[1;3mI have sent an email to test@example.com informing them that you will be late for the meeting.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n",
"I have sent an email to test@example.com informing them that you will be late for the meeting.\n"
]
}
],
"source": [
"llm = ChatOpenAI(temperature=0)\n",
"agent = initialize_agent(\n",
" [send_email_action], llm, AgentType.OPENAI_FUNCTIONS, verbose=True\n",
")\n",
"agent_run_result = agent.run(\n",
" f\"Send an email to the {recepient_email} and say that I will be late for the meeting.\"\n",
")\n",
"print(agent_run_result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"NOTE: Connery Action is a structured tool, so you can only use it in the agents supporting structured tools."
]
}
],
"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.10.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -60,7 +60,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Using ExaSearchRetriever\n",
"## Using ExaSearchRetriever\n",
"\n",
"ExaSearchRetriever is a retriever that uses Exa Search to retrieve relevant documents."
]
@@ -345,7 +345,7 @@
" Set the optional include_domains (list[str]) parameter to restrict the search to a list of domains.\n",
" Set the optional start_published_date (str) parameter to restrict the search to documents published after the date (YYYY-MM-DD).\n",
" \"\"\"\n",
" return exa.search(\n",
" return exa.search_and_contents(\n",
" f\"{query}\",\n",
" use_autoprompt=True,\n",
" num_results=5,\n",
@@ -359,7 +359,7 @@
" \"\"\"Search for webpages similar to a given URL.\n",
" The url passed in should be a URL returned from `search`.\n",
" \"\"\"\n",
" return exa.find_similar(url, num_results=5)\n",
" return exa.find_similar_and_contents(url, num_results=5)\n",
"\n",
"\n",
"@tool\n",

View File

@@ -0,0 +1,181 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "b3G2HfJwwAwc"
},
"source": [
"# Ionic Shopping Tool\n",
"\n",
"[Ionic](https://www.ioniccommerce.com/) is a plug and play ecommerce marketplace for AI Assistants. By including the [Ionic Tool](https://github.com/ioniccommerce/ionic_langchain) in your agent, you are effortlessly providing your users with the ability to shop and transact directly within your agent, and you'll get a cut of the transaction.\n",
"\n",
"\n",
"This is a basic jupyter notebook demonstrating how to integrate the Ionic Tool into your agent. For more information on setting up your Agent with Ionic, see the Ionic [documentation](https://docs.ioniccommerce.com/introduction).\n",
"\n",
"This Jupyter Notebook demonstrates how to use the Ionic tool with an Agent.\n",
"\n",
"**Note: The ionic-langchain package is maintained by the Ionic Commerce team, not the LangChain maintainers.**\n",
"\n",
"\n",
"\n",
"---\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EIO5SfIb5FiB"
},
"source": [
"## Setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "wsPt35XcSuWM"
},
"outputs": [],
"source": [
"pip install langchain langchain_openai langchainhub"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "OME5aldfS5FJ"
},
"outputs": [],
"source": [
"pip install ionic-langchain"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "g1UbcClL5IJR"
},
"source": [
"## Setup Agent"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "5vOjSwyQLguq",
"outputId": "e5cda856-1298-4b51-aa93-6e9f22be7279"
},
"outputs": [],
"source": [
"from ionic_langchain.tool import Ionic, IonicTool\n",
"from langchain import hub\n",
"from langchain.agents import AgentExecutor, Tool, create_react_agent\n",
"from langchain_openai import OpenAI\n",
"\n",
"# Based on ReAct Agent\n",
"# https://python.langchain.com/docs/modules/agents/agent_types/react\n",
"# Please reach out to support@ionicapi.com for help with add'l agent types.\n",
"\n",
"open_ai_key = \"YOUR KEY HERE\"\n",
"model = \"gpt-3.5-turbo-instruct\"\n",
"temperature = 0.6\n",
"\n",
"llm = OpenAI(openai_api_key=open_ai_key, model_name=model, temperature=temperature)\n",
"\n",
"\n",
"ionic_tool = IonicTool().tool()\n",
"\n",
"\n",
"# The tool comes with its own prompt,\n",
"# but you may also update it directly via the description attribute:\n",
"\n",
"ionic_tool.description = str(\n",
" \"\"\"\n",
"Ionic is an e-commerce shopping tool. Assistant uses the Ionic Commerce Shopping Tool to find, discover, and compare products from thousands of online retailers. Assistant should use the tool when the user is looking for a product recommendation or trying to find a specific product.\n",
"\n",
"The user may specify the number of results, minimum price, and maximum price for which they want to see results.\n",
"Ionic Tool input is a comma-separated string of values:\n",
" - query string (required, must not include commas)\n",
" - number of results (default to 4, no more than 10)\n",
" - minimum price in cents ($5 becomes 500)\n",
" - maximum price in cents\n",
"For example, if looking for coffee beans between 5 and 10 dollars, the tool input would be `coffee beans, 5, 500, 1000`.\n",
"\n",
"Return them as a markdown formatted list with each recommendation from tool results, being sure to include the full PDP URL. For example:\n",
"\n",
"1. Product 1: [Price] -- link\n",
"2. Product 2: [Price] -- link\n",
"3. Product 3: [Price] -- link\n",
"4. Product 4: [Price] -- link\n",
"\"\"\"\n",
")\n",
"\n",
"tools = [ionic_tool]\n",
"\n",
"# default prompt for create_react_agent\n",
"prompt = hub.pull(\"hwchase17/react\")\n",
"\n",
"agent = create_react_agent(\n",
" llm,\n",
" tools,\n",
" prompt=prompt,\n",
")\n",
"\n",
"agent_executor = AgentExecutor(\n",
" agent=agent, tools=tools, handle_parsing_errors=True, verbose=True, max_iterations=5\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Eb78bHgb5O6u"
},
"source": [
"## Run"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 197
},
"id": "FxELjaR9URF-",
"outputId": "f4bf30ec-64b8-4970-dea1-f0720c60681e"
},
"outputs": [],
"source": [
"input = (\n",
" \"I'm looking for a new 4k monitor can you find me some options for less than $1000\"\n",
")\n",
"agent_executor.invoke({\"input\": input})"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@@ -19,7 +19,7 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain.tools import PubmedQueryRun"
"from langchain_community.tools.pubmed.tool import PubmedQueryRun"
]
},
{

View File

@@ -0,0 +1,73 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c4b39799",
"metadata": {},
"source": [
"# Wikidata\n",
"\n",
">[Wikidata](https://wikidata.org/) is a free and open knowledge base that can be read and edited by both humans and machines. Wikidata is one of the world's largest open knowledge bases.\n",
"\n",
"First, you need to install `wikibase-rest-api-client` and `mediawikiapi` python packages."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3d9195d4",
"metadata": {
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [],
"source": [
"%pip install --upgrade --quiet wikibase-rest-api-client mediawikiapi"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "955988a1-ebc2-4c9a-9298-c493fe842de1",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.tools.wikidata.tool import WikidataAPIWrapper, WikidataQueryRun\n",
"\n",
"wikidata = WikidataQueryRun(api_wrapper=WikidataAPIWrapper())"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "9926a8a7-3e4e-4a97-ba43-7e5a274b9561",
"metadata": {},
"outputs": [],
"source": [
"print(wikidata.run(\"Alan Turing\"))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -7,22 +7,12 @@
},
"source": [
"# BigQuery Vector Search\n",
"> **BigQueryVectorSearch**:\n",
"BigQuery vector search lets you use GoogleSQL to do semantic search, using vector indexes for fast approximate results, or using brute force for exact results.\n",
"> [**BigQuery Vector Search**](https://cloud.google.com/bigquery/docs/vector-search-intro) lets you use GoogleSQL to do semantic search, using vector indexes for fast approximate results, or using brute force for exact results.\n",
"\n",
"\n",
"This tutorial illustrates how to work with an end-to-end data and embedding management system in LangChain, and provide scalable semantic search in BigQuery."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a **private preview (experimental)** feature. Please submit this\n",
"[enrollment form](https://docs.google.com/forms/d/18yndSb4dTf2H0orqA9N7NAchQEDQekwWiD5jYfEkGWk/viewform?edit_requested=true)\n",
"if you want to enroll BigQuery Vector Search Experimental."
]
},
{
"cell_type": "markdown",
"metadata": {

View File

@@ -49,14 +49,6 @@
"id": "ae9fcf3e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/jeff/.pyenv/versions/3.10.10/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
},
{
"name": "stdout",
"output_type": "stream",

View File

@@ -416,7 +416,7 @@
"metadata": {},
"source": [
"## Similarity Search with filtering\n",
"FAISS vectorstore can also support filtering, since the FAISS does not natively support filtering we have to do it manually. This is done by first fetching more results than `k` and then filtering them. You can filter the documents based on metadata. You can also set the `fetch_k` parameter when calling any search method to set how many documents you want to fetch before filtering. Here is a small example:"
"FAISS vectorstore can also support filtering, since the FAISS does not natively support filtering we have to do it manually. This is done by first fetching more results than `k` and then filtering them. This filter is either a callble that takes as input a metadata dict and returns a bool, or a metadata dict where each missing key is ignored and each present k must be in a list of values. You can also set the `fetch_k` parameter when calling any search method to set how many documents you want to fetch before filtering. Here is a small example:"
]
},
{
@@ -480,6 +480,8 @@
],
"source": [
"results_with_scores = db.similarity_search_with_score(\"foo\", filter=dict(page=1))\n",
"# Or with a callable:\n",
"# results_with_scores = db.similarity_search_with_score(\"foo\", filter=lambda d: d[\"page\"] == 1)\n",
"for doc, score in results_with_scores:\n",
" print(f\"Content: {doc.page_content}, Metadata: {doc.metadata}, Score: {score}\")"
]

View File

@@ -167,9 +167,9 @@
],
"source": [
"%%time\n",
"URL = 'https://www.conseil-constitutionnel.fr/node/3850/pdf'\n",
"PDF = 'Déclaration_des_droits_de_l_homme_et_du_citoyen.pdf'\n",
"open(PDF, 'wb').write(requests.get(URL).content)"
"URL = \"https://www.conseil-constitutionnel.fr/node/3850/pdf\"\n",
"PDF = \"Déclaration_des_droits_de_l_homme_et_du_citoyen.pdf\"\n",
"open(PDF, \"wb\").write(requests.get(URL).content)"
]
},
{
@@ -208,7 +208,7 @@
],
"source": [
"%%time\n",
"print('Read a PDF...')\n",
"print(\"Read a PDF...\")\n",
"loader = PyPDFLoader(PDF)\n",
"pages = loader.load_and_split()\n",
"len(pages)"
@@ -252,12 +252,14 @@
],
"source": [
"%%time\n",
"print('Create a Vector Database from PDF text...')\n",
"embeddings = OpenAIEmbeddings(model='text-embedding-ada-002')\n",
"print(\"Create a Vector Database from PDF text...\")\n",
"embeddings = OpenAIEmbeddings(model=\"text-embedding-ada-002\")\n",
"texts = [p.page_content for p in pages]\n",
"metadata = pd.DataFrame(index=list(range(len(texts))))\n",
"metadata['tag'] = 'law'\n",
"metadata['title'] = 'Déclaration des Droits de l\\'Homme et du Citoyen de 1789'.encode('utf-8')\n",
"metadata[\"tag\"] = \"law\"\n",
"metadata[\"title\"] = \"Déclaration des Droits de l'Homme et du Citoyen de 1789\".encode(\n",
" \"utf-8\"\n",
")\n",
"vectordb = KDBAI(table, embeddings)\n",
"vectordb.add_texts(texts=texts, metadatas=metadata)"
]
@@ -288,11 +290,13 @@
],
"source": [
"%%time\n",
"print('Create LangChain Pipeline...')\n",
"qabot = RetrievalQA.from_chain_type(chain_type='stuff',\n",
" llm=ChatOpenAI(model='gpt-3.5-turbo-16k', temperature=TEMP), \n",
" retriever=vectordb.as_retriever(search_kwargs=dict(k=K)),\n",
" return_source_documents=True)"
"print(\"Create LangChain Pipeline...\")\n",
"qabot = RetrievalQA.from_chain_type(\n",
" chain_type=\"stuff\",\n",
" llm=ChatOpenAI(model=\"gpt-3.5-turbo-16k\", temperature=TEMP),\n",
" retriever=vectordb.as_retriever(search_kwargs=dict(k=K)),\n",
" return_source_documents=True,\n",
")"
]
},
{
@@ -325,9 +329,9 @@
],
"source": [
"%%time\n",
"Q = 'Summarize the document in English:'\n",
"print(f'\\n\\n{Q}\\n')\n",
"print(qabot.invoke(dict(query=Q))['result'])"
"Q = \"Summarize the document in English:\"\n",
"print(f\"\\n\\n{Q}\\n\")\n",
"print(qabot.invoke(dict(query=Q))[\"result\"])"
]
},
{
@@ -362,9 +366,9 @@
],
"source": [
"%%time\n",
"Q = 'Is it a fair law and why ?'\n",
"print(f'\\n\\n{Q}\\n')\n",
"print(qabot.invoke(dict(query=Q))['result'])"
"Q = \"Is it a fair law and why ?\"\n",
"print(f\"\\n\\n{Q}\\n\")\n",
"print(qabot.invoke(dict(query=Q))[\"result\"])"
]
},
{
@@ -414,9 +418,9 @@
],
"source": [
"%%time\n",
"Q = 'What are the rights and duties of the man, the citizen and the society ?'\n",
"print(f'\\n\\n{Q}\\n')\n",
"print(qabot.invoke(dict(query=Q))['result'])"
"Q = \"What are the rights and duties of the man, the citizen and the society ?\"\n",
"print(f\"\\n\\n{Q}\\n\")\n",
"print(qabot.invoke(dict(query=Q))[\"result\"])"
]
},
{
@@ -441,9 +445,9 @@
],
"source": [
"%%time\n",
"Q = 'Is this law practical ?'\n",
"print(f'\\n\\n{Q}\\n')\n",
"print(qabot.invoke(dict(query=Q))['result'])"
"Q = \"Is this law practical ?\"\n",
"print(f\"\\n\\n{Q}\\n\")\n",
"print(qabot.invoke(dict(query=Q))[\"result\"])"
]
},
{

View File

@@ -13,7 +13,16 @@
"This notebook shows how to use functionality related to the `Pinecone` vector database.\n",
"\n",
"To use Pinecone, you must have an API key. \n",
"Here are the [installation instructions](https://docs.pinecone.io/docs/quickstart)."
"Here are the [installation instructions](https://docs.pinecone.io/docs/quickstart).\n",
"\n",
"Set the following environment variables to make using the `Pinecone` integration easier:\n",
"\n",
"- `PINECONE_API_KEY`: Your Pinecone API key.\n",
"- `PINECONE_INDEX_NAME`: The name of the index you want to use.\n",
"\n",
"And to follow along in this doc, you should also set\n",
"\n",
"- `OPENAI_API_KEY`: Your OpenAI API key, for using `OpenAIEmbeddings`"
]
},
{
@@ -25,74 +34,27 @@
},
"outputs": [],
"source": [
"%pip install --upgrade --quiet pinecone-client langchain-openai tiktoken langchain"
"%pip install --upgrade --quiet langchain-pinecone langchain-openai langchain"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c1e38361-c1fe-4ac6-86e9-c90ebaf7ae87",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"os.environ[\"PINECONE_API_KEY\"] = getpass.getpass(\"Pinecone API Key:\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "02a536e0-d603-4d79-b18b-1ed562977b40",
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"PINECONE_ENV\"] = getpass.getpass(\"Pinecone Environment:\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "320af802-9271-46ee-948f-d2453933d44b",
"id": "42f2ea67",
"metadata": {},
"source": [
"We want to use `OpenAIEmbeddings` so we have to get the OpenAI API Key."
"First, let's split our state of the union document into chunked `docs`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ffea66e4-bc23-46a9-9580-b348dfe7b7a7",
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"OpenAI API Key:\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aac9563e",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.text_splitter import CharacterTextSplitter\n",
"from langchain_community.document_loaders import TextLoader\n",
"from langchain_community.vectorstores import Pinecone\n",
"from langchain_openai import OpenAIEmbeddings"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"id": "a3c3999a",
"metadata": {},
"outputs": [],
"source": [
"from langchain.text_splitter import CharacterTextSplitter\n",
"from langchain_community.document_loaders import TextLoader\n",
"from langchain_openai import OpenAIEmbeddings\n",
"\n",
"loader = TextLoader(\"../../modules/state_of_the_union.txt\")\n",
"documents = loader.load()\n",
@@ -103,43 +65,52 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6e104aee",
"cell_type": "markdown",
"id": "3a4d377f",
"metadata": {},
"outputs": [],
"source": [
"import pinecone\n",
"Now let's assume you have your Pinecone index set up with `dimension=1536`.\n",
"\n",
"# initialize pinecone\n",
"pinecone.init(\n",
" api_key=os.getenv(\"PINECONE_API_KEY\"), # find at app.pinecone.io\n",
" environment=os.getenv(\"PINECONE_ENV\"), # next to api key in console\n",
")\n",
"\n",
"index_name = \"langchain-demo\"\n",
"\n",
"# First, check if our index already exists. If it doesn't, we create it\n",
"if index_name not in pinecone.list_indexes():\n",
" # we create a new index\n",
" pinecone.create_index(name=index_name, metric=\"cosine\", dimension=1536)\n",
"# The OpenAI embedding model `text-embedding-ada-002 uses 1536 dimensions`\n",
"docsearch = Pinecone.from_documents(docs, embeddings, index_name=index_name)\n",
"\n",
"# if you already have an index, you can load it like this\n",
"# docsearch = Pinecone.from_existing_index(index_name, embeddings)\n",
"\n",
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"docs = docsearch.similarity_search(query)"
"We can connect to our Pinecone index and insert those chunked docs as contents with `Pinecone.from_documents`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9c608226",
"execution_count": 6,
"id": "6e104aee",
"metadata": {},
"outputs": [],
"source": [
"from langchain_pinecone import Pinecone\n",
"\n",
"index_name = \"langchain-test-index\"\n",
"\n",
"docsearch = Pinecone.from_documents(docs, embeddings, index_name=index_name)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "ffbcb3fb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while youre at it, pass the Disclose Act so Americans can know who is funding our elections. \n",
"\n",
"Tonight, Id like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n",
"\n",
"One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n",
"\n",
"And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nations top legal minds, who will continue Justice Breyers legacy of excellence.\n"
]
}
],
"source": [
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"docs = docsearch.similarity_search(query)\n",
"print(docs[0].page_content)"
]
},
@@ -156,15 +127,25 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"id": "38a7a60e",
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"['24631802-4bad-44a7-a4ba-fd71f00cc160']"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"index = pinecone.Index(\"langchain-demo\")\n",
"vectorstore = Pinecone(index, embeddings.embed_query, \"text\")\n",
"vectorstore = Pinecone(index_name=index_name, embedding=embeddings)\n",
"\n",
"vectorstore.add_texts(\"More text!\")"
"vectorstore.add_texts([\"More text!\"])"
]
},
{
@@ -180,10 +161,91 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"id": "a359ed74",
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"## Document 0\n",
"\n",
"Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while youre at it, pass the Disclose Act so Americans can know who is funding our elections. \n",
"\n",
"Tonight, Id like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n",
"\n",
"One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n",
"\n",
"And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nations top legal minds, who will continue Justice Breyers legacy of excellence.\n",
"\n",
"## Document 1\n",
"\n",
"And Im taking robust action to make sure the pain of our sanctions is targeted at Russias economy. And I will use every tool at our disposal to protect American businesses and consumers. \n",
"\n",
"Tonight, I can announce that the United States has worked with 30 other countries to release 60 Million barrels of oil from reserves around the world. \n",
"\n",
"America will lead that effort, releasing 30 Million barrels from our own Strategic Petroleum Reserve. And we stand ready to do more if necessary, unified with our allies. \n",
"\n",
"These steps will help blunt gas prices here at home. And I know the news about whats happening can seem alarming. \n",
"\n",
"But I want you to know that we are going to be okay. \n",
"\n",
"When the history of this era is written Putins war on Ukraine will have left Russia weaker and the rest of the world stronger. \n",
"\n",
"While it shouldnt have taken something so terrible for people around the world to see whats at stake now everyone sees it clearly.\n",
"\n",
"## Document 2\n",
"\n",
"We cant change how divided weve been. But we can change how we move forward—on COVID-19 and other issues we must face together. \n",
"\n",
"I recently visited the New York City Police Department days after the funerals of Officer Wilbert Mora and his partner, Officer Jason Rivera. \n",
"\n",
"They were responding to a 9-1-1 call when a man shot and killed them with a stolen gun. \n",
"\n",
"Officer Mora was 27 years old. \n",
"\n",
"Officer Rivera was 22. \n",
"\n",
"Both Dominican Americans whod grown up on the same streets they later chose to patrol as police officers. \n",
"\n",
"I spoke with their families and told them that we are forever in debt for their sacrifice, and we will carry on their mission to restore the trust and safety every community deserves. \n",
"\n",
"Ive worked on these issues a long time. \n",
"\n",
"I know what works: Investing in crime prevention and community police officers wholl walk the beat, wholl know the neighborhood, and who can restore trust and safety.\n",
"\n",
"## Document 3\n",
"\n",
"One was stationed at bases and breathing in toxic smoke from “burn pits” that incinerated wastes of war—medical and hazard material, jet fuel, and more. \n",
"\n",
"When they came home, many of the worlds fittest and best trained warriors were never the same. \n",
"\n",
"Headaches. Numbness. Dizziness. \n",
"\n",
"A cancer that would put them in a flag-draped coffin. \n",
"\n",
"I know. \n",
"\n",
"One of those soldiers was my son Major Beau Biden. \n",
"\n",
"We dont know for sure if a burn pit was the cause of his brain cancer, or the diseases of so many of our troops. \n",
"\n",
"But Im committed to finding out everything we can. \n",
"\n",
"Committed to military families like Danielle Robinson from Ohio. \n",
"\n",
"The widow of Sergeant First Class Heath Robinson. \n",
"\n",
"He was born a soldier. Army National Guard. Combat medic in Kosovo and Iraq. \n",
"\n",
"Stationed near Baghdad, just yards from burn pits the size of football fields. \n",
"\n",
"Heaths widow Danielle is here with us tonight. They loved going to Ohio State football games. He loved building Legos with their daughter.\n"
]
}
],
"source": [
"retriever = docsearch.as_retriever(search_type=\"mmr\")\n",
"matched_docs = retriever.get_relevant_documents(query)\n",
@@ -203,15 +265,56 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"id": "9ca82740",
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1. Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while youre at it, pass the Disclose Act so Americans can know who is funding our elections. \n",
"\n",
"Tonight, Id like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n",
"\n",
"One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n",
"\n",
"And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nations top legal minds, who will continue Justice Breyers legacy of excellence. \n",
"\n",
"2. We cant change how divided weve been. But we can change how we move forward—on COVID-19 and other issues we must face together. \n",
"\n",
"I recently visited the New York City Police Department days after the funerals of Officer Wilbert Mora and his partner, Officer Jason Rivera. \n",
"\n",
"They were responding to a 9-1-1 call when a man shot and killed them with a stolen gun. \n",
"\n",
"Officer Mora was 27 years old. \n",
"\n",
"Officer Rivera was 22. \n",
"\n",
"Both Dominican Americans whod grown up on the same streets they later chose to patrol as police officers. \n",
"\n",
"I spoke with their families and told them that we are forever in debt for their sacrifice, and we will carry on their mission to restore the trust and safety every community deserves. \n",
"\n",
"Ive worked on these issues a long time. \n",
"\n",
"I know what works: Investing in crime prevention and community police officers wholl walk the beat, wholl know the neighborhood, and who can restore trust and safety. \n",
"\n"
]
}
],
"source": [
"found_docs = docsearch.max_marginal_relevance_search(query, k=2, fetch_k=10)\n",
"for i, doc in enumerate(found_docs):\n",
" print(f\"{i + 1}.\", doc.page_content, \"\\n\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b0fd750b",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@@ -230,7 +333,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.11.4"
}
},
"nbformat": 4,

View File

@@ -0,0 +1,160 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# **NeuralDB**\n",
"NeuralDB is a CPU-friendly and fine-tunable vector store developed by ThirdAI.\n",
"\n",
"### **Initialization**\n",
"There are three initialization methods:\n",
"- From Scratch: Basic model\n",
"- From Bazaar: Download a pretrained base model from our model bazaar for better performance\n",
"- From Checkpoint: Load a model that was previously saved\n",
"\n",
"For all of the following initialization methods, the `thirdai_key` parameter can be ommitted if the `THIRDAI_KEY` environment variable is set.\n",
"\n",
"ThirdAI API keys can be obtained at https://www.thirdai.com/try-bolt/"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.vectorstores import NeuralDBVectorStore\n",
"\n",
"# From scratch\n",
"vectorstore = NeuralDBVectorStore.from_scratch(thirdai_key=\"your-thirdai-key\")\n",
"\n",
"# From bazaar\n",
"vectorstore = NeuralDBVectorStore.from_bazaar(\n",
" # Name of base model to be downloaded from model bazaar.\n",
" # \"General QnA\" gives better performance on question-answering.\n",
" base=\"General QnA\",\n",
" # Path to a directory that caches models to prevent repeated downloading.\n",
" # Defaults to {CWD}/model_bazaar\n",
" bazaar_cache=\"/path/to/bazaar_cache\",\n",
" thirdai_key=\"your-thirdai-key\",\n",
")\n",
"\n",
"# From checkpoint\n",
"vectorstore = NeuralDBVectorStore.from_checkpoint(\n",
" # Path to a NeuralDB checkpoint. For example, if you call\n",
" # vectorstore.save(\"/path/to/checkpoint.ndb\") in one script, then you can\n",
" # call NeuralDBVectorStore.from_checkpoint(\"/path/to/checkpoint.ndb\") in\n",
" # another script to load the saved model.\n",
" checkpoint=\"/path/to/checkpoint.ndb\",\n",
" thirdai_key=\"your-thirdai-key\",\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Inserting document sources**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vectorstore.insert(\n",
" # If you have PDF, DOCX, or CSV files, you can directly pass the paths to the documents\n",
" sources=[\"/path/to/doc.pdf\", \"/path/to/doc.docx\", \"/path/to/doc.csv\"],\n",
" # When True this means that the underlying model in the NeuralDB will\n",
" # undergo unsupervised pretraining on the inserted files. Defaults to True.\n",
" train=True,\n",
" # Much faster insertion with a slight drop in performance. Defaults to True.\n",
" fast_mode=True,\n",
")\n",
"\n",
"from thirdai import neural_db as ndb\n",
"\n",
"vectorstore.insert(\n",
" # If you have files in other formats, or prefer to configure how\n",
" # your files are parsed, then you can pass in NeuralDB document objects\n",
" # like this.\n",
" sources=[\n",
" ndb.PDF(\n",
" \"/path/to/doc.pdf\",\n",
" version=\"v2\",\n",
" chunk_size=100,\n",
" metadata={\"published\": 2022},\n",
" ),\n",
" ndb.Unstructured(\"/path/to/deck.pptx\"),\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Similarity search**\n",
"To query the vectorstore, you can use the standard LangChain vectorstore method `similarity_search`, which returns a list of LangChain Document objects. Each document object represents a chunk of text from the indexed files. For example, it may contain a paragraph from one of the indexed PDF files. In addition to the text, the document's metadata field contains information such as the document's ID, the source of this document (which file it came from), and the score of the document."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# This returns a list of LangChain Document objects\n",
"documents = vectorstore.similarity_search(\"query\", k=10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### **Fine tuning**\n",
"NeuralDBVectorStore can be fine-tuned to user behavior and domain-specific knowledge. It can be fine-tuned in two ways:\n",
"1. Association: the vectorstore associates a source phrase with a target phrase. When the vectorstore sees the source phrase, it will also consider results that are relevant to the target phrase.\n",
"2. Upvoting: the vectorstore upweights the score of a document for a specific query. This is useful when you want to fine-tune the vectorstore to user behavior. For example, if a user searches \"how is a car manufactured\" and likes the returned document with id 52, then we can upvote the document with id 52 for the query \"how is a car manufactured\"."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vectorstore.associate(source=\"source phrase\", target=\"target phrase\")\n",
"vectorstore.associate_batch(\n",
" [\n",
" (\"source phrase 1\", \"target phrase 1\"),\n",
" (\"source phrase 2\", \"target phrase 2\"),\n",
" ]\n",
")\n",
"\n",
"vectorstore.upvote(query=\"how is a car manufactured\", document_id=52)\n",
"vectorstore.upvote_batch(\n",
" [\n",
" (\"query 1\", 52),\n",
" (\"query 2\", 20),\n",
" ]\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "langchain",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -44,11 +44,9 @@
"metadata": {},
"outputs": [
{
"name": "stderr",
"name": "stdout",
"output_type": "stream",
"text": [
"/export/anaconda3/envs/vearch_cluster_langchain/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n",
"Loading checkpoint shards: 100%|██████████| 7/7 [00:07<00:00, 1.01s/it]\n"
]
}

View File

@@ -19,7 +19,7 @@
"\n",
"Newer OpenAI models have been fine-tuned to detect when **one or more** function(s) should be called and respond with the inputs that should be passed to the function(s). In an API call, you can describe functions and have the model intelligently choose to output a JSON object containing arguments to call these functions. The goal of the OpenAI tools APIs is to more reliably return valid and useful function calls than what can be done using a generic text completion or chat API.\n",
"\n",
"OpenAI termed the capability to invoke a **single** function as **functions**, and the capability to invoke **one or more** funcitons as **tools**.\n",
"OpenAI termed the capability to invoke a **single** function as **functions**, and the capability to invoke **one or more** functions as **tools**.\n",
"\n",
":::tip\n",
"\n",

View File

@@ -23,7 +23,7 @@
"\n",
"* Use with regular LLMs, not with chat models.\n",
"* Use only with unstructured tools; i.e., tools that accept a single string input.\n",
"* See [AgentTypes](/docs/moduels/agents/agent_types/) documentation for more agent types.\n",
"* See [AgentTypes](/docs/modules/agents/agent_types/) documentation for more agent types.\n",
":::"
]
},

View File

@@ -60,7 +60,7 @@
" * document addition by id (`add_documents` method with `ids` argument)\n",
" * delete by id (`delete` method with `ids` argument)\n",
"\n",
"Compatible Vectorstores: `AnalyticDB`, `AstraDB`, `AwaDB`, `Bagel`, `Cassandra`, `Chroma`, `DashVector`, `DatabricksVectorSearch`, `DeepLake`, `Dingo`, `ElasticVectorSearch`, `ElasticsearchStore`, `FAISS`, `HanaDB`, `MyScale`, `PGVector`, `Pinecone`, `Qdrant`, `Redis`, `ScaNN`, `SupabaseVectorStore`, `SurrealDBStore`, `TimescaleVector`, `Vald`, `Vearch`, `VespaStore`, `Weaviate`, `ZepVectorStore`.\n",
"Compatible Vectorstores: `AnalyticDB`, `AstraDB`, `AwaDB`, `Bagel`, `Cassandra`, `Chroma`, `DashVector`, `DatabricksVectorSearch`, `DeepLake`, `Dingo`, `ElasticVectorSearch`, `ElasticsearchStore`, `FAISS`, `HanaDB`, `Milvus`, `MyScale`, `PGVector`, `Pinecone`, `Qdrant`, `Redis`, `ScaNN`, `SupabaseVectorStore`, `SurrealDBStore`, `TimescaleVector`, `Vald`, `Vearch`, `VespaStore`, `Weaviate`, `ZepVectorStore`.\n",
" \n",
"## Caution\n",
"\n",

View File

@@ -24,8 +24,8 @@
"from langchain.prompts import (\n",
" PromptTemplate,\n",
")\n",
"from langchain_openai import ChatOpenAI, OpenAI\n",
"from pydantic import BaseModel, Field"
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
"from langchain_openai import ChatOpenAI, OpenAI"
]
},
{
@@ -174,7 +174,7 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain.output_parsers import RetryWithErrorOutputParser"
"from langchain.output_parsers import RetryOutputParser"
]
},
{
@@ -184,9 +184,7 @@
"metadata": {},
"outputs": [],
"source": [
"retry_parser = RetryWithErrorOutputParser.from_llm(\n",
" parser=parser, llm=OpenAI(temperature=0)\n",
")"
"retry_parser = RetryOutputParser.from_llm(parser=parser, llm=OpenAI(temperature=0))"
]
},
{
@@ -210,6 +208,41 @@
"retry_parser.parse_with_prompt(bad_response, prompt_value)"
]
},
{
"cell_type": "markdown",
"id": "16827256-5801-4388-b6fa-608991e29961",
"metadata": {},
"source": [
"We can also add the RetryOutputParser easily with a custom chain which transform the raw LLM/ChatModel output into a more workable format."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "7eaff2fb-56d3-481c-99a1-a968a49d0654",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Action(action='search', action_input='leo di caprio girlfriend')\n"
]
}
],
"source": [
"from langchain_core.runnables import RunnableLambda, RunnableParallel\n",
"\n",
"completion_chain = prompt | OpenAI(temperature=0)\n",
"\n",
"main_chain = RunnableParallel(\n",
" completion=completion_chain, prompt_value=prompt\n",
") | RunnableLambda(lambda x: retry_parser.parse_with_prompt(**x))\n",
"\n",
"\n",
"main_chain.invoke({\"query\": \"who is leo di caprios gf?\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -235,7 +268,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.9.13"
}
},
"nbformat": 4,

View File

@@ -101,7 +101,7 @@
"metadata": {},
"source": [
"You can create custom prompt templates that format the prompt in any way you want.\n",
"For more information, see [Custom Prompt Templates](./custom_prompt_template).\n",
"For more information, see [Prompt Template Composition](./composition).\n",
"\n",
"## `ChatPromptTemplate`\n",
"\n",

View File

@@ -1,747 +0,0 @@
{
"cells": [
{
"cell_type": "raw",
"id": "22fd28c9-9b48-476c-bca8-20efef7fdb14",
"metadata": {},
"source": [
"---\n",
"sidebar_position: 1\n",
"title: Chatbots\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "ee7f95e4",
"metadata": {},
"source": [
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/langchain-ai/langchain/blob/master/docs/docs/use_cases/chatbots.ipynb)\n",
"\n",
"## Use case\n",
"\n",
"Chatbots are one of the central LLM use-cases. The core features of chatbots are that they can have long-running conversations and have access to information that users want to know about.\n",
"\n",
"Aside from basic prompting and LLMs, memory and retrieval are the core components of a chatbot. Memory allows a chatbot to remember past interactions, and retrieval provides a chatbot with up-to-date, domain-specific information."
]
},
{
"cell_type": "markdown",
"id": "56615b45",
"metadata": {},
"source": [
"![Image description](../../static/img/chat_use_case.png)"
]
},
{
"cell_type": "markdown",
"id": "ff48f490",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"The chat model interface is based around messages rather than raw text. Several components are important to consider for chat:\n",
"\n",
"* `chat model`: See [here](/docs/integrations/chat) for a list of chat model integrations and [here](/docs/modules/model_io/chat) for documentation on the chat model interface in LangChain. You can use `LLMs` (see [here](/docs/modules/model_io/llms)) for chatbots as well, but chat models have a more conversational tone and natively support a message interface.\n",
"* `prompt template`: Prompt templates make it easy to assemble prompts that combine default messages, user input, chat history, and (optionally) additional retrieved context.\n",
"* `memory`: [See here](/docs/modules/memory/) for in-depth documentation on memory types\n",
"* `retriever` (optional): [See here](/docs/modules/data_connection/retrievers) for in-depth documentation on retrieval systems. These are useful if you want to build a chatbot with domain-specific knowledge.\n",
"\n",
"## Quickstart\n",
"\n",
"Here's a quick preview of how we can create chatbot interfaces. First let's install some dependencies and set the required credentials:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5070a1fd",
"metadata": {},
"outputs": [],
"source": [
"%pip install --upgrade --quiet langchain langchain-openai\n",
"\n",
"# Set env var OPENAI_API_KEY or load from a .env file:\n",
"# import dotenv\n",
"# dotenv.load_dotenv()"
]
},
{
"cell_type": "markdown",
"id": "88197b95",
"metadata": {},
"source": [
"With a plain chat model, we can get chat completions by [passing one or more messages](/docs/modules/model_io/chat) to the model.\n",
"\n",
"The chat model will respond with a message."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "5b0d84ae",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"J'adore la programmation.\", additional_kwargs={}, example=False)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.schema import HumanMessage, SystemMessage\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"chat = ChatOpenAI()\n",
"chat(\n",
" [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French: I love programming.\"\n",
" )\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"id": "7935d9a5",
"metadata": {},
"source": [
"And if we pass in a list of messages:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "afd27a9f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"J'adore la programmation.\", additional_kwargs={}, example=False)"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" SystemMessage(\n",
" content=\"You are a helpful assistant that translates English to French.\"\n",
" ),\n",
" HumanMessage(content=\"I love programming.\"),\n",
"]\n",
"chat(messages)"
]
},
{
"cell_type": "markdown",
"id": "c7a1d169",
"metadata": {},
"source": [
"We can then wrap our chat model in a `ConversationChain`, which has built-in memory for remembering past user inputs and model outputs."
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "fdb05d74",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Je adore la programmation.'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.chains import ConversationChain\n",
"\n",
"conversation = ConversationChain(llm=chat)\n",
"conversation.run(\"Translate this sentence from English to French: I love programming.\")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "d801a173",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Ich liebe Programmieren.'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversation.run(\"Translate it to German.\")"
]
},
{
"cell_type": "markdown",
"id": "9e86788c",
"metadata": {},
"source": [
"## Memory \n",
"\n",
"As we mentioned above, the core component of chatbots is the memory system. One of the simplest and most commonly used forms of memory is `ConversationBufferMemory`:\n",
"\n",
"* This memory allows for storing of messages in a `buffer`\n",
"* When called in a chain, it returns all of the messages it has stored\n",
"\n",
"LangChain comes with many other types of memory, too. [See here](/docs/modules/memory/) for in-depth documentation on memory types.\n",
"\n",
"For now let's take a quick look at ConversationBufferMemory. We can manually add a few chat messages to the memory like so:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1380a4ea",
"metadata": {},
"outputs": [],
"source": [
"from langchain.memory import ConversationBufferMemory\n",
"\n",
"memory = ConversationBufferMemory()\n",
"memory.chat_memory.add_user_message(\"hi!\")\n",
"memory.chat_memory.add_ai_message(\"whats up?\")"
]
},
{
"cell_type": "markdown",
"id": "a3d5d1f8",
"metadata": {},
"source": [
"And now we can load from our memory. The key method exposed by all `Memory` classes is `load_memory_variables`. This takes in any initial chain input and returns a list of memory variables which are added to the chain input. \n",
"\n",
"Since this simple memory type doesn't actually take into account the chain input when loading memory, we can pass in an empty input for now:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "982467e7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'history': 'Human: hi!\\nAI: whats up?'}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"memory.load_memory_variables({})"
]
},
{
"cell_type": "markdown",
"id": "7c1b20d4",
"metadata": {},
"source": [
"We can also keep a sliding window of the most recent `k` interactions using `ConversationBufferWindowMemory`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f72b9ff7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'history': 'Human: not much you\\nAI: not much'}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.memory import ConversationBufferWindowMemory\n",
"\n",
"memory = ConversationBufferWindowMemory(k=1)\n",
"memory.save_context({\"input\": \"hi\"}, {\"output\": \"whats up\"})\n",
"memory.save_context({\"input\": \"not much you\"}, {\"output\": \"not much\"})\n",
"memory.load_memory_variables({})"
]
},
{
"cell_type": "markdown",
"id": "7b84f90a",
"metadata": {},
"source": [
"`ConversationSummaryMemory` is an extension of this theme.\n",
"\n",
"It creates a summary of the conversation over time. \n",
"\n",
"This memory is most useful for longer conversations where the full message history would consume many tokens."
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "ca2596ed",
"metadata": {},
"outputs": [],
"source": [
"from langchain.memory import ConversationSummaryMemory\n",
"from langchain_openai import OpenAI\n",
"\n",
"llm = OpenAI(temperature=0)\n",
"memory = ConversationSummaryMemory(llm=llm)\n",
"memory.save_context({\"input\": \"hi\"}, {\"output\": \"whats up\"})\n",
"memory.save_context(\n",
" {\"input\": \"im working on better docs for chatbots\"},\n",
" {\"output\": \"oh, that sounds like a lot of work\"},\n",
")\n",
"memory.save_context(\n",
" {\"input\": \"yes, but it's worth the effort\"},\n",
" {\"output\": \"agreed, good docs are important!\"},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "060f69b7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'history': '\\nThe human greets the AI, to which the AI responds. The human then mentions they are working on better docs for chatbots, to which the AI responds that it sounds like a lot of work. The human agrees that it is worth the effort, and the AI agrees that good docs are important.'}"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"memory.load_memory_variables({})"
]
},
{
"cell_type": "markdown",
"id": "4bf036f6",
"metadata": {},
"source": [
"`ConversationSummaryBufferMemory` extends this a bit further:\n",
"\n",
"It uses token length rather than number of interactions to determine when to flush interactions."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "38b42728",
"metadata": {},
"outputs": [],
"source": [
"from langchain.memory import ConversationSummaryBufferMemory\n",
"\n",
"memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)\n",
"memory.save_context({\"input\": \"hi\"}, {\"output\": \"whats up\"})\n",
"memory.save_context({\"input\": \"not much you\"}, {\"output\": \"not much\"})"
]
},
{
"cell_type": "markdown",
"id": "ff0db09f",
"metadata": {},
"source": [
"## Conversation \n",
"\n",
"We can unpack what goes under the hood with `ConversationChain`. \n",
"\n",
"We can specify our memory, `ConversationSummaryMemory` and we can specify the prompt. "
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "fccd6995",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
"Prompt after formatting:\n",
"\u001b[32;1m\u001b[1;3mSystem: You are a nice chatbot having a conversation with a human.\n",
"Human: hi\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'question': 'hi',\n",
" 'chat_history': [HumanMessage(content='hi', additional_kwargs={}, example=False),\n",
" AIMessage(content='Hello! How can I assist you today?', additional_kwargs={}, example=False)],\n",
" 'text': 'Hello! How can I assist you today?'}"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.chains import LLMChain\n",
"from langchain.prompts import (\n",
" ChatPromptTemplate,\n",
" HumanMessagePromptTemplate,\n",
" MessagesPlaceholder,\n",
" SystemMessagePromptTemplate,\n",
")\n",
"\n",
"# LLM\n",
"llm = ChatOpenAI()\n",
"\n",
"# Prompt\n",
"prompt = ChatPromptTemplate(\n",
" messages=[\n",
" SystemMessagePromptTemplate.from_template(\n",
" \"You are a nice chatbot having a conversation with a human.\"\n",
" ),\n",
" # The `variable_name` here is what must align with memory\n",
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
" HumanMessagePromptTemplate.from_template(\"{question}\"),\n",
" ]\n",
")\n",
"\n",
"# Notice that we `return_messages=True` to fit into the MessagesPlaceholder\n",
"# Notice that `\"chat_history\"` aligns with the MessagesPlaceholder name\n",
"memory = ConversationBufferMemory(memory_key=\"chat_history\", return_messages=True)\n",
"conversation = LLMChain(llm=llm, prompt=prompt, verbose=True, memory=memory)\n",
"\n",
"# Notice that we just pass in the `question` variables - `chat_history` gets populated by memory\n",
"conversation({\"question\": \"hi\"})"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "eb0cadfd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
"Prompt after formatting:\n",
"\u001b[32;1m\u001b[1;3mSystem: You are a nice chatbot having a conversation with a human.\n",
"Human: hi\n",
"AI: Hello! How can I assist you today?\n",
"Human: Translate this sentence from English to French: I love programming.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'question': 'Translate this sentence from English to French: I love programming.',\n",
" 'chat_history': [HumanMessage(content='hi', additional_kwargs={}, example=False),\n",
" AIMessage(content='Hello! How can I assist you today?', additional_kwargs={}, example=False),\n",
" HumanMessage(content='Translate this sentence from English to French: I love programming.', additional_kwargs={}, example=False),\n",
" AIMessage(content='Sure! The translation of \"I love programming\" from English to French is \"J\\'adore programmer.\"', additional_kwargs={}, example=False)],\n",
" 'text': 'Sure! The translation of \"I love programming\" from English to French is \"J\\'adore programmer.\"'}"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversation(\n",
" {\"question\": \"Translate this sentence from English to French: I love programming.\"}\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "c56d6219",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new LLMChain chain...\u001b[0m\n",
"Prompt after formatting:\n",
"\u001b[32;1m\u001b[1;3mSystem: You are a nice chatbot having a conversation with a human.\n",
"Human: hi\n",
"AI: Hello! How can I assist you today?\n",
"Human: Translate this sentence from English to French: I love programming.\n",
"AI: Sure! The translation of \"I love programming\" from English to French is \"J'adore programmer.\"\n",
"Human: Now translate the sentence to German.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'question': 'Now translate the sentence to German.',\n",
" 'chat_history': [HumanMessage(content='hi', additional_kwargs={}, example=False),\n",
" AIMessage(content='Hello! How can I assist you today?', additional_kwargs={}, example=False),\n",
" HumanMessage(content='Translate this sentence from English to French: I love programming.', additional_kwargs={}, example=False),\n",
" AIMessage(content='Sure! The translation of \"I love programming\" from English to French is \"J\\'adore programmer.\"', additional_kwargs={}, example=False),\n",
" HumanMessage(content='Now translate the sentence to German.', additional_kwargs={}, example=False),\n",
" AIMessage(content='Certainly! The translation of \"I love programming\" from English to German is \"Ich liebe das Programmieren.\"', additional_kwargs={}, example=False)],\n",
" 'text': 'Certainly! The translation of \"I love programming\" from English to German is \"Ich liebe das Programmieren.\"'}"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversation({\"question\": \"Now translate the sentence to German.\"})"
]
},
{
"cell_type": "markdown",
"id": "43858489",
"metadata": {},
"source": [
"We can see the chat history preserved in the prompt using the [LangSmith trace](https://smith.langchain.com/public/dce34c57-21ca-4283-9020-a8e0d78a59de/r).\n",
"\n",
"![Image description](../../static/img/chat_use_case_2.png)"
]
},
{
"cell_type": "markdown",
"id": "3f35cc16",
"metadata": {},
"source": [
"## Chat Retrieval\n",
"\n",
"Now, suppose we want to [chat with documents](https://twitter.com/mayowaoshin/status/1640385062708424708?s=20) or some other source of knowledge.\n",
"\n",
"This is popular use case, combining chat with [document retrieval](/docs/use_cases/question_answering).\n",
"\n",
"It allows us to chat with specific information that the model was not trained on."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a01e7b5",
"metadata": {},
"outputs": [],
"source": [
"%pip install --upgrade --quiet tiktoken chromadb"
]
},
{
"cell_type": "markdown",
"id": "88e220de",
"metadata": {},
"source": [
"Load a blog post."
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "1b99b36c",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.document_loaders import WebBaseLoader\n",
"\n",
"loader = WebBaseLoader(\"https://lilianweng.github.io/posts/2023-06-23-agent/\")\n",
"data = loader.load()"
]
},
{
"cell_type": "markdown",
"id": "3662ce79",
"metadata": {},
"source": [
"Split and store this in a vector."
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "058f1541",
"metadata": {},
"outputs": [],
"source": [
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"\n",
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)\n",
"all_splits = text_splitter.split_documents(data)\n",
"\n",
"from langchain_community.vectorstores import Chroma\n",
"from langchain_openai import OpenAIEmbeddings\n",
"\n",
"vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())"
]
},
{
"cell_type": "markdown",
"id": "603d9441",
"metadata": {},
"source": [
"Create our memory, as before, but's let's use `ConversationSummaryMemory`."
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "f89fd3f5",
"metadata": {},
"outputs": [],
"source": [
"memory = ConversationSummaryMemory(\n",
" llm=llm, memory_key=\"chat_history\", return_messages=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "28503423",
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains import ConversationalRetrievalChain\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"llm = ChatOpenAI()\n",
"retriever = vectorstore.as_retriever()\n",
"qa = ConversationalRetrievalChain.from_llm(llm, retriever=retriever, memory=memory)"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "a9c3bd5e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'question': 'How do agents use Task decomposition?',\n",
" 'chat_history': [SystemMessage(content='', additional_kwargs={})],\n",
" 'answer': 'Agents can use task decomposition in several ways:\\n\\n1. Simple prompting: Agents can use Language Model based prompting to break down tasks into subgoals. For example, by providing prompts like \"Steps for XYZ\" or \"What are the subgoals for achieving XYZ?\", the agent can generate a sequence of smaller steps that lead to the completion of the overall task.\\n\\n2. Task-specific instructions: Agents can be given task-specific instructions to guide their planning process. For example, if the task is to write a novel, the agent can be instructed to \"Write a story outline.\" This provides a high-level structure for the task and helps in breaking it down into smaller components.\\n\\n3. Human inputs: Agents can also take inputs from humans to decompose tasks. This can be done through direct communication or by leveraging human expertise. Humans can provide guidance and insights to help the agent break down complex tasks into manageable subgoals.\\n\\nOverall, task decomposition allows agents to break down large tasks into smaller, more manageable subgoals, enabling them to plan and execute complex tasks efficiently.'}"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qa(\"How do agents use Task decomposition?\")"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "a29a7713",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'question': 'What are the various ways to implement memory to support it?',\n",
" 'chat_history': [SystemMessage(content='The human asks how agents use task decomposition. The AI explains that agents can use task decomposition in several ways, including simple prompting, task-specific instructions, and human inputs. Task decomposition allows agents to break down large tasks into smaller, more manageable subgoals, enabling them to plan and execute complex tasks efficiently.', additional_kwargs={})],\n",
" 'answer': 'There are several ways to implement memory to support task decomposition:\\n\\n1. Long-Term Memory Management: This involves storing and organizing information in a long-term memory system. The agent can retrieve past experiences, knowledge, and learned strategies to guide the task decomposition process.\\n\\n2. Internet Access: The agent can use internet access to search for relevant information and gather resources to aid in task decomposition. This allows the agent to access a vast amount of information and utilize it in the decomposition process.\\n\\n3. GPT-3.5 Powered Agents: The agent can delegate simple tasks to GPT-3.5 powered agents. These agents can perform specific tasks or provide assistance in task decomposition, allowing the main agent to focus on higher-level planning and decision-making.\\n\\n4. File Output: The agent can store the results of task decomposition in files or documents. This allows for easy retrieval and reference during the execution of the task.\\n\\nThese memory resources help the agent in organizing and managing information, making informed decisions, and effectively decomposing complex tasks into smaller, manageable subgoals.'}"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qa(\"What are the various ways to implement memory to support it?\")"
]
},
{
"cell_type": "markdown",
"id": "d5e8d5f4",
"metadata": {},
"source": [
"Again, we can use the [LangSmith trace](https://smith.langchain.com/public/18460363-0c70-4c72-81c7-3b57253bb58c/r) to explore the prompt structure.\n",
"\n",
"### Going deeper \n",
"\n",
"* Agents, such as the [conversational retrieval agent](/docs/use_cases/question_answering/conversational_retrieval_agents), can be used for retrieval when necessary while also holding a conversation.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1ff8925f-4c21-4680-a9cd-3670ad4852b3",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,39 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Chatbots\n",
"\n",
"## Overview\n",
"\n",
"Chatbots are one of the most popular use-cases for LLMs. The core features of chatbots are that they can have long-running, stateful conversations and can answer user questions using relevant information.\n",
"\n",
"## Architectures\n",
"\n",
"Designing a chatbot involves considering various techniques with different benefits and tradeoffs depending on what sorts of questions you expect it to handle.\n",
"\n",
"For example, chatbots commonly use [retrieval-augmented generation](/docs/use_cases/question_answering/), or RAG, over private data to better answer domain-specific questions. You also might choose to route between multiple data sources to ensure it only uses the most topical context for final question answering, or choose to use a more specialized type of chat history or memory than just passing messages back and forth.\n",
"\n",
"![Image description](../../../static/img/chat_use_case.png)\n",
"\n",
"Optimizations like this can make your chatbot more powerful, but add latency and complexity. The aim of this guide is to give you an overview of how to implement various features and help you tailor your chatbot to your particular use-case.\n",
"\n",
"## Table of contents\n",
"\n",
"- [Quickstart](/docs/use_cases/chatbots/quickstart): We recommend starting here. Many of the following guides assume you fully understand the architecture shown in the Quickstart.\n",
"- [Memory management](/docs/use_cases/chatbots/memory_management): This section covers various strategies your chatbot can use to handle information from previous conversation turns.\n",
"- [Retrieval](/docs/use_cases/chatbots/retrieval): This section covers how to enable your chatbot to use outside data sources as context.\n",
"- [Tool usage](/docs/use_cases/chatbots/tool_usage): This section covers how to turn your chatbot into a conversational agent by adding the ability to interact with other systems and APIs using tools."
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,780 @@
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"---\n",
"sidebar_position: 1\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Memory management\n",
"\n",
"A key feature of chatbots is their ability to use content of previous conversation turns as context. This state management can take several forms, including:\n",
"\n",
"- Simply stuffing previous messages into a chat model prompt.\n",
"- The above, but trimming old messages to reduce the amount of distracting information the model has to deal with.\n",
"- More complex modifications like synthesizing summaries for long running conversations.\n",
"\n",
"We'll go into more detail on a few techniques below!\n",
"\n",
"## Setup\n",
"\n",
"You'll need to install a few packages, and have your OpenAI API key set as an environment variable named `OPENAI_API_KEY`:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 22.0.4; however, version 23.3.2 is available.\n",
"You should consider upgrading via the '/Users/jacoblee/.pyenv/versions/3.10.5/bin/python -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n",
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%pip install --upgrade --quiet langchain langchain-openai\n",
"\n",
"# Set env var OPENAI_API_KEY or load from a .env file:\n",
"import dotenv\n",
"\n",
"dotenv.load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's also set up a chat model that we'll use for the below examples."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"\n",
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Message passing\n",
"\n",
"The simplest form of memory is simply passing chat history messages into a chain. Here's an example:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='I said \"J\\'adore la programmation,\" which means \"I love programming\" in French.')"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import AIMessage, HumanMessage\n",
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. Answer all questions to the best of your ability.\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
")\n",
"\n",
"chain = prompt | chat\n",
"\n",
"chain.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French: I love programming.\"\n",
" ),\n",
" AIMessage(content=\"J'adore la programmation.\"),\n",
" HumanMessage(content=\"What did you just say?\"),\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that by passing the previous conversation into a chain, it can use it as context to answer questions. This is the basic concept underpinning chatbot memory - the rest of the guide will demonstrate convenient techniques for passing or reformatting messages.\n",
"\n",
"## Chat history\n",
"\n",
"It's perfectly fine to store and pass messages directly as an array, but we can use LangChain's built-in [message history class](/docs/modules/memory/chat_messages/) to store and load messages as well. Instances of this class are responsible for storing and loading chat messages from persistent storage. LangChain integrates with many providers - you can see a [list of integrations here](/docs/integrations/memory) - but for this demo we will use an ephemeral demo class.\n",
"\n",
"Here's an example of the API:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content='Translate this sentence from English to French: I love programming.'),\n",
" AIMessage(content=\"J'adore la programmation.\")]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.memory import ChatMessageHistory\n",
"\n",
"demo_ephemeral_chat_history = ChatMessageHistory()\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\n",
" \"Translate this sentence from English to French: I love programming.\"\n",
")\n",
"\n",
"demo_ephemeral_chat_history.add_ai_message(\"J'adore la programmation.\")\n",
"\n",
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can use it directly to store conversation turns for our chain:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='You asked me to translate the sentence \"I love programming\" from English to French.')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history = ChatMessageHistory()\n",
"\n",
"input1 = \"Translate this sentence from English to French: I love programming.\"\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(input1)\n",
"\n",
"response = chain.invoke(\n",
" {\n",
" \"messages\": demo_ephemeral_chat_history.messages,\n",
" }\n",
")\n",
"\n",
"demo_ephemeral_chat_history.add_ai_message(response)\n",
"\n",
"input2 = \"What did I just ask you?\"\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(input2)\n",
"\n",
"chain.invoke(\n",
" {\n",
" \"messages\": demo_ephemeral_chat_history.messages,\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Automatic history management\n",
"\n",
"The previous examples pass messages to the chain explicitly. This is a completely acceptable approach, but it does require external management of new messages. LangChain also includes an wrapper for LCEL chains that can handle this process automatically called `RunnableWithMessageHistory`.\n",
"\n",
"To show how it works, let's slightly modify the above prompt to take a final `input` variable that populates a `HumanMessage` template after the chat history. This means that we will expect a `chat_history` parameter that contains all messages BEFORE the current messages instead of all messages:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. Answer all questions to the best of your ability.\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
" (\"human\", \"{input}\"),\n",
" ]\n",
")\n",
"\n",
"chain = prompt | chat"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" We'll pass the latest input to the conversation here and let the `RunnableWithMessageHistory` class wrap our chain and do the work of appending that `input` variable to the chat history.\n",
" \n",
" Next, let's declare our wrapped chain:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.runnables.history import RunnableWithMessageHistory\n",
"\n",
"demo_ephemeral_chat_history_for_chain = ChatMessageHistory()\n",
"\n",
"chain_with_message_history = RunnableWithMessageHistory(\n",
" chain,\n",
" lambda session_id: demo_ephemeral_chat_history_for_chain,\n",
" input_messages_key=\"input\",\n",
" history_messages_key=\"chat_history\",\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This class takes a few parameters in addition to the chain that we want to wrap:\n",
"\n",
"- A factory function that returns a message history for a given session id. This allows your chain to handle multiple users at once by loading different messages for different conversations.\n",
"- An `input_messages_key` that specifies which part of the input should be tracked and stored in the chat history. In this example, we want to track the string passed in as `input`.\n",
"- A `history_messages_key` that specifies what the previous messages should be injected into the prompt as. Our prompt has a `MessagesPlaceholder` named `chat_history`, so we specify this property to match.\n",
"- (For chains with multiple outputs) an `output_messages_key` which specifies which output to store as history. This is the inverse of `input_messages_key`.\n",
"\n",
"We can invoke this new chain as normal, with an additional `configurable` field that specifies the particular `session_id` to pass to the factory function. This is unused for the demo, but in real-world chains, you'll want to return a chat history corresponding to the passed session:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='The translation of \"I love programming\" in French is \"J\\'adore la programmation.\"')"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain_with_message_history.invoke(\n",
" {\"input\": \"Translate this sentence from English to French: I love programming.\"},\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='You just asked me to translate the sentence \"I love programming\" from English to French.')"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain_with_message_history.invoke(\n",
" {\"input\": \"What did I just ask you?\"}, {\"configurable\": {\"session_id\": \"unused\"}}\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Modifying chat history\n",
"\n",
"Modifying stored chat messages can help your chatbot handle a variety of situations. Here are some examples:\n",
"\n",
"### Trimming messages\n",
"\n",
"LLMs and chat models have limited context windows, and even if you're not directly hitting limits, you may want to limit the amount of distraction the model has to deal with. One solution is to only load and store the most recent `n` messages. Let's use an example history with some preloaded messages:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content=\"Hey there! I'm Nemo.\"),\n",
" AIMessage(content='Hello!'),\n",
" HumanMessage(content='How are you today?'),\n",
" AIMessage(content='Fine thanks!')]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history = ChatMessageHistory()\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\"Hey there! I'm Nemo.\")\n",
"demo_ephemeral_chat_history.add_ai_message(\"Hello!\")\n",
"demo_ephemeral_chat_history.add_user_message(\"How are you today?\")\n",
"demo_ephemeral_chat_history.add_ai_message(\"Fine thanks!\")\n",
"\n",
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's use this message history with the `RunnableWithMessageHistory` chain we declared above:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='Your name is Nemo.')"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. Answer all questions to the best of your ability.\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
" (\"human\", \"{input}\"),\n",
" ]\n",
")\n",
"\n",
"chain = prompt | chat\n",
"\n",
"chain_with_message_history = RunnableWithMessageHistory(\n",
" chain,\n",
" lambda session_id: demo_ephemeral_chat_history,\n",
" input_messages_key=\"input\",\n",
" history_messages_key=\"chat_history\",\n",
")\n",
"\n",
"chain_with_message_history.invoke(\n",
" {\"input\": \"What's my name?\"},\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see the chain remembers the preloaded name.\n",
"\n",
"But let's say we have a very small context window, and we want to trim the number of messages passed to the chain to only the 2 most recent ones. We can use the `clear` method to remove messages and re-add them to the history. We don't have to, but let's put this method at the front of our chain to ensure it's always called:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.runnables import RunnablePassthrough\n",
"\n",
"\n",
"def trim_messages(chain_input):\n",
" stored_messages = demo_ephemeral_chat_history.messages\n",
" if len(stored_messages) <= 2:\n",
" return False\n",
"\n",
" demo_ephemeral_chat_history.clear()\n",
"\n",
" for message in stored_messages[-2:]:\n",
" demo_ephemeral_chat_history.add_message(message)\n",
"\n",
" return True\n",
"\n",
"\n",
"chain_with_trimming = (\n",
" RunnablePassthrough.assign(messages_trimmed=trim_messages)\n",
" | chain_with_message_history\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's call this new chain and check the messages afterwards:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"P. Sherman's address is 42 Wallaby Way, Sydney.\")"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain_with_trimming.invoke(\n",
" {\"input\": \"Where does P. Sherman live?\"},\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content=\"What's my name?\"),\n",
" AIMessage(content='Your name is Nemo.'),\n",
" HumanMessage(content='Where does P. Sherman live?'),\n",
" AIMessage(content=\"P. Sherman's address is 42 Wallaby Way, Sydney.\")]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And we can see that our history has removed the two oldest messages while still adding the most recent conversation at the end. The next time the chain is called, `trim_messages` will be called again, and only the two most recent messages will be passed to the model. In this case, this means that the model will forget the name we gave it the next time we invoke it:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"I'm sorry, I don't have access to your personal information.\")"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain_with_trimming.invoke(\n",
" {\"input\": \"What is my name?\"},\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content='Where does P. Sherman live?'),\n",
" AIMessage(content=\"P. Sherman's address is 42 Wallaby Way, Sydney.\"),\n",
" HumanMessage(content='What is my name?'),\n",
" AIMessage(content=\"I'm sorry, I don't have access to your personal information.\")]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Summary memory\n",
"\n",
"We can use this same pattern in other ways too. For example, we could use an additional LLM call to generate a summary of the conversation before calling our chain. Let's recreate our chat history and chatbot chain:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content=\"Hey there! I'm Nemo.\"),\n",
" AIMessage(content='Hello!'),\n",
" HumanMessage(content='How are you today?'),\n",
" AIMessage(content='Fine thanks!')]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history = ChatMessageHistory()\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\"Hey there! I'm Nemo.\")\n",
"demo_ephemeral_chat_history.add_ai_message(\"Hello!\")\n",
"demo_ephemeral_chat_history.add_user_message(\"How are you today?\")\n",
"demo_ephemeral_chat_history.add_ai_message(\"Fine thanks!\")\n",
"\n",
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We'll slightly modify the prompt to make the LLM aware that will receive a condensed summary instead of a chat history:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. Answer all questions to the best of your ability. The provided chat history includes facts about the user you are speaking with.\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
" (\"user\", \"{input}\"),\n",
" ]\n",
")\n",
"\n",
"chain = prompt | chat\n",
"\n",
"chain_with_message_history = RunnableWithMessageHistory(\n",
" chain,\n",
" lambda session_id: demo_ephemeral_chat_history,\n",
" input_messages_key=\"input\",\n",
" history_messages_key=\"chat_history\",\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now, let's create a function that will distill previous interactions into a summary. We can add this one to the front of the chain too:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"def summarize_messages(chain_input):\n",
" stored_messages = demo_ephemeral_chat_history.messages\n",
" if len(stored_messages) == 0:\n",
" return False\n",
" summarization_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
" (\n",
" \"user\",\n",
" \"Distill the above chat messages into a single summary message. Include as many specific details as you can.\",\n",
" ),\n",
" ]\n",
" )\n",
" summarization_chain = summarization_prompt | chat\n",
"\n",
" summary_message = summarization_chain.invoke({\"chat_history\": stored_messages})\n",
"\n",
" demo_ephemeral_chat_history.clear()\n",
"\n",
" demo_ephemeral_chat_history.add_message(summary_message)\n",
"\n",
" return True\n",
"\n",
"\n",
"chain_with_summarization = (\n",
" RunnablePassthrough.assign(messages_summarized=summarize_messages)\n",
" | chain_with_message_history\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see if it remembers the name we gave it:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='You introduced yourself as Nemo. How can I assist you today, Nemo?')"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain_with_summarization.invoke(\n",
" {\"input\": \"What did I say my name was?\"},\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[AIMessage(content='The conversation is between Nemo and an AI. Nemo introduces himself and the AI responds with a greeting. Nemo then asks the AI how it is doing, and the AI responds that it is fine.'),\n",
" HumanMessage(content='What did I say my name was?'),\n",
" AIMessage(content='You introduced yourself as Nemo. How can I assist you today, Nemo?')]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that invoking the chain again will generate another summary generated from the initial summary plus new messages and so on. You could also design a hybrid approach where a certain number of messages are retained in chat history while others are summarized."
]
}
],
"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.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,935 @@
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"---\n",
"sidebar_position: 0\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[![](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/langchain-ai/langchain/blob/master/docs/docs/use_cases/chatbots.ipynb)\n",
"\n",
"# Quickstart"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"We'll go over an example of how to design and implement an LLM-powered chatbot. Here are a few of the high-level components we'll be working with:\n",
"\n",
"- `Chat Models`. The chatbot interface is based around messages rather than raw text, and therefore is best suited to Chat Models rather than text LLMs. See [here](/docs/integrations/chat) for a list of chat model integrations and [here](/docs/modules/model_io/chat) for documentation on the chat model interface in LangChain. You can use `LLMs` (see [here](/docs/modules/model_io/llms)) for chatbots as well, but chat models have a more conversational tone and natively support a message interface.\n",
"- `Prompt Templates`, which simplify the process of assembling prompts that combine default messages, user input, chat history, and (optionally) additional retrieved context.\n",
"- `Chat History`, which allows a chatbot to \"remember\" past interactions and take them into account when responding to followup questions. [See here](/docs/modules/memory/chat_messages/) for more information.\n",
"- `Retrievers` (optional), which are useful if you want to build a chatbot that can use domain-specific, up-to-date knowledge as context to augment its responses. [See here](/docs/modules/data_connection/retrievers) for in-depth documentation on retrieval systems.\n",
"\n",
"We'll cover how to fit the above components together to create a powerful conversational chatbot.\n",
"\n",
"## Quickstart\n",
"\n",
"To start, let's install some dependencies and set the required credentials:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 22.0.4; however, version 23.3.2 is available.\n",
"You should consider upgrading via the '/Users/jacoblee/.pyenv/versions/3.10.5/bin/python -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n",
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%pip install --upgrade --quiet langchain langchain-openai\n",
"\n",
"# Set env var OPENAI_API_KEY or load from a .env file:\n",
"import dotenv\n",
"\n",
"dotenv.load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's initialize the chat model which will serve as the chatbot's brain:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"\n",
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\", temperature=0.2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we invoke our chat model, the output is an `AIMessage`:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"J'adore programmer.\")"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"chat.invoke(\n",
" [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French: I love programming.\"\n",
" )\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The model on its own does not have any concept of state. For example, if you ask a followup question:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='I said, \"What did you just say?\"')"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat.invoke([HumanMessage(content=\"What did you just say?\")])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that it doesn't take the previous conversation turn into context, and cannot answer the question.\n",
"\n",
"To get around this, we need to pass the entire conversation history into the model. Let's see what happens when we do that:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='I said \"J\\'adore la programmation,\" which means \"I love programming\" in French.')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import AIMessage\n",
"\n",
"chat.invoke(\n",
" [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French: I love programming.\"\n",
" ),\n",
" AIMessage(content=\"J'adore la programmation.\"),\n",
" HumanMessage(content=\"What did you just say?\"),\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now we can see that we get a good response!\n",
"\n",
"This is the basic idea underpinning a chatbot's ability to interact conversationally.\n",
"\n",
"## Prompt templates\n",
"\n",
"Let's define a prompt template to make formatting a bit easier. We can create a chain by piping it into the model:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. Answer all questions to the best of your ability.\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
")\n",
"\n",
"chain = prompt | chat"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `MessagesPlaceholder` above inserts chat messages passed into the chain's input as `chat_history` directly into the prompt. Then, we can invoke the chain like this:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='I said \"J\\'adore la programmation,\" which means \"I love programming\" in French.')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French: I love programming.\"\n",
" ),\n",
" AIMessage(content=\"J'adore la programmation.\"),\n",
" HumanMessage(content=\"What did you just say?\"),\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Message history\n",
"\n",
"As a shortcut for managing the chat history, we can use a [`MessageHistory`](/docs/modules/memory/chat_messages/) class, which is responsible for saving and loading chat messages. There are many built-in message history integrations that persist messages to a variety of databases, but for this quickstart we'll use a in-memory, demo message history called `ChatMessageHistory`.\n",
"\n",
"Here's an example of using it directly:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content='hi!'), AIMessage(content='whats up?')]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.memory import ChatMessageHistory\n",
"\n",
"demo_ephemeral_chat_history = ChatMessageHistory()\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\"hi!\")\n",
"\n",
"demo_ephemeral_chat_history.add_ai_message(\"whats up?\")\n",
"\n",
"demo_ephemeral_chat_history.messages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once we do that, we can pass the stored messages directly into our chain as a parameter:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='The translation of \"I love programming\" in French is \"J\\'adore la programmation.\"')"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.add_user_message(\n",
" \"Translate this sentence from English to French: I love programming.\"\n",
")\n",
"\n",
"response = chain.invoke({\"messages\": demo_ephemeral_chat_history.messages})\n",
"\n",
"response"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='I said \"J\\'adore la programmation,\" which is the French translation for \"I love programming.\"')"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.add_ai_message(response)\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\"What did you just say?\")\n",
"\n",
"chain.invoke({\"messages\": demo_ephemeral_chat_history.messages})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now we have a basic chatbot!\n",
"\n",
"While this chain can serve as a useful chatbot on its own with just the model's internal knowledge, it's often useful to introduce some form of `retrieval-augmented generation`, or RAG for short, over domain-specific knowledge to make our chatbot more focused. We'll cover this next.\n",
"\n",
"## Retrievers\n",
"\n",
"We can set up and use a [`Retriever`](/docs/modules/data_connection/retrievers/) to pull domain-specific knowledge for our chatbot. To show this, let's expand the simple chatbot we created above to be able to answer questions about LangSmith.\n",
"\n",
"We'll use [the LangSmith documentation](https://docs.smith.langchain.com/overview) as source material and store it in a vectorstore for later retrieval. Note that this example will gloss over some of the specifics around parsing and storing a data source - you can see more [in-depth documentation on creating retrieval systems here](https://python.langchain.com/docs/use_cases/question_answering/).\n",
"\n",
"Let's set up our retriever. First, we'll install some required deps:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 22.0.4; however, version 23.3.2 is available.\n",
"You should consider upgrading via the '/Users/jacoblee/.pyenv/versions/3.10.5/bin/python -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n",
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip install --upgrade --quiet chromadb beautifulsoup4"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we'll use a document loader to pull data from a webpage:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.document_loaders import WebBaseLoader\n",
"\n",
"loader = WebBaseLoader(\"https://docs.smith.langchain.com/overview\")\n",
"data = loader.load()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we split it into smaller chunks that the LLM's context window can handle and store it in a vector database:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"\n",
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)\n",
"all_splits = text_splitter.split_documents(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we embed and store those chunks in a vector database:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.vectorstores import Chroma\n",
"from langchain_openai import OpenAIEmbeddings\n",
"\n",
"vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And finally, let's create a retriever from our initialized vectorstore:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='inputs, and see what happens. At some point though, our application is performing\\nwell and we want to be more rigorous about testing changes. We can use a dataset\\nthat weve constructed along the way (see above). Alternatively, we could spend some\\ntime constructing a small dataset by hand. For these situations, LangSmith simplifies', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='have been building and using LangSmith with the goal of bridging this gap. This is our tactical user guide to outline effective ways to use LangSmith and maximize its benefits.On by default\\u200bAt LangChain, all of us have LangSmiths tracing running in the background by default. On the Python side, this is achieved by setting environment variables, which we establish whenever we launch a virtual environment or open our bash shell and leave them set. The same principle applies to most JavaScript', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# k is the number of chunks to retrieve\n",
"retriever = vectorstore.as_retriever(k=4)\n",
"\n",
"docs = retriever.invoke(\"how can langsmith help with testing?\")\n",
"\n",
"docs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that invoking the retriever above results in some parts of the LangSmith docs that contain information about testing that our chatbot can use as context when answering questions.\n",
"\n",
"### Handling documents\n",
"\n",
"Let's modify our previous prompt to accept documents as context. We'll use a `create_stuff_documents_chain` helper function to \"stuff\" all of the input documents into the prompt, which also conveniently handles formatting. Other arguments (like `messages`) will be passed directly through into the prompt:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains.combine_documents import create_stuff_documents_chain\n",
"\n",
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\")\n",
"\n",
"question_answering_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"Answer the user's questions based on the below context:\\n\\n{context}\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
")\n",
"\n",
"document_chain = create_stuff_documents_chain(chat, question_answering_prompt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can invoke this `document_chain` with the raw documents we retrieved above:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'LangSmith can assist with testing by providing the capability to quickly edit examples and add them to datasets. This allows for the expansion of evaluation sets or fine-tuning of a model for improved quality or reduced costs. Additionally, LangSmith simplifies the construction of small datasets by hand, providing a convenient way to rigorously test changes in the application.'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.memory import ChatMessageHistory\n",
"\n",
"demo_ephemeral_chat_history = ChatMessageHistory()\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\"how can langsmith help with testing?\")\n",
"\n",
"document_chain.invoke(\n",
" {\n",
" \"messages\": demo_ephemeral_chat_history.messages,\n",
" \"context\": docs,\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Awesome! We see an answer synthesized from information in the input documents.\n",
"\n",
"### Creating a retrieval chain\n",
"\n",
"Next, let's integrate our retriever into the chain. Our retriever should retrieve information relevant to the last message we pass in from the user, so we extract it and use that as input to fetch relevant docs, which we add to the current chain as `context`. We pass `context` plus the previous `messages` into our document chain to generate a final answer.\n",
"\n",
"We also use the `RunnablePassthrough.assign()` method to pass intermediate steps through at each invocation. Here's what it looks like:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"from typing import Dict\n",
"\n",
"from langchain_core.runnables import RunnablePassthrough\n",
"\n",
"\n",
"def parse_retriever_input(params: Dict):\n",
" return params[\"messages\"][-1].content\n",
"\n",
"\n",
"retrieval_chain = RunnablePassthrough.assign(\n",
" context=parse_retriever_input | retriever,\n",
").assign(\n",
" answer=document_chain,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='how can langsmith help with testing?')],\n",
" 'context': [Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='inputs, and see what happens. At some point though, our application is performing\\nwell and we want to be more rigorous about testing changes. We can use a dataset\\nthat weve constructed along the way (see above). Alternatively, we could spend some\\ntime constructing a small dataset by hand. For these situations, LangSmith simplifies', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='have been building and using LangSmith with the goal of bridging this gap. This is our tactical user guide to outline effective ways to use LangSmith and maximize its benefits.On by default\\u200bAt LangChain, all of us have LangSmiths tracing running in the background by default. On the Python side, this is achieved by setting environment variables, which we establish whenever we launch a virtual environment or open our bash shell and leave them set. The same principle applies to most JavaScript', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'LangSmith can help with testing in several ways:\\n\\n1. Dataset Expansion: LangSmith enables quick editing of examples and adding them to datasets, which expands the surface area of evaluation sets. This allows for more comprehensive testing of models and applications.\\n\\n2. Fine-Tuning Models: LangSmith facilitates the fine-tuning of models for improved quality or reduced costs. This is beneficial for optimizing the performance of models during testing.\\n\\n3. Monitoring: LangSmith can be used to monitor applications, log traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise during testing. This monitoring helps in ensuring the reliability and performance of the application during testing phases.\\n\\nOverall, LangSmith helps in making testing more rigorous and comprehensive, whether by expanding datasets, fine-tuning models, or monitoring application performance.'}"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response = retrieval_chain.invoke(\n",
" {\n",
" \"messages\": demo_ephemeral_chat_history.messages,\n",
" }\n",
")\n",
"\n",
"response"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='how can langsmith help with testing?'),\n",
" AIMessage(content='LangSmith can help with testing in several ways:\\n\\n1. Dataset Expansion: LangSmith enables quick editing of examples and adding them to datasets, which expands the surface area of evaluation sets. This allows for more comprehensive testing of models and applications.\\n\\n2. Fine-Tuning Models: LangSmith facilitates the fine-tuning of models for improved quality or reduced costs. This is beneficial for optimizing the performance of models during testing.\\n\\n3. Monitoring: LangSmith can be used to monitor applications, log traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise during testing. This monitoring helps in ensuring the reliability and performance of the application during testing phases.\\n\\nOverall, LangSmith helps in making testing more rigorous and comprehensive, whether by expanding datasets, fine-tuning models, or monitoring application performance.'),\n",
" HumanMessage(content='tell me more about that!')],\n",
" 'context': [Document(page_content='however, there is still no complete substitute for human review to get the utmost quality and reliability from your application.', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content=\"against these known issues.Why is this so impactful? When building LLM applications, its often common to start without a dataset of any kind. This is part of the power of LLMs! They are amazing zero-shot learners, making it possible to get started as easily as possible. But this can also be a curse -- as you adjust the prompt, you're wandering blind. You dont have any examples to benchmark your changes against.LangSmith addresses this problem by including an “Add to Dataset” button for each\", metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='playground. Here, you can modify the prompt and re-run it to observe the resulting changes to the output - as many times as needed!Currently, this feature supports only OpenAI and Anthropic models and works for LLM and Chat Model calls. We plan to extend its functionality to more LLM types, chains, agents, and retrievers in the future.What is the exact sequence of events?\\u200bIn complicated chains and agents, it can often be hard to understand what is going on under the hood. What calls are being', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'Certainly! LangSmith offers the following capabilities to aid in testing:\\n\\n1. Dataset Expansion: By allowing quick editing of examples and adding them to datasets, LangSmith enables the expansion of evaluation sets. This is crucial for thorough testing of models and applications, as it broadens the range of scenarios and inputs that can be used to assess performance.\\n\\n2. Fine-Tuning Models: LangSmith supports the fine-tuning of models to enhance their quality and reduce operational costs. This capability is valuable during testing as it enables the optimization of model performance based on specific testing requirements and objectives.\\n\\n3. Monitoring: LangSmith provides monitoring features that allow for the logging of traces, visualization of latency and token usage statistics, and troubleshooting of issues as they occur during testing. This real-time monitoring helps in identifying and addressing any issues that may impact the reliability and performance of the application during testing.\\n\\nBy leveraging these features, LangSmith enhances the testing process by enabling comprehensive dataset expansion, model fine-tuning, and real-time monitoring to ensure the quality and reliability of applications and models.'}"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.add_ai_message(response[\"answer\"])\n",
"\n",
"demo_ephemeral_chat_history.add_user_message(\"tell me more about that!\")\n",
"\n",
"retrieval_chain.invoke(\n",
" {\n",
" \"messages\": demo_ephemeral_chat_history.messages,\n",
" },\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nice! Our chatbot can now answer domain-specific questions in a conversational way.\n",
"\n",
"As an aside, if you don't want to return all the intermediate steps, you can define your retrieval chain like this using a pipe directly into the document chain instead of the final `.assign()` call:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"LangSmith offers the capability to quickly edit examples and add them to datasets, thereby enhancing the scope of evaluation sets. This feature is particularly valuable for testing as it allows for a more thorough assessment of model performance and application behavior.\\n\\nFurthermore, LangSmith enables the fine-tuning of models to enhance quality and reduce costs, which can significantly impact testing outcomes. By adjusting and refining models, developers can ensure that they are thoroughly tested and optimized for various scenarios and use cases.\\n\\nAdditionally, LangSmith provides monitoring functionality, allowing users to log traces, visualize latency and token usage statistics, and troubleshoot specific issues as they encounter them during testing. This real-time monitoring and troubleshooting capability contribute to the overall effectiveness and reliability of the testing process.\\n\\nIn essence, LangSmith's features are designed to improve the quality and reliability of testing by expanding evaluation sets, fine-tuning models, and providing comprehensive monitoring capabilities. These aspects collectively contribute to a more robust and thorough testing process for applications and models.\""
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"retrieval_chain_with_only_answer = (\n",
" RunnablePassthrough.assign(\n",
" context=parse_retriever_input | retriever,\n",
" )\n",
" | document_chain\n",
")\n",
"\n",
"retrieval_chain_with_only_answer.invoke(\n",
" {\n",
" \"messages\": demo_ephemeral_chat_history.messages,\n",
" },\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Query transformation\n",
"\n",
"There's one more optimization we'll cover here - in the above example, when we asked a followup question, `tell me more about that!`, you might notice that the retrieved docs don't directly include information about testing. This is because we're passing `tell me more about that!` verbatim as a query to the retriever. The output in the retrieval chain is still okay because the document chain retrieval chain can generate an answer based on the chat history, but we could be retrieving more rich and informative documents:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='inputs, and see what happens. At some point though, our application is performing\\nwell and we want to be more rigorous about testing changes. We can use a dataset\\nthat weve constructed along the way (see above). Alternatively, we could spend some\\ntime constructing a small dataset by hand. For these situations, LangSmith simplifies', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='have been building and using LangSmith with the goal of bridging this gap. This is our tactical user guide to outline effective ways to use LangSmith and maximize its benefits.On by default\\u200bAt LangChain, all of us have LangSmiths tracing running in the background by default. On the Python side, this is achieved by setting environment variables, which we establish whenever we launch a virtual environment or open our bash shell and leave them set. The same principle applies to most JavaScript', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})]"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"retriever.invoke(\"how can langsmith help with testing?\")"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Document(page_content='however, there is still no complete substitute for human review to get the utmost quality and reliability from your application.', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content=\"against these known issues.Why is this so impactful? When building LLM applications, its often common to start without a dataset of any kind. This is part of the power of LLMs! They are amazing zero-shot learners, making it possible to get started as easily as possible. But this can also be a curse -- as you adjust the prompt, you're wandering blind. You dont have any examples to benchmark your changes against.LangSmith addresses this problem by including an “Add to Dataset” button for each\", metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='playground. Here, you can modify the prompt and re-run it to observe the resulting changes to the output - as many times as needed!Currently, this feature supports only OpenAI and Anthropic models and works for LLM and Chat Model calls. We plan to extend its functionality to more LLM types, chains, agents, and retrievers in the future.What is the exact sequence of events?\\u200bIn complicated chains and agents, it can often be hard to understand what is going on under the hood. What calls are being', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"retriever.invoke(\"tell me more about that!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get around this common problem, let's add a `query transformation` step that removes references from the input. We'll wrap our old retriever as follows:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.output_parsers import StrOutputParser\n",
"from langchain_core.runnables import RunnableBranch\n",
"\n",
"# We need a prompt that we can pass into an LLM to generate a transformed search query\n",
"\n",
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\", temperature=0.2)\n",
"\n",
"query_transform_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" (\n",
" \"user\",\n",
" \"Given the above conversation, generate a search query to look up in order to get information relevant to the conversation. Only respond with the query, nothing else.\",\n",
" ),\n",
" ]\n",
")\n",
"\n",
"query_transforming_retriever_chain = RunnableBranch(\n",
" (\n",
" lambda x: len(x.get(\"messages\", [])) == 1,\n",
" # If only one message, then we just pass that message's content to retriever\n",
" (lambda x: x[\"messages\"][-1].content) | retriever,\n",
" ),\n",
" # If messages, then we pass inputs to LLM chain to transform the query, then pass to retriever\n",
" query_transform_prompt | chat | StrOutputParser() | retriever,\n",
").with_config(run_name=\"chat_retriever_chain\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's recreate our earlier chain with this new `query_transforming_retriever_chain`. Note that this new chain accepts a dict as input and parses a string to pass to the retriever, so we don't have to do additional parsing at the top level:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"document_chain = create_stuff_documents_chain(chat, question_answering_prompt)\n",
"\n",
"conversational_retrieval_chain = RunnablePassthrough.assign(\n",
" context=query_transforming_retriever_chain,\n",
").assign(\n",
" answer=document_chain,\n",
")\n",
"\n",
"demo_ephemeral_chat_history = ChatMessageHistory()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And finally, let's invoke it!"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='how can langsmith help with testing?'),\n",
" AIMessage(content='LangSmith can assist with testing in several ways. It allows you to quickly edit examples and add them to datasets, expanding the range of evaluation sets. This can help in fine-tuning a model for improved quality or reduced costs. Additionally, LangSmith simplifies the construction of small datasets by hand, providing a convenient way to rigorously test changes in your application. Furthermore, it enables monitoring of your application by logging all traces, visualizing latency and token usage statistics, and troubleshooting specific issues as they arise.')],\n",
" 'context': [Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='inputs, and see what happens. At some point though, our application is performing\\nwell and we want to be more rigorous about testing changes. We can use a dataset\\nthat weve constructed along the way (see above). Alternatively, we could spend some\\ntime constructing a small dataset by hand. For these situations, LangSmith simplifies', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='have been building and using LangSmith with the goal of bridging this gap. This is our tactical user guide to outline effective ways to use LangSmith and maximize its benefits.On by default\\u200bAt LangChain, all of us have LangSmiths tracing running in the background by default. On the Python side, this is achieved by setting environment variables, which we establish whenever we launch a virtual environment or open our bash shell and leave them set. The same principle applies to most JavaScript', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'LangSmith can assist with testing in several ways. It allows you to quickly edit examples and add them to datasets, expanding the range of evaluation sets. This can help in fine-tuning a model for improved quality or reduced costs. Additionally, LangSmith simplifies the construction of small datasets by hand, providing a convenient way to rigorously test changes in your application. Furthermore, it enables monitoring of your application by logging all traces, visualizing latency and token usage statistics, and troubleshooting specific issues as they arise.'}"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.add_user_message(\"how can langsmith help with testing?\")\n",
"\n",
"response = conversational_retrieval_chain.invoke(\n",
" {\"messages\": demo_ephemeral_chat_history.messages},\n",
")\n",
"\n",
"demo_ephemeral_chat_history.add_ai_message(response[\"answer\"])\n",
"\n",
"response"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='how can langsmith help with testing?'),\n",
" AIMessage(content='LangSmith can assist with testing in several ways. It allows you to quickly edit examples and add them to datasets, expanding the range of evaluation sets. This can help in fine-tuning a model for improved quality or reduced costs. Additionally, LangSmith simplifies the construction of small datasets by hand, providing a convenient way to rigorously test changes in your application. Furthermore, it enables monitoring of your application by logging all traces, visualizing latency and token usage statistics, and troubleshooting specific issues as they arise.'),\n",
" HumanMessage(content='tell me more about that!')],\n",
" 'context': [Document(page_content='LangSmith Overview and User Guide | 🦜️🛠️ LangSmith', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='inputs, and see what happens. At some point though, our application is performing\\nwell and we want to be more rigorous about testing changes. We can use a dataset\\nthat weve constructed along the way (see above). Alternatively, we could spend some\\ntime constructing a small dataset by hand. For these situations, LangSmith simplifies', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'Certainly! LangSmith simplifies the process of constructing and editing datasets, which is essential for testing and fine-tuning models. By quickly editing examples and adding them to datasets, you can expand the surface area of your evaluation sets, leading to improved model quality and potentially reduced costs. Additionally, LangSmith provides monitoring capabilities for your application, allowing you to log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. This comprehensive monitoring functionality helps ensure the reliability and performance of your application in production.'}"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo_ephemeral_chat_history.add_user_message(\"tell me more about that!\")\n",
"\n",
"conversational_retrieval_chain.invoke(\n",
" {\"messages\": demo_ephemeral_chat_history.messages}\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To help you understand what's happening internally, [this LangSmith trace](https://smith.langchain.com/public/42f8993b-7d19-42d3-990a-6608a73c5824/r) shows the first invocation. You can see that the user's initial query is passed directly to the retriever, which return suitable docs.\n",
"\n",
"The invocation for followup question, [illustrated by this LangSmith trace](https://smith.langchain.com/public/7b463791-868b-42bd-8035-17b471e9c7cd/r) rephrases the user's initial question to something more relevant to testing with LangSmith, resulting in higher quality docs.\n",
"\n",
"And we now have a chatbot capable of conversational retrieval!\n",
"\n",
"## Next steps\n",
"\n",
"You now know how to build a conversational chatbot that can integrate past messages and domain-specific knowledge into its generations. There are many other optimizations you can make around this - check out the following pages for more information:\n",
"\n",
"- [Memory management](/docs/use_cases/chatbots/memory_management): This includes a guide on automatically updating chat history, as well as trimming, summarizing, or otherwise modifying long conversations to keep your bot focused.\n",
"- [Retrieval](/docs/use_cases/chatbots/retrieval): A deeper dive into using different types of retrieval with your chatbot\n",
"- [Tool usage](/docs/use_cases/chatbots/tool_usage): How to allows your chatbots to use tools that interact with other APIs and systems."
]
}
],
"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.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,765 @@
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"---\n",
"sidebar_position: 2\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Retrieval\n",
"\n",
"Retrieval is a common technique chatbots use to augment their responses with data outside a chat model's training data. This section will cover how to implement retrieval in the context of chatbots, but it's worth noting that retrieval is a very subtle and deep topic - we encourage you to explore [other parts of the documentation](/docs/use_cases/question_answering/) that go into greater depth!\n",
"\n",
"## Setup\n",
"\n",
"You'll need to install a few packages, and have your OpenAI API key set as an environment variable named `OPENAI_API_KEY`:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 22.0.4; however, version 23.3.2 is available.\n",
"You should consider upgrading via the '/Users/jacoblee/.pyenv/versions/3.10.5/bin/python -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n",
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%pip install --upgrade --quiet langchain langchain-openai chromadb beautifulsoup4\n",
"\n",
"# Set env var OPENAI_API_KEY or load from a .env file:\n",
"import dotenv\n",
"\n",
"dotenv.load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's also set up a chat model that we'll use for the below examples."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"\n",
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\", temperature=0.2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Creating a retriever\n",
"\n",
"We'll use [the LangSmith documentation](https://docs.smith.langchain.com/overview) as source material and store the content in a vectorstore for later retrieval. Note that this example will gloss over some of the specifics around parsing and storing a data source - you can see more [in-depth documentation on creating retrieval systems here](https://python.langchain.com/docs/use_cases/question_answering/).\n",
"\n",
"Let's use a document loader to pull text from the docs:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.document_loaders import WebBaseLoader\n",
"\n",
"loader = WebBaseLoader(\"https://docs.smith.langchain.com/overview\")\n",
"data = loader.load()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we split it into smaller chunks that the LLM's context window can handle and store it in a vector database:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"\n",
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)\n",
"all_splits = text_splitter.split_documents(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we embed and store those chunks in a vector database:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.vectorstores import Chroma\n",
"from langchain_openai import OpenAIEmbeddings\n",
"\n",
"vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And finally, let's create a retriever from our initialized vectorstore:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='LangSmith Overview and User Guide | 🦜️🛠️ LangSmith', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content=\"does that affect the output?\\u200bSo you notice a bad output, and you go into LangSmith to see what's going on. You find the faulty LLM call and are now looking at the exact input. You want to try changing a word or a phrase to see what happens -- what do you do?We constantly ran into this issue. Initially, we copied the prompt to a playground of sorts. But this got annoying, so we built a playground of our own! When examining an LLM call, you can click the Open in Playground button to access this\", metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# k is the number of chunks to retrieve\n",
"retriever = vectorstore.as_retriever(k=4)\n",
"\n",
"docs = retriever.invoke(\"Can LangSmith help test my LLM applications?\")\n",
"\n",
"docs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that invoking the retriever above results in some parts of the LangSmith docs that contain information about testing that our chatbot can use as context when answering questions. And now we've got a retriever that can return related data from the LangSmith docs!\n",
"\n",
"## Document chains\n",
"\n",
"Now that we have a retriever that can return LangChain docs, let's create a chain that can use them as context to answer questions. We'll use a `create_stuff_documents_chain` helper function to \"stuff\" all of the input documents into the prompt. It will also handle formatting the docs as strings.\n",
"\n",
"In addition to a chat model, the function also expects a prompt that has a `context` variables, as well as a placeholder for chat history messages named `messages`. We'll create an appropriate prompt and pass it as shown below:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains.combine_documents import create_stuff_documents_chain\n",
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"\n",
"SYSTEM_TEMPLATE = \"\"\"\n",
"Answer the user's questions based on the below context. \n",
"If the context doesn't contain any relevant information to the question, don't make something up and just say \"I don't know\":\n",
"\n",
"<context>\n",
"{context}\n",
"</context>\n",
"\"\"\"\n",
"\n",
"question_answering_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" SYSTEM_TEMPLATE,\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
")\n",
"\n",
"document_chain = create_stuff_documents_chain(chat, question_answering_prompt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can invoke this `document_chain` by itself to answer questions. Let's use the docs we retrieved above and the same question, `how can langsmith help with testing?`:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Yes, LangSmith can help test and evaluate your LLM applications. It simplifies the initial setup, and you can use it to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.'"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"document_chain.invoke(\n",
" {\n",
" \"context\": docs,\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\")\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks good! For comparison, we can try it with no context docs and compare the result:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"I don't know about LangSmith's specific capabilities for testing LLM applications. It's best to reach out to LangSmith directly to inquire about their services and how they can assist with testing your LLM applications.\""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"document_chain.invoke(\n",
" {\n",
" \"context\": [],\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\")\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that the LLM does not return any results.\n",
"\n",
"## Retrieval chains\n",
"\n",
"Let's combine this document chain with the retriever. Here's one way this can look:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"from typing import Dict\n",
"\n",
"from langchain_core.runnables import RunnablePassthrough\n",
"\n",
"\n",
"def parse_retriever_input(params: Dict):\n",
" return params[\"messages\"][-1].content\n",
"\n",
"\n",
"retrieval_chain = RunnablePassthrough.assign(\n",
" context=parse_retriever_input | retriever,\n",
").assign(\n",
" answer=document_chain,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Given a list of input messages, we extract the content of the last message in the list and pass that to the retriever to fetch some documents. Then, we pass those documents as context to our document chain to generate a final response.\n",
"\n",
"Invoking this chain combines both steps outlined above:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='Can LangSmith help test my LLM applications?')],\n",
" 'context': [Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='LangSmith Overview and User Guide | 🦜️🛠️ LangSmith', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content=\"does that affect the output?\\u200bSo you notice a bad output, and you go into LangSmith to see what's going on. You find the faulty LLM call and are now looking at the exact input. You want to try changing a word or a phrase to see what happens -- what do you do?We constantly ran into this issue. Initially, we copied the prompt to a playground of sorts. But this got annoying, so we built a playground of our own! When examining an LLM call, you can click the Open in Playground button to access this\", metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'Yes, LangSmith can help test and evaluate your LLM applications. It simplifies the initial setup, and you can use it to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.'}"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"retrieval_chain.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\")\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks good!\n",
"\n",
"## Query transformation\n",
"\n",
"Our retrieval chain is capable of answering questions about LangSmith, but there's a problem - chatbots interact with users conversationally, and therefore have to deal with followup questions.\n",
"\n",
"The chain in its current form will struggle with this. Consider a followup question to our original question like `Tell me more!`. If we invoke our retriever with that query directly, we get documents irrelevant to LLM application testing:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='playground. Here, you can modify the prompt and re-run it to observe the resulting changes to the output - as many times as needed!Currently, this feature supports only OpenAI and Anthropic models and works for LLM and Chat Model calls. We plan to extend its functionality to more LLM types, chains, agents, and retrievers in the future.What is the exact sequence of events?\\u200bIn complicated chains and agents, it can often be hard to understand what is going on under the hood. What calls are being', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='however, there is still no complete substitute for human review to get the utmost quality and reliability from your application.', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"retriever.invoke(\"Tell me more!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is because the retriever has no innate concept of state, and will only pull documents most similar to the query given. To solve this, we can transform the query into a standalone query without any external references an LLM.\n",
"\n",
"Here's an example:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='\"LangSmith LLM application testing and evaluation\"')"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import AIMessage, HumanMessage\n",
"\n",
"query_transform_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" (\n",
" \"user\",\n",
" \"Given the above conversation, generate a search query to look up in order to get information relevant to the conversation. Only respond with the query, nothing else.\",\n",
" ),\n",
" ]\n",
")\n",
"\n",
"query_transformation_chain = query_transform_prompt | chat\n",
"\n",
"query_transformation_chain.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\"),\n",
" AIMessage(\n",
" content=\"Yes, LangSmith can help test and evaluate your LLM applications. It allows you to quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs. Additionally, LangSmith can be used to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.\"\n",
" ),\n",
" HumanMessage(content=\"Tell me more!\"),\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Awesome! That transformed query would pull up context documents related to LLM application testing.\n",
"\n",
"Let's add this to our retrieval chain. We can wrap our retriever as follows:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.output_parsers import StrOutputParser\n",
"from langchain_core.runnables import RunnableBranch\n",
"\n",
"query_transforming_retriever_chain = RunnableBranch(\n",
" (\n",
" lambda x: len(x.get(\"messages\", [])) == 1,\n",
" # If only one message, then we just pass that message's content to retriever\n",
" (lambda x: x[\"messages\"][-1].content) | retriever,\n",
" ),\n",
" # If messages, then we pass inputs to LLM chain to transform the query, then pass to retriever\n",
" query_transform_prompt | chat | StrOutputParser() | retriever,\n",
").with_config(run_name=\"chat_retriever_chain\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, we can use this query transformation chain to make our retrieval chain better able to handle such followup questions:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"SYSTEM_TEMPLATE = \"\"\"\n",
"Answer the user's questions based on the below context. \n",
"If the context doesn't contain any relevant information to the question, don't make something up and just say \"I don't know\":\n",
"\n",
"<context>\n",
"{context}\n",
"</context>\n",
"\"\"\"\n",
"\n",
"question_answering_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" SYSTEM_TEMPLATE,\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
")\n",
"\n",
"document_chain = create_stuff_documents_chain(chat, question_answering_prompt)\n",
"\n",
"conversational_retrieval_chain = RunnablePassthrough.assign(\n",
" context=query_transforming_retriever_chain,\n",
").assign(\n",
" answer=document_chain,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Awesome! Let's invoke this new chain with the same inputs as earlier:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='Can LangSmith help test my LLM applications?')],\n",
" 'context': [Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='LangSmith Overview and User Guide | 🦜️🛠️ LangSmith', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content=\"does that affect the output?\\u200bSo you notice a bad output, and you go into LangSmith to see what's going on. You find the faulty LLM call and are now looking at the exact input. You want to try changing a word or a phrase to see what happens -- what do you do?We constantly ran into this issue. Initially, we copied the prompt to a playground of sorts. But this got annoying, so we built a playground of our own! When examining an LLM call, you can click the Open in Playground button to access this\", metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'Yes, LangSmith can help test and evaluate LLM (Language Model) applications. It simplifies the initial setup, and you can use it to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.'}"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversational_retrieval_chain.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\"),\n",
" ]\n",
" }\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='Can LangSmith help test my LLM applications?'),\n",
" AIMessage(content='Yes, LangSmith can help test and evaluate your LLM applications. It allows you to quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs. Additionally, LangSmith can be used to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.'),\n",
" HumanMessage(content='Tell me more!')],\n",
" 'context': [Document(page_content='LangSmith Overview and User Guide | 🦜️🛠️ LangSmith', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}),\n",
" Document(page_content='LangSmith makes it easy to manually review and annotate runs through annotation queues.These queues allow you to select any runs based on criteria like model type or automatic evaluation scores, and queue them up for human review. As a reviewer, you can then quickly step through the runs, viewing the input, output, and any existing tags before adding your own feedback.We often use this for a couple of reasons:To assess subjective qualities that automatic evaluators struggle with, like', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})],\n",
" 'answer': 'LangSmith simplifies the initial setup for building reliable LLM applications, but it acknowledges that there is still work needed to bring the performance of prompts, chains, and agents up to the level where they are reliable enough to be used in production. It also provides the capability to manually review and annotate runs through annotation queues, allowing you to select runs based on criteria like model type or automatic evaluation scores for human review. This feature is particularly useful for assessing subjective qualities that automatic evaluators struggle with.'}"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversational_retrieval_chain.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\"),\n",
" AIMessage(\n",
" content=\"Yes, LangSmith can help test and evaluate your LLM applications. It allows you to quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs. Additionally, LangSmith can be used to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.\"\n",
" ),\n",
" HumanMessage(content=\"Tell me more!\"),\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can check out [this LangSmith trace](https://smith.langchain.com/public/bb329a3b-e92a-4063-ad78-43f720fbb5a2/r) to see the internal query transformation step for yourself.\n",
"\n",
"## Streaming\n",
"\n",
"Because this chain is constructed with LCEL, you can use familiar methods like `.stream()` with it:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'messages': [HumanMessage(content='Can LangSmith help test my LLM applications?'), AIMessage(content='Yes, LangSmith can help test and evaluate your LLM applications. It allows you to quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs. Additionally, LangSmith can be used to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.'), HumanMessage(content='Tell me more!')]}\n",
"{'context': [Document(page_content='LangSmith Overview and User Guide | 🦜️🛠️ LangSmith', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}), Document(page_content='You can also quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs.Monitoring\\u200bAfter all this, your app might finally ready to go in production. LangSmith can also be used to monitor your application in much the same way that you used for debugging. You can log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise. Each run can also be', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}), Document(page_content='Skip to main content🦜🛠 LangSmith DocsPython DocsJS/TS DocsSearchGo to AppLangSmithOverviewTracingTesting & EvaluationOrganizationsHubLangSmith CookbookOverviewOn this pageLangSmith Overview and User GuideBuilding reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.Over the past two months, we at LangChain', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'}), Document(page_content='LangSmith makes it easy to manually review and annotate runs through annotation queues.These queues allow you to select any runs based on criteria like model type or automatic evaluation scores, and queue them up for human review. As a reviewer, you can then quickly step through the runs, viewing the input, output, and any existing tags before adding your own feedback.We often use this for a couple of reasons:To assess subjective qualities that automatic evaluators struggle with, like', metadata={'description': 'Building reliable LLM applications can be challenging. LangChain simplifies the initial setup, but there is still work needed to bring the performance of prompts, chains and agents up the level where they are reliable enough to be used in production.', 'language': 'en', 'source': 'https://docs.smith.langchain.com/overview', 'title': 'LangSmith Overview and User Guide | 🦜️🛠️ LangSmith'})]}\n",
"{'answer': ''}\n",
"{'answer': 'Lang'}\n",
"{'answer': 'Smith'}\n",
"{'answer': ' simpl'}\n",
"{'answer': 'ifies'}\n",
"{'answer': ' the'}\n",
"{'answer': ' initial'}\n",
"{'answer': ' setup'}\n",
"{'answer': ' for'}\n",
"{'answer': ' building'}\n",
"{'answer': ' reliable'}\n",
"{'answer': ' L'}\n",
"{'answer': 'LM'}\n",
"{'answer': ' applications'}\n",
"{'answer': '.'}\n",
"{'answer': ' It'}\n",
"{'answer': ' provides'}\n",
"{'answer': ' features'}\n",
"{'answer': ' for'}\n",
"{'answer': ' manually'}\n",
"{'answer': ' reviewing'}\n",
"{'answer': ' and'}\n",
"{'answer': ' annot'}\n",
"{'answer': 'ating'}\n",
"{'answer': ' runs'}\n",
"{'answer': ' through'}\n",
"{'answer': ' annotation'}\n",
"{'answer': ' queues'}\n",
"{'answer': ','}\n",
"{'answer': ' allowing'}\n",
"{'answer': ' you'}\n",
"{'answer': ' to'}\n",
"{'answer': ' select'}\n",
"{'answer': ' runs'}\n",
"{'answer': ' based'}\n",
"{'answer': ' on'}\n",
"{'answer': ' criteria'}\n",
"{'answer': ' like'}\n",
"{'answer': ' model'}\n",
"{'answer': ' type'}\n",
"{'answer': ' or'}\n",
"{'answer': ' automatic'}\n",
"{'answer': ' evaluation'}\n",
"{'answer': ' scores'}\n",
"{'answer': ','}\n",
"{'answer': ' and'}\n",
"{'answer': ' queue'}\n",
"{'answer': ' them'}\n",
"{'answer': ' up'}\n",
"{'answer': ' for'}\n",
"{'answer': ' human'}\n",
"{'answer': ' review'}\n",
"{'answer': '.'}\n",
"{'answer': ' As'}\n",
"{'answer': ' a'}\n",
"{'answer': ' reviewer'}\n",
"{'answer': ','}\n",
"{'answer': ' you'}\n",
"{'answer': ' can'}\n",
"{'answer': ' quickly'}\n",
"{'answer': ' step'}\n",
"{'answer': ' through'}\n",
"{'answer': ' the'}\n",
"{'answer': ' runs'}\n",
"{'answer': ','}\n",
"{'answer': ' view'}\n",
"{'answer': ' the'}\n",
"{'answer': ' input'}\n",
"{'answer': ','}\n",
"{'answer': ' output'}\n",
"{'answer': ','}\n",
"{'answer': ' and'}\n",
"{'answer': ' any'}\n",
"{'answer': ' existing'}\n",
"{'answer': ' tags'}\n",
"{'answer': ' before'}\n",
"{'answer': ' adding'}\n",
"{'answer': ' your'}\n",
"{'answer': ' own'}\n",
"{'answer': ' feedback'}\n",
"{'answer': '.'}\n",
"{'answer': ' This'}\n",
"{'answer': ' can'}\n",
"{'answer': ' be'}\n",
"{'answer': ' particularly'}\n",
"{'answer': ' useful'}\n",
"{'answer': ' for'}\n",
"{'answer': ' assessing'}\n",
"{'answer': ' subjective'}\n",
"{'answer': ' qualities'}\n",
"{'answer': ' that'}\n",
"{'answer': ' automatic'}\n",
"{'answer': ' evalu'}\n",
"{'answer': 'ators'}\n",
"{'answer': ' struggle'}\n",
"{'answer': ' with'}\n",
"{'answer': '.'}\n",
"{'answer': ''}\n"
]
}
],
"source": [
"stream = conversational_retrieval_chain.stream(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(content=\"Can LangSmith help test my LLM applications?\"),\n",
" AIMessage(\n",
" content=\"Yes, LangSmith can help test and evaluate your LLM applications. It allows you to quickly edit examples and add them to datasets to expand the surface area of your evaluation sets or to fine-tune a model for improved quality or reduced costs. Additionally, LangSmith can be used to monitor your application, log all traces, visualize latency and token usage statistics, and troubleshoot specific issues as they arise.\"\n",
" ),\n",
" HumanMessage(content=\"Tell me more!\"),\n",
" ],\n",
" }\n",
")\n",
"\n",
"for chunk in stream:\n",
" print(chunk)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Further reading\n",
"\n",
"This guide only scratches the surface of retrieval techniques. For more on different ways of ingesting, preparing, and retrieving the most relevant data, check out [this section](/docs/modules/data_connection/) of the docs."
]
}
],
"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.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,465 @@
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"---\n",
"sidebar_position: 3\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tool usage\n",
"\n",
"This section will cover how to create conversational agents: chatbots that can interact with other systems and APIs using tools.\n",
"\n",
"Before reading this guide, we recommend you read both [the chatbot quickstart](/docs/use_cases/chatbots/quickstart) in this section and be familiar with [the documentation on agents](/docs/modules/agents/).\n",
"\n",
"## Setup\n",
"\n",
"For this guide, we'll be using an [OpenAI tools agent](/docs/modules/agents/agent_types/openai_tools) with a single tool for searching the web. The default will be powered by [Tavily](/docs/integrations/tools/tavily_search), but you can switch it out for any similar tool. The rest of this section will assume you're using Tavily.\n",
"\n",
"You'll need to [sign up for an account](https://tavily.com/) on the Tavily website, and install the following packages:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 22.0.4; however, version 23.3.2 is available.\n",
"You should consider upgrading via the '/Users/jacoblee/.pyenv/versions/3.10.5/bin/python -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n",
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%pip install --upgrade --quiet langchain-openai tavily-python\n",
"\n",
"# Set env var OPENAI_API_KEY or load from a .env file:\n",
"import dotenv\n",
"\n",
"dotenv.load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You will also need your OpenAI key set as `OPENAI_API_KEY` and your Tavily API key set as `TAVILY_API_KEY`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Creating an agent\n",
"\n",
"Our end goal is to create an agent that can respond conversationally to user questions while looking up information as needed.\n",
"\n",
"First, let's initialize Tavily and an OpenAI chat model capable of tool calling:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.tools.tavily_search import TavilySearchResults\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"tools = [TavilySearchResults(max_results=1)]\n",
"\n",
"# Choose the LLM that will drive the agent\n",
"# Only certain models support this\n",
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\", temperature=0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To make our agent conversational, we must also choose a prompt with a placeholder for our chat history. Here's an example:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"\n",
"# Adapted from https://smith.langchain.com/hub/hwchase17/openai-tools-agent\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. You may not need to use tools for every query - the user may just want to chat!\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Great! Now let's assemble our agent:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from langchain.agents import AgentExecutor, create_openai_tools_agent\n",
"\n",
"agent = create_openai_tools_agent(chat, tools, prompt)\n",
"\n",
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Running the agent\n",
"\n",
"Now that we've set up our agent, let's try interacting with it! It can handle both trivial queries that require no lookup:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3mHello Nemo! It's great to meet you. How can I assist you today?\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content=\"I'm Nemo!\")],\n",
" 'output': \"Hello Nemo! It's great to meet you. How can I assist you today?\"}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"agent_executor.invoke({\"messages\": [HumanMessage(content=\"I'm Nemo!\")]})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Or, it can use of the passed search tool to get up to date information if needed:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"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: `tavily_search_results_json` with `{'query': 'current conservation status of the Great Barrier Reef'}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m[{'url': 'https://www.barrierreef.org/news/blog/this-is-the-critical-decade-for-coral-reef-survival', 'content': \"global coral reef conservation. © 2024 Great Barrier Reef Foundation. Website by bigfish.tv #Related News · 29 January 2024 290m more baby corals to help restore and protect the Great Barrier Reef Great Barrier Reef Foundation Managing Director Anna Marsden says its not too late if we act now.The Status of Coral Reefs of the World: 2020 report is the largest analysis of global coral reef health ever undertaken. It found that 14 per cent of the world's coral has been lost since 2009. The report also noted, however, that some of these corals recovered during the 10 years to 2019.\"}]\u001b[0m\u001b[32;1m\u001b[1;3mThe current conservation status of the Great Barrier Reef is a critical concern. According to the Great Barrier Reef Foundation, the Status of Coral Reefs of the World: 2020 report found that 14% of the world's coral has been lost since 2009. However, the report also noted that some of these corals recovered during the 10 years to 2019. For more information, you can visit the following link: [Great Barrier Reef Foundation - Conservation Status](https://www.barrierreef.org/news/blog/this-is-the-critical-decade-for-coral-reef-survival)\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='What is the current conservation status of the Great Barrier Reef?')],\n",
" 'output': \"The current conservation status of the Great Barrier Reef is a critical concern. According to the Great Barrier Reef Foundation, the Status of Coral Reefs of the World: 2020 report found that 14% of the world's coral has been lost since 2009. However, the report also noted that some of these corals recovered during the 10 years to 2019. For more information, you can visit the following link: [Great Barrier Reef Foundation - Conservation Status](https://www.barrierreef.org/news/blog/this-is-the-critical-decade-for-coral-reef-survival)\"}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agent_executor.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(\n",
" content=\"What is the current conservation status of the Great Barrier Reef?\"\n",
" )\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conversational responses\n",
"\n",
"Because our prompt contains a placeholder for chat history messages, our agent can also take previous interactions into account and respond conversationally like a standard chatbot:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3mYour name is Nemo!\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content=\"I'm Nemo!\"),\n",
" AIMessage(content='Hello Nemo! How can I assist you today?'),\n",
" HumanMessage(content='What is my name?')],\n",
" 'output': 'Your name is Nemo!'}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import AIMessage, HumanMessage\n",
"\n",
"agent_executor.invoke(\n",
" {\n",
" \"messages\": [\n",
" HumanMessage(content=\"I'm Nemo!\"),\n",
" AIMessage(content=\"Hello Nemo! How can I assist you today?\"),\n",
" HumanMessage(content=\"What is my name?\"),\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If preferred, you can also wrap the agent executor in a `RunnableWithMessageHistory` class to internally manage history messages. First, we need to slightly modify the prompt to take a separate input variable so that the wrapper can parse which input value to store as history:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Adapted from https://smith.langchain.com/hub/hwchase17/openai-tools-agent\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are a helpful assistant. You may not need to use tools for every query - the user may just want to chat!\",\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
" (\"human\", \"{input}\"),\n",
" MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n",
" ]\n",
")\n",
"\n",
"agent = create_openai_tools_agent(chat, tools, prompt)\n",
"\n",
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, because our agent executor has multiple outputs, we also have to set the `output_messages_key` property when initializing the wrapper:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"from langchain.memory import ChatMessageHistory\n",
"from langchain_core.runnables.history import RunnableWithMessageHistory\n",
"\n",
"demo_ephemeral_chat_history_for_chain = ChatMessageHistory()\n",
"\n",
"conversational_agent_executor = RunnableWithMessageHistory(\n",
" agent_executor,\n",
" lambda session_id: demo_ephemeral_chat_history_for_chain,\n",
" input_messages_key=\"input\",\n",
" output_messages_key=\"output\",\n",
" history_messages_key=\"chat_history\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3mHi Nemo! It's great to meet you. How can I assist you today?\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': \"I'm Nemo!\",\n",
" 'chat_history': [],\n",
" 'output': \"Hi Nemo! It's great to meet you. How can I assist you today?\"}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversational_agent_executor.invoke(\n",
" {\n",
" \"input\": \"I'm Nemo!\",\n",
" },\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3mYour name is Nemo! How can I assist you today, Nemo?\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': 'What is my name?',\n",
" 'chat_history': [HumanMessage(content=\"I'm Nemo!\"),\n",
" AIMessage(content=\"Hi Nemo! It's great to meet you. How can I assist you today?\")],\n",
" 'output': 'Your name is Nemo! How can I assist you today, Nemo?'}"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conversational_agent_executor.invoke(\n",
" {\n",
" \"input\": \"What is my name?\",\n",
" },\n",
" {\"configurable\": {\"session_id\": \"unused\"}},\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Further reading\n",
"\n",
"Other types agents can also support conversational responses too - for more, check out the [agents section](/docs/modules/agents).\n",
"\n",
"For more on tool usage, you can also check out [this use case section](/docs/use_cases/tool_use/)."
]
}
],
"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.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,781 @@
{
"cells": [
{
"cell_type": "raw",
"id": "d00a802f-a27e-43a5-af1e-500d4bb70859",
"metadata": {},
"source": [
"---\n",
"sidebar_position: 0.3\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "674a0d41-e3e3-4423-a995-25d40128c518",
"metadata": {},
"source": [
"# CSV\n",
"\n",
"LLMs are great for building question-answering systems over various types of data sources. In this section we'll go over how to build Q&A systems over data stored in a CSV file(s). Like working with SQL databases, the key to working with CSV files is to give an LLM access to tools for querying and interacting with the data. The two main ways to do this are to either:\n",
"\n",
"* **RECOMMENDED**: Load the CSV(s) into a SQL database, and use the approaches outlined in the [SQL use case docs](/docs/use_cases/sql/).\n",
"* Give the LLM access to a Python environment where it can use libraries like Pandas to interact with the data.\n",
"\n",
"## ⚠️ Security note ⚠️\n",
"\n",
"Both approaches mentioned above carry significant risks. Using SQL requires executing model-generated SQL queries. Using a library like Pandas requires letting the model execute Python code. Since it is easier to tightly scope SQL connection permissions and sanitize SQL queries than it is to sandbox Python environments, **we HIGHLY recommend interacting with CSV data via SQL.** For more on general security best practices, [see here](/docs/security)."
]
},
{
"cell_type": "markdown",
"id": "d20c20d7-71e1-4808-9012-48278f3a9b94",
"metadata": {},
"source": [
"## Setup\n",
"Dependencies for this guide:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c3fcf245-b0aa-4aee-8f0a-9c9cf94b065e",
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain langchain-openai langchain-community langchain-experimental pandas"
]
},
{
"cell_type": "markdown",
"id": "7f2e34a3-0978-4856-8844-d8dfc6d5ac51",
"metadata": {},
"source": [
"Set required environment variables:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "53913d79-4a11-4bc6-bb49-dea2cc8c453b",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n",
"\n",
"# Using LangSmith is recommended but not required. Uncomment below lines to use.\n",
"# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
"# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()"
]
},
{
"cell_type": "markdown",
"id": "c23b4232-2f6a-4eb5-b0cb-1d48a9e02fcc",
"metadata": {},
"source": [
"Download the [Titanic dataset](https://www.kaggle.com/datasets/yasserh/titanic-dataset) if you don't already have it:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c2c5e524-781c-4b8e-83ec-d302023f8767",
"metadata": {},
"outputs": [],
"source": [
"!wget https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv -O titanic.csv"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "8431551e-e0d7-4702-90e3-12c53161a479",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(887, 8)\n",
"['Survived', 'Pclass', 'Name', 'Sex', 'Age', 'Siblings/Spouses Aboard', 'Parents/Children Aboard', 'Fare']\n"
]
}
],
"source": [
"import pandas as pd\n",
"\n",
"df = pd.read_csv(\"titanic.csv\")\n",
"print(df.shape)\n",
"print(df.columns.tolist())"
]
},
{
"cell_type": "markdown",
"id": "1779ab07-b715-49e5-ab2a-2e6be7d02927",
"metadata": {},
"source": [
"## SQL\n",
"\n",
"Using SQL to interact with CSV data is the recommended approach because it is easier to limit permissions and sanitize queries than with arbitrary Python.\n",
"\n",
"Most SQL databases make it easy to load a CSV file in as a table ([DuckDB](https://duckdb.org/docs/data/csv/overview.html), [SQLite](https://www.sqlite.org/csv.html), etc.). Once you've done this you can use all of the chain and agent-creating techniques outlined in the [SQL use case guide](/docs/use_cases/sql/). Here's a quick example of how we might do this with SQLite:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "f61e9886-4713-4c88-87d4-dab439687f43",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"887"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_community.utilities import SQLDatabase\n",
"from sqlalchemy import create_engine\n",
"\n",
"engine = create_engine(\"sqlite:///titanic.db\")\n",
"df.to_sql(\"titanic\", engine, index=False)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "fa314f1f-d764-41a2-8f27-163cd071c562",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"sqlite\n",
"['titanic']\n"
]
},
{
"data": {
"text/plain": [
"\"[(1, 2, 'Master. Alden Gates Caldwell', 'male', 0.83, 0, 2, 29.0), (0, 3, 'Master. Eino Viljami Panula', 'male', 1.0, 4, 1, 39.6875), (1, 3, 'Miss. Eleanor Ileen Johnson', 'female', 1.0, 1, 1, 11.1333), (1, 2, 'Master. Richard F Becker', 'male', 1.0, 2, 1, 39.0), (1, 1, 'Master. Hudson Trevor Allison', 'male', 0.92, 1, 2, 151.55), (1, 3, 'Miss. Maria Nakid', 'female', 1.0, 0, 2, 15.7417), (0, 3, 'Master. Sidney Leonard Goodwin', 'male', 1.0, 5, 2, 46.9), (1, 3, 'Miss. Helene Barbara Baclini', 'female', 0.75, 2, 1, 19.2583), (1, 3, 'Miss. Eugenie Baclini', 'female', 0.75, 2, 1, 19.2583), (1, 2, 'Master. Viljo Hamalainen', 'male', 0.67, 1, 1, 14.5), (1, 3, 'Master. Bertram Vere Dean', 'male', 1.0, 1, 2, 20.575), (1, 3, 'Master. Assad Alexander Thomas', 'male', 0.42, 0, 1, 8.5167), (1, 2, 'Master. Andre Mallet', 'male', 1.0, 0, 2, 37.0042), (1, 2, 'Master. George Sibley Richards', 'male', 0.83, 1, 1, 18.75)]\""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"db = SQLDatabase(engine=engine)\n",
"print(db.dialect)\n",
"print(db.get_usable_table_names())\n",
"db.run(\"SELECT * FROM titanic WHERE Age < 2;\")"
]
},
{
"cell_type": "markdown",
"id": "42f5a3c3-707c-4331-9f5f-0cb4919763dd",
"metadata": {},
"source": [
"And create a [SQL agent](/docs/use_cases/sql/agents) to interact with it:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "edd92649-b178-47bd-b2b7-d5d4e14b3512",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.agent_toolkits import create_sql_agent\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"llm = ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0)\n",
"agent_executor = create_sql_agent(llm, db=db, agent_type=\"openai-tools\", verbose=True)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "9680e2c0-7957-4dba-9183-9782865176a3",
"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: `sql_db_list_tables` with `{}`\n",
"\n",
"\n",
"\u001b[0m\u001b[38;5;200m\u001b[1;3mtitanic\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `sql_db_schema` with `{'table_names': 'titanic'}`\n",
"\n",
"\n",
"\u001b[0m\u001b[33;1m\u001b[1;3m\n",
"CREATE TABLE titanic (\n",
"\t\"Survived\" BIGINT, \n",
"\t\"Pclass\" BIGINT, \n",
"\t\"Name\" TEXT, \n",
"\t\"Sex\" TEXT, \n",
"\t\"Age\" FLOAT, \n",
"\t\"Siblings/Spouses Aboard\" BIGINT, \n",
"\t\"Parents/Children Aboard\" BIGINT, \n",
"\t\"Fare\" FLOAT\n",
")\n",
"\n",
"/*\n",
"3 rows from titanic table:\n",
"Survived\tPclass\tName\tSex\tAge\tSiblings/Spouses Aboard\tParents/Children Aboard\tFare\n",
"0\t3\tMr. Owen Harris Braund\tmale\t22.0\t1\t0\t7.25\n",
"1\t1\tMrs. John Bradley (Florence Briggs Thayer) Cumings\tfemale\t38.0\t1\t0\t71.2833\n",
"1\t3\tMiss. Laina Heikkinen\tfemale\t26.0\t0\t0\t7.925\n",
"*/\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `sql_db_query` with `{'query': 'SELECT AVG(Age) AS AverageAge FROM titanic WHERE Survived = 1'}`\n",
"responded: To find the average age of survivors, I will query the \"titanic\" table and calculate the average of the \"Age\" column for the rows where \"Survived\" is equal to 1.\n",
"\n",
"Here is the SQL query:\n",
"\n",
"```sql\n",
"SELECT AVG(Age) AS AverageAge\n",
"FROM titanic\n",
"WHERE Survived = 1\n",
"```\n",
"\n",
"Executing this query will give us the average age of the survivors.\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m[(28.408391812865496,)]\u001b[0m\u001b[32;1m\u001b[1;3mThe average age of the survivors is approximately 28.41 years.\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"{'input': \"what's the average age of survivors\",\n",
" 'output': 'The average age of the survivors is approximately 28.41 years.'}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agent_executor.invoke({\"input\": \"what's the average age of survivors\"})"
]
},
{
"cell_type": "markdown",
"id": "4d1eb128-842b-4018-87ab-bb269147f6ec",
"metadata": {},
"source": [
"This approach easily generalizes to multiple CSVs, since we can just load each of them into our database as it's own table. Head to the [SQL guide](/docs/use_cases/sql/) for more."
]
},
{
"cell_type": "markdown",
"id": "fe7f2d91-2377-49dd-97a3-19d48a750715",
"metadata": {},
"source": [
"## Pandas\n",
"\n",
"Instead of SQL we can also use data analysis libraries like pandas and the code generating abilities of LLMs to interact with CSV data. Again, **this approach is not fit for production use cases unless you have extensive safeguards in place**. For this reason, our code-execution utilities and constructors live in the `langchain-experimental` package.\n",
"\n",
"### Chain\n",
"\n",
"Most LLMs have been trained on enough pandas Python code that they can generate it just by being asked to:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "cd02e72d-31bf-4ed3-b4fd-643011dab236",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"```python\n",
"correlation = df['Age'].corr(df['Fare'])\n",
"correlation\n",
"```\n"
]
}
],
"source": [
"ai_msg = llm.invoke(\n",
" \"I have a pandas DataFrame 'df' with columns 'Age' and 'Fare'. Write code to compute the correlation between the two columns. Return Markdown for a Python code snippet and nothing else.\"\n",
")\n",
"print(ai_msg.content)"
]
},
{
"cell_type": "markdown",
"id": "f5e84003-5c39-496b-afa7-eaa50a01b7bb",
"metadata": {},
"source": [
"We can combine this ability with a Python-executing tool to create a simple data analysis chain. We'll first want to load our CSV table as a dataframe, and give the tool access to this dataframe:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "d8132f75-12d4-4294-b446-2d114e603f4f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"32.30542018038331"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"from langchain_core.prompts import ChatPromptTemplate\n",
"from langchain_experimental.tools import PythonAstREPLTool\n",
"\n",
"df = pd.read_csv(\"titanic.csv\")\n",
"tool = PythonAstREPLTool(locals={\"df\": df})\n",
"tool.invoke(\"df['Fare'].mean()\")"
]
},
{
"cell_type": "markdown",
"id": "ab1b2e7c-6ea8-4674-98eb-a43c69f5c19d",
"metadata": {},
"source": [
"To help enforce proper use of our Python tool, we'll using [function calling](/docs/modules/model_io/chat/function_calling):"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "2d30dbca-2d19-4574-bc78-43753f648eb7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_6TZsNaCqOcbP7lqWudosQTd6', 'function': {'arguments': '{\\n \"query\": \"df[[\\'Age\\', \\'Fare\\']].corr()\"\\n}', 'name': 'python_repl_ast'}, 'type': 'function'}]})"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_with_tools = llm.bind_tools([tool], tool_choice=tool.name)\n",
"llm_with_tools.invoke(\n",
" \"I have a dataframe 'df' and want to know the correlation between the 'Age' and 'Fare' columns\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "bdec46fb-7296-443c-9e97-cfa9045ff21d",
"metadata": {},
"source": [
"We'll add a [OpenAI tools output parser](/docs/modules/model_io/output_parsers/types/openai_tools) to extract the function call as a dict:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "f0b658cb-722b-43e8-84ad-62ba8929169a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'query': \"df[['Age', 'Fare']].corr()\"}"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.output_parsers.openai_tools import JsonOutputKeyToolsParser\n",
"\n",
"parser = JsonOutputKeyToolsParser(tool.name, return_single=True)\n",
"(llm_with_tools | parser).invoke(\n",
" \"I have a dataframe 'df' and want to know the correlation between the 'Age' and 'Fare' columns\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "59362ea0-cc5a-4841-b87c-51d6a87d5810",
"metadata": {},
"source": [
"And combine with a prompt so that we can just specify a question without needing to specify the dataframe info every invocation:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "0bd2ecba-90c6-4301-8cc1-bd021a7f74fc",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'query': \"df[['Age', 'Fare']].corr()\"}"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"system = f\"\"\"You have access to a pandas dataframe `df`. \\\n",
"Here is the output of `df.head().to_markdown()`:\n",
"\n",
"```\n",
"{df.head().to_markdown()}\n",
"```\n",
"\n",
"Given a user question, write the Python code to answer it. \\\n",
"Return ONLY the valid Python code and nothing else. \\\n",
"Don't assume you have access to any libraries other than built-in Python ones and pandas.\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", system), (\"human\", \"{question}\")]\n",
")\n",
"code_chain = prompt | llm_with_tools | parser\n",
"code_chain.invoke({\"question\": \"What's the correlation between age and fare\"})"
]
},
{
"cell_type": "markdown",
"id": "63989e47-c0af-409e-9766-83c3fe6d69bb",
"metadata": {},
"source": [
"And lastly we'll add our Python tool so that the generated code is actually executed:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "745b5b2c-2eda-441e-8459-275dc1d4d9aa",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.11232863699941621"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain = prompt | llm_with_tools | parser | tool # noqa\n",
"chain.invoke({\"question\": \"What's the correlation between age and fare\"})"
]
},
{
"cell_type": "markdown",
"id": "fbb12764-4a90-4e84-88b4-a25949084ea2",
"metadata": {},
"source": [
"And just like that we have a simple data analysis chain. We can take a peak at the intermediate steps by looking at the LangSmith trace: https://smith.langchain.com/public/b1309290-7212-49b7-bde2-75b39a32b49a/r\n",
"\n",
"We could add an additional LLM call at the end to generate a conversational response, so that we're not just responding with the tool output. For this we'll want to add a chat history `MessagesPlaceholder` to our prompt:"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "3fe3818d-0657-4729-ac46-ab5d4860d8f6",
"metadata": {},
"outputs": [],
"source": [
"from operator import itemgetter\n",
"\n",
"from langchain_core.messages import ToolMessage\n",
"from langchain_core.output_parsers import StrOutputParser\n",
"from langchain_core.prompts import MessagesPlaceholder\n",
"from langchain_core.runnables import RunnablePassthrough\n",
"\n",
"system = f\"\"\"You have access to a pandas dataframe `df`. \\\n",
"Here is the output of `df.head().to_markdown()`:\n",
"\n",
"```\n",
"{df.head().to_markdown()}\n",
"```\n",
"\n",
"Given a user question, write the Python code to answer it. \\\n",
"Don't assume you have access to any libraries other than built-in Python ones and pandas.\n",
"Respond directly to the question once you have enough information to answer it.\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" system,\n",
" ),\n",
" (\"human\", \"{question}\"),\n",
" # This MessagesPlaceholder allows us to optionally append an arbitrary number of messages\n",
" # at the end of the prompt using the 'chat_history' arg.\n",
" MessagesPlaceholder(\"chat_history\", optional=True),\n",
" ]\n",
")\n",
"\n",
"\n",
"def _get_chat_history(x: dict) -> list:\n",
" \"\"\"Parse the chain output up to this point into a list of chat history messages to insert in the prompt.\"\"\"\n",
" ai_msg = x[\"ai_msg\"]\n",
" tool_call_id = x[\"ai_msg\"].additional_kwargs[\"tool_calls\"][0][\"id\"]\n",
" tool_msg = ToolMessage(tool_call_id=tool_call_id, content=str(x[\"tool_output\"]))\n",
" return [ai_msg, tool_msg]\n",
"\n",
"\n",
"chain = (\n",
" RunnablePassthrough.assign(ai_msg=prompt | llm_with_tools)\n",
" .assign(tool_output=itemgetter(\"ai_msg\") | parser | tool)\n",
" .assign(chat_history=_get_chat_history)\n",
" .assign(response=prompt | llm | StrOutputParser())\n",
" .pick([\"tool_output\", \"response\"])\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "03e14712-9959-4f2d-94d5-4ac2bd9f3f08",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'tool_output': 0.11232863699941621,\n",
" 'response': 'The correlation between age and fare is approximately 0.112.'}"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"question\": \"What's the correlation between age and fare\"})"
]
},
{
"cell_type": "markdown",
"id": "245a5a91-c6d2-4a40-9b9f-eb38f78c9d22",
"metadata": {},
"source": [
"Here's the LangSmith trace for this run: https://smith.langchain.com/public/ca689f8a-5655-4224-8bcf-982080744462/r"
]
},
{
"cell_type": "markdown",
"id": "6c24b4f4-abbf-4891-b200-814eb9c35bec",
"metadata": {},
"source": [
"### Agent\n",
"\n",
"For complex questions it can be helpful for an LLM to be able to iteratively execute code while maintaining the inputs and outputs of its previous executions. This is where Agents come into play. They allow an LLM to decide how many times a tool needs to be invoked and keep track of the executions it's made so far. The [create_pandas_dataframe_agent](https://api.python.langchain.com/en/latest/agents/langchain_experimental.agents.agent_toolkits.pandas.base.create_pandas_dataframe_agent.html) is a built-in agent that makes it easy to work with dataframes:"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "b8b3a781-189f-48ff-b541-f5ed2f65e3e7",
"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()\"}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m Age Fare\n",
"Age 1.000000 0.112329\n",
"Fare 0.112329 1.000000\u001b[0m\u001b[32;1m\u001b[1;3m\n",
"Invoking: `python_repl_ast` with `{'query': \"df[['Fare', 'Survived']].corr()\"}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m Fare Survived\n",
"Fare 1.000000 0.256179\n",
"Survived 0.256179 1.000000\u001b[0m\u001b[32;1m\u001b[1;3mThe correlation between age and fare is 0.112329, while the correlation between fare and survival is 0.256179. Therefore, the correlation between fare and survival is greater than the correlation between age and fare.\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 0.112329, while the correlation between fare and survival is 0.256179. Therefore, the correlation between fare and survival is greater than the correlation between age and fare.'}"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_experimental.agents import create_pandas_dataframe_agent\n",
"\n",
"agent = create_pandas_dataframe_agent(llm, df, agent_type=\"openai-tools\", verbose=True)\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",
")"
]
},
{
"cell_type": "markdown",
"id": "a65322f3-b13c-4949-82b2-4517b9a0859d",
"metadata": {},
"source": [
"Here's the LangSmith trace for this run: https://smith.langchain.com/public/8e6c23cc-782c-4203-bac6-2a28c770c9f0/r"
]
},
{
"cell_type": "markdown",
"id": "68492261-faef-47e7-8009-e20ef1420d5a",
"metadata": {},
"source": [
"### Multiple CSVs\n",
"\n",
"To handle multiple CSVs (or dataframes) we just need to pass multiple dataframes to our Python tool. Our `create_pandas_dataframe_agent` constructor can do this out of the box, we can pass in a list of dataframes instead of just one. If we're constructing a chain ourselves, we can do something like:"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "bb528ab0-4aed-43fd-8a15-a1fe02a33d9e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"-0.14384991262954416"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_1 = df[[\"Age\", \"Fare\"]]\n",
"df_2 = df[[\"Fare\", \"Survived\"]]\n",
"\n",
"tool = PythonAstREPLTool(locals={\"df_1\": df_1, \"df_2\": df_2})\n",
"llm_with_tool = llm.bind_tools(tools=[tool], tool_choice=tool.name)\n",
"df_template = \"\"\"```python\n",
"{df_name}.head().to_markdown()\n",
">>> {df_head}\n",
"```\"\"\"\n",
"df_context = \"\\n\\n\".join(\n",
" df_template.format(df_head=_df.head().to_markdown(), df_name=df_name)\n",
" for _df, df_name in [(df_1, \"df_1\"), (df_2, \"df_2\")]\n",
")\n",
"\n",
"system = f\"\"\"You have access to a number of pandas dataframes. \\\n",
"Here is a sample of rows from each dataframe and the python code that was used to generate the sample:\n",
"\n",
"{df_context}\n",
"\n",
"Given a user question about the dataframes, write the Python code to answer it. \\\n",
"Don't assume you have access to any libraries other than built-in Python ones and pandas. \\\n",
"Make sure to refer only to the variables mentioned above.\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", \"{question}\")])\n",
"\n",
"chain = prompt | llm_with_tool | parser | tool\n",
"chain.invoke(\n",
" {\n",
" \"question\": \"return the difference in the correlation between age and fare and the correlation between fare and survival\"\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"id": "7043363f-4ab1-41de-9318-c556e4ae66bc",
"metadata": {},
"source": [
"Here's the LangSmith trace for this run: https://smith.langchain.com/public/653e499f-179c-4757-8041-f5e2a5f11fcc/r"
]
},
{
"cell_type": "markdown",
"id": "a2256d09-23c2-4e52-bfc6-c84eba538586",
"metadata": {},
"source": [
"### Sandboxed code execution\n",
"\n",
"There are a number of tools like [E2B](/docs/integrations/tools/e2b_data_analysis) and [Bearly](/docs/integrations/tools/bearly) that provide sandboxed environments for Python code execution, to allow for safer code-executing chains and agents."
]
},
{
"cell_type": "markdown",
"id": "1728e791-f114-41e6-aa12-0436fdeeedae",
"metadata": {},
"source": [
"## Next steps\n",
"\n",
"For more advanced data analysis applications we recommend checking out:\n",
"\n",
"* [SQL use case](/docs/use_cases/sql/): Many of the challenges of working with SQL db's and CSV's are generic to any structured data type, so it's useful to read the SQL techniques even if you're using Pandas for CSV data analysis.\n",
"* [Tool use](/docs/use_cases/tool_use/): Guides on general best practices when working with chains and agents that invoke tools\n",
"* [Agents](/docs/modules/agents/): Understand the fundamentals of building LLM agents.\n",
"* Integrations: Sandboxed envs like [E2B](/docs/integrations/tools/e2b_data_analysis) and [Bearly](/docs/integrations/tools/bearly), utilities like [SQLDatabase](https://api.python.langchain.com/en/latest/utilities/langchain_community.utilities.sql_database.SQLDatabase.html#langchain_community.utilities.sql_database.SQLDatabase), related agents like [Spark DataFrame agent](/docs/integrations/toolkits/spark)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "poetry-venv",
"language": "python",
"name": "poetry-venv"
},
"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.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -6,7 +6,6 @@
"metadata": {},
"source": [
"---\n",
"sidebar-position: 1\n",
"title: Synthetic data generation\n",
"---"
]

View File

@@ -6,7 +6,6 @@
"metadata": {},
"source": [
"---\n",
"sidebar_position: 1\n",
"title: Extraction\n",
"---"
]
@@ -430,7 +429,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"id": "64650362",
"metadata": {},
"outputs": [
@@ -452,8 +451,8 @@
"from langchain.prompts import (\n",
" PromptTemplate,\n",
")\n",
"from langchain_core.pydantic_v1 import BaseModel, Field, validator\n",
"from langchain_openai import OpenAI\n",
"from pydantic import BaseModel, Field, validator\n",
"\n",
"\n",
"class Person(BaseModel):\n",
@@ -531,8 +530,8 @@
"from langchain.prompts import (\n",
" PromptTemplate,\n",
")\n",
"from langchain_core.pydantic_v1 import BaseModel, Field, validator\n",
"from langchain_openai import OpenAI\n",
"from pydantic import BaseModel, Field, validator\n",
"\n",
"\n",
"# Define your desired data structure.\n",
@@ -611,7 +610,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.2"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -0,0 +1,543 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "922a7a98-7d73-4a1a-8860-76a33451d1be",
"metadata": {
"id": "922a7a98-7d73-4a1a-8860-76a33451d1be"
},
"source": [
"# Ontotext GraphDB QA Chain\n",
"\n",
"This notebook shows how to use LLMs to provide natural language querying (NLQ to SPARQL, also called text2sparql) for [Ontotext GraphDB](https://graphdb.ontotext.com/). Ontotext GraphDB is a graph database and knowledge discovery tool compliant with [RDF](https://www.w3.org/RDF/) and [SPARQL](https://www.w3.org/TR/sparql11-query/).\n",
"\n",
"## GraphDB LLM Functionalities\n",
"\n",
"GraphDB supports some LLM integration functionalities as described in [https://github.com/w3c/sparql-dev/issues/193](https://github.com/w3c/sparql-dev/issues/193):\n",
"\n",
"[gpt-queries](https://graphdb.ontotext.com/documentation/10.5/gpt-queries.html)\n",
"\n",
"* magic predicates to ask an LLM for text, list or table using data from your knowledge graph (KG)\n",
"* query explanation\n",
"* result explanation, summarization, rephrasing, translation\n",
"\n",
"[retrieval-graphdb-connector](https://graphdb.ontotext.com/documentation/10.5/retrieval-graphdb-connector.html)\n",
"\n",
"* Indexing of KG entities in a vector database\n",
"* Supports any text embedding algorithm and vector database\n",
"* Uses the same powerful connector (indexing) language that GraphDB uses for Elastic, Solr, Lucene\n",
"* Automatic synchronization of changes in RDF data to the KG entity index\n",
"* Supports nested objects (no UI support in GraphDB version 10.5)\n",
"* Serializes KG entities to text like this (e.g. for a Wines dataset):\n",
"\n",
"```\n",
"Franvino:\n",
"- is a RedWine.\n",
"- made from grape Merlo.\n",
"- made from grape Cabernet Franc.\n",
"- has sugar dry.\n",
"- has year 2012.\n",
"```\n",
"\n",
"[talk-to-graph](https://graphdb.ontotext.com/documentation/10.5/talk-to-graph.html)\n",
"\n",
"* A simple chatbot using a defined KG entity index\n",
"\n",
"## Querying the GraphDB Database\n",
"\n",
"For this tutorial, we won't use the GraphDB LLM integration, but SPARQL generation from NLQ. We'll use the Star Wars API (SWAPI) ontology and dataset that you can examine [here](https://drive.google.com/file/d/1wQ2K4uZp4eq3wlJ6_F_TxkOolaiczdYp/view?usp=drive_link).\n",
"\n",
"You will need to have a running GraphDB instance. This tutorial shows how to run the database locally using the [GraphDB Docker image](https://hub.docker.com/r/ontotext/graphdb). It provides a docker compose set-up, which populates GraphDB with the Star Wars dataset. All nessessary files including this notebook can be downloaded from GDrive.\n",
"\n",
"### Set-up\n",
"\n",
"* Install [Docker](https://docs.docker.com/get-docker/). This tutorial is created using Docker version `24.0.7` which bundles [Docker Compose](https://docs.docker.com/compose/). For earlier Docker versions you may need to install Docker Compose separately.\n",
"* Download all files from [GDrive](https://drive.google.com/drive/folders/18dN7WQxfGu26Z9C9HUU5jBwDuPnVTLbl) in a local folder on your machine.\n",
"* Start GraphDB with the following script executed from this folder\n",
" ```\n",
" docker build --tag graphdb .\n",
" docker compose up -d graphdb\n",
" ```\n",
" You need to wait a couple of seconds for the database to start on `http://localhost:7200/`. The Star Wars dataset `starwars-data.trig` is automatically loaded into the `langchain` repository. The local SPARQL endpoint `http://localhost:7200/repositories/langchain` can be used to run queries against. You can also open the GraphDB Workbench from your favourite web browser `http://localhost:7200/sparql` where you can make queries interactively.\n",
"* Working environment\n",
"\n",
"If you use `conda`, create and activate a new conda env (e.g. `conda create -n graph_ontotext_graphdb_qa python=3.9.18`).\n",
"Install the following libraries:\n",
"\n",
"```\n",
"pip install jupyter==1.0.0\n",
"pip install openai==1.6.1\n",
"pip install rdflib==7.0.0\n",
"pip install langchain-openai==0.0.2\n",
"pip install langchain\n",
"```\n",
"\n",
"Run Jupyter with\n",
"```\n",
"jupyter notebook\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "e51b397c-2fdc-4b99-9fed-1ab2b6ef7547",
"metadata": {
"id": "e51b397c-2fdc-4b99-9fed-1ab2b6ef7547"
},
"source": [
"### Specifying the Ontology\n",
"\n",
"In order for the LLM to be able to generate SPARQL, it needs to know the knowledge graph schema (the ontology). It can be provided using one of two parameters on the `OntotextGraphDBGraph` class:\n",
"\n",
"* `query_ontology`: a `CONSTRUCT` query that is executed on the SPARQL endpoint and returns the KG schema statements. We recommend that you store the ontology in its own named graph, which will make it easier to get only the relevant statements (as the example below). `DESCRIBE` queries are not supported, because `DESCRIBE` returns the Symmetric Concise Bounded Description (SCBD), i.e. also the incoming class links. In case of large graphs with a million of instances, this is not efficient. Check https://github.com/eclipse-rdf4j/rdf4j/issues/4857\n",
"* `local_file`: a local RDF ontology file. Supported RDF formats are `Turtle`, `RDF/XML`, `JSON-LD`, `N-Triples`, `Notation-3`, `Trig`, `Trix`, `N-Quads`.\n",
"\n",
"In either case, the ontology dump should:\n",
"\n",
"* Include enough information about classes, properties, property attachment to classes (using rdfs:domain, schema:domainIncludes or OWL restrictions), and taxonomies (important individuals).\n",
"* Not include overly verbose and irrelevant definitions and examples that do not help SPARQL construction."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "dc8792e0-acfb-4310-b5fa-8f649e448870",
"metadata": {
"id": "dc8792e0-acfb-4310-b5fa-8f649e448870"
},
"outputs": [],
"source": [
"from langchain_community.graphs import OntotextGraphDBGraph\n",
"\n",
"# feeding the schema using a user construct query\n",
"\n",
"graph = OntotextGraphDBGraph(\n",
" query_endpoint=\"http://localhost:7200/repositories/langchain\",\n",
" query_ontology=\"CONSTRUCT {?s ?p ?o} FROM <https://swapi.co/ontology/> WHERE {?s ?p ?o}\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a08b8d8c-af01-4401-8069-5f2cd022a6df",
"metadata": {
"id": "a08b8d8c-af01-4401-8069-5f2cd022a6df"
},
"outputs": [],
"source": [
"# feeding the schema using a local RDF file\n",
"\n",
"graph = OntotextGraphDBGraph(\n",
" query_endpoint=\"http://localhost:7200/repositories/langchain\",\n",
" local_file=\"/path/to/langchain_graphdb_tutorial/starwars-ontology.nt\", # change the path here\n",
")"
]
},
{
"cell_type": "markdown",
"id": "583b26ce-fb0d-4e9c-b5cd-9ec0e3be8922",
"metadata": {
"id": "583b26ce-fb0d-4e9c-b5cd-9ec0e3be8922"
},
"source": [
"Either way, the ontology (schema) is fed to the LLM as `Turtle` since `Turtle` with appropriate prefixes is most compact and easiest for the LLM to remember.\n",
"\n",
"The Star Wars ontology is a bit unusual in that it includes a lot of specific triples about classes, e.g. that the species `:Aleena` live on `<planet/38>`, they are a subclass of `:Reptile`, have certain typical characteristics (average height, average lifespan, skinColor), and specific individuals (characters) are representatives of that class:\n",
"\n",
"\n",
"```\n",
"@prefix : <https://swapi.co/vocabulary/> .\n",
"@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n",
"\n",
":Aleena a owl:Class, :Species ;\n",
" rdfs:label \"Aleena\" ;\n",
" rdfs:isDefinedBy <https://swapi.co/ontology/> ;\n",
" rdfs:subClassOf :Reptile, :Sentient ;\n",
" :averageHeight 80.0 ;\n",
" :averageLifespan \"79\" ;\n",
" :character <https://swapi.co/resource/aleena/47> ;\n",
" :film <https://swapi.co/resource/film/4> ;\n",
" :language \"Aleena\" ;\n",
" :planet <https://swapi.co/resource/planet/38> ;\n",
" :skinColor \"blue\", \"gray\" .\n",
"\n",
" ...\n",
"\n",
" ```\n"
]
},
{
"cell_type": "markdown",
"id": "6277d911-b0f6-4aeb-9aa5-96416b668468",
"metadata": {
"id": "6277d911-b0f6-4aeb-9aa5-96416b668468"
},
"source": [
"In order to keep this tutorial simple, we use un-secured GraphDB. If GraphDB is secured, you should set the environment variables 'GRAPHDB_USERNAME' and 'GRAPHDB_PASSWORD' before the initialization of `OntotextGraphDBGraph`.\n",
"\n",
"```python\n",
"os.environ[\"GRAPHDB_USERNAME\"] = \"graphdb-user\"\n",
"os.environ[\"GRAPHDB_PASSWORD\"] = \"graphdb-password\"\n",
"\n",
"graph = OntotextGraphDBGraph(\n",
" query_endpoint=...,\n",
" query_ontology=...\n",
")\n",
"```\n"
]
},
{
"cell_type": "markdown",
"id": "446d8a00-c98f-43b8-9e84-77b244f7bb24",
"metadata": {
"id": "446d8a00-c98f-43b8-9e84-77b244f7bb24"
},
"source": [
"### Question Answering against the StarWars Dataset\n",
"\n",
"We can now use the `OntotextGraphDBQAChain` to ask some questions."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "fab63d88-511d-4049-9bf0-ca8748f1fbff",
"metadata": {
"id": "fab63d88-511d-4049-9bf0-ca8748f1fbff"
},
"outputs": [],
"source": [
"import os\n",
"\n",
"from langchain.chains import OntotextGraphDBQAChain\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"# We'll be using an OpenAI model which requires an OpenAI API Key.\n",
"# However, other models are available as well:\n",
"# https://python.langchain.com/docs/integrations/chat/\n",
"\n",
"# Set the environment variable `OPENAI_API_KEY` to your OpenAI API key\n",
"os.environ[\"OPENAI_API_KEY\"] = \"sk-***\"\n",
"\n",
"# Any available OpenAI model can be used here.\n",
"# We use 'gpt-4-1106-preview' because of the bigger context window.\n",
"# The 'gpt-4-1106-preview' model_name will deprecate in the future and will change to 'gpt-4-turbo' or similar,\n",
"# so be sure to consult with the OpenAI API https://platform.openai.com/docs/models for the correct naming.\n",
"\n",
"chain = OntotextGraphDBQAChain.from_llm(\n",
" ChatOpenAI(temperature=0, model_name=\"gpt-4-1106-preview\"),\n",
" graph=graph,\n",
" verbose=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "64de8463-35b1-4c65-91e4-387daf4dd7d4",
"metadata": {},
"source": [
"Let's ask a simple one."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "f1dc4bea-b0f1-48f7-99a6-351a31acac7b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new OntotextGraphDBQAChain chain...\u001b[0m\n",
"Generated SPARQL:\n",
"\u001b[32;1m\u001b[1;3mPREFIX : <https://swapi.co/vocabulary/>\n",
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n",
"\n",
"SELECT ?climate\n",
"WHERE {\n",
" ?planet rdfs:label \"Tatooine\" ;\n",
" :climate ?climate .\n",
"}\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"'The climate on Tatooine is arid.'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({chain.input_key: \"What is the climate on Tatooine?\"})[chain.output_key]"
]
},
{
"cell_type": "markdown",
"id": "6d3a37f4-5c56-4b3e-b6ae-3eb030ffcc8f",
"metadata": {},
"source": [
"And a bit more complicated one."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "4dde8b18-4329-4a86-abfb-26d3e77034b7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new OntotextGraphDBQAChain chain...\u001b[0m\n",
"Generated SPARQL:\n",
"\u001b[32;1m\u001b[1;3mPREFIX : <https://swapi.co/vocabulary/>\n",
"PREFIX owl: <http://www.w3.org/2002/07/owl#>\n",
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n",
"\n",
"SELECT ?climate\n",
"WHERE {\n",
" ?character rdfs:label \"Luke Skywalker\" .\n",
" ?character :homeworld ?planet .\n",
" ?planet :climate ?climate .\n",
"}\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"\"The climate on Luke Skywalker's home planet is arid.\""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({chain.input_key: \"What is the climate on Luke Skywalker's home planet?\"})[\n",
" chain.output_key\n",
"]"
]
},
{
"cell_type": "markdown",
"id": "51d3ce3e-9528-4a65-8f3e-2281de08cbf1",
"metadata": {},
"source": [
"We can also ask more complicated questions like"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ab6f55f1-a3e0-4615-abd2-3cb26619c8d9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\u001b[1m> Entering new OntotextGraphDBQAChain chain...\u001b[0m\n",
"Generated SPARQL:\n",
"\u001b[32;1m\u001b[1;3mPREFIX : <https://swapi.co/vocabulary/>\n",
"PREFIX owl: <http://www.w3.org/2002/07/owl#>\n",
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n",
"PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n",
"\n",
"SELECT (AVG(?boxOffice) AS ?averageBoxOffice)\n",
"WHERE {\n",
" ?film a :Film .\n",
" ?film :boxOffice ?boxOfficeValue .\n",
" BIND(xsd:decimal(?boxOfficeValue) AS ?boxOffice)\n",
"}\n",
"\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
},
{
"data": {
"text/plain": [
"'The average box office revenue for all the Star Wars movies is approximately 754.1 million dollars.'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke(\n",
" {\n",
" chain.input_key: \"What is the average box office revenue for all the Star Wars movies?\"\n",
" }\n",
")[chain.output_key]"
]
},
{
"cell_type": "markdown",
"id": "11511345-8436-4634-92c6-36f2c0dd44db",
"metadata": {
"id": "11511345-8436-4634-92c6-36f2c0dd44db"
},
"source": [
"### Chain Modifiers\n",
"\n",
"The Ontotext GraphDB QA chain allows prompt refinement for further improvement of your QA chain and enhancing the overall user experience of your app.\n",
"\n",
"\n",
"#### \"SPARQL Generation\" Prompt\n",
"\n",
"The prompt is used for the SPARQL query generation based on the user question and the KG schema.\n",
"\n",
"- `sparql_generation_prompt`\n",
"\n",
" Default value:\n",
" ````python\n",
" GRAPHDB_SPARQL_GENERATION_TEMPLATE = \"\"\"\n",
" Write a SPARQL SELECT query for querying a graph database.\n",
" The ontology schema delimited by triple backticks in Turtle format is:\n",
" ```\n",
" {schema}\n",
" ```\n",
" Use only the classes and properties provided in the schema to construct the SPARQL query.\n",
" Do not use any classes or properties that are not explicitly provided in the SPARQL query.\n",
" Include all necessary prefixes.\n",
" Do not include any explanations or apologies in your responses.\n",
" Do not wrap the query in backticks.\n",
" Do not include any text except the SPARQL query generated.\n",
" The question delimited by triple backticks is:\n",
" ```\n",
" {prompt}\n",
" ```\n",
" \"\"\"\n",
" GRAPHDB_SPARQL_GENERATION_PROMPT = PromptTemplate(\n",
" input_variables=[\"schema\", \"prompt\"],\n",
" template=GRAPHDB_SPARQL_GENERATION_TEMPLATE,\n",
" )\n",
" ````\n",
"\n",
"#### \"SPARQL Fix\" Prompt\n",
"\n",
"Sometimes, the LLM may generate a SPARQL query with syntactic errors or missing prefixes, etc. The chain will try to amend this by prompting the LLM to correct it a certain number of times.\n",
"\n",
"- `sparql_fix_prompt`\n",
"\n",
" Default value:\n",
" ````python\n",
" GRAPHDB_SPARQL_FIX_TEMPLATE = \"\"\"\n",
" This following SPARQL query delimited by triple backticks\n",
" ```\n",
" {generated_sparql}\n",
" ```\n",
" is not valid.\n",
" The error delimited by triple backticks is\n",
" ```\n",
" {error_message}\n",
" ```\n",
" Give me a correct version of the SPARQL query.\n",
" Do not change the logic of the query.\n",
" Do not include any explanations or apologies in your responses.\n",
" Do not wrap the query in backticks.\n",
" Do not include any text except the SPARQL query generated.\n",
" The ontology schema delimited by triple backticks in Turtle format is:\n",
" ```\n",
" {schema}\n",
" ```\n",
" \"\"\"\n",
" \n",
" GRAPHDB_SPARQL_FIX_PROMPT = PromptTemplate(\n",
" input_variables=[\"error_message\", \"generated_sparql\", \"schema\"],\n",
" template=GRAPHDB_SPARQL_FIX_TEMPLATE,\n",
" )\n",
" ````\n",
"\n",
"- `max_fix_retries`\n",
" \n",
" Default value: `5`\n",
"\n",
"#### \"Answering\" Prompt\n",
"\n",
"The prompt is used for answering the question based on the results returned from the database and the initial user question. By default, the LLM is instructed to only use the information from the returned result(s). If the result set is empty, the LLM should inform that it can't answer the question.\n",
"\n",
"- `qa_prompt`\n",
" \n",
" Default value:\n",
" ````python\n",
" GRAPHDB_QA_TEMPLATE = \"\"\"Task: Generate a natural language response from the results of a SPARQL query.\n",
" You are an assistant that creates well-written and human understandable answers.\n",
" The information part contains the information provided, which you can use to construct an answer.\n",
" The information provided is authoritative, you must never doubt it or try to use your internal knowledge to correct it.\n",
" Make your response sound like the information is coming from an AI assistant, but don't add any information.\n",
" Don't use internal knowledge to answer the question, just say you don't know if no information is available.\n",
" Information:\n",
" {context}\n",
" \n",
" Question: {prompt}\n",
" Helpful Answer:\"\"\"\n",
" GRAPHDB_QA_PROMPT = PromptTemplate(\n",
" input_variables=[\"context\", \"prompt\"], template=GRAPHDB_QA_TEMPLATE\n",
" )\n",
" ````"
]
},
{
"cell_type": "markdown",
"id": "2ef8c073-003d-44ab-8a7b-cf45c50f6370",
"metadata": {
"id": "2ef8c073-003d-44ab-8a7b-cf45c50f6370"
},
"source": [
"Once you're finished playing with QA with GraphDB, you can shut down the Docker environment by running\n",
"``\n",
"docker compose down -v --remove-orphans\n",
"``\n",
"from the directory with the Docker compose file."
]
}
],
"metadata": {
"colab": {
"provenance": [],
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.8.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -586,11 +586,12 @@
"Vector stores are commonly used for retrieval, but there are other ways to do retrieval, too.\n",
"\n",
"`Retriever`: An object that returns `Document`s given a text query\n",
"\n",
"- [Docs](/docs/modules/data_connection/retrievers/): Further documentation on the interface and built-in retrieval techniques. Some of which include:\n",
" - `MultiQueryRetriever` [generates variants of the input question](/docs/modules/data_connection/retrievers/MultiQueryRetriever) to improve retrieval hit rate.\n",
" - `MultiVectorRetriever` (diagram below) instead generates [variants of the embeddings](/docs/modules/data_connection/retrievers/multi_vector), also in order to improve retrieval hit rate.\n",
" - `Max marginal relevance` selects for [relevance and diversity](https://www.cs.cmu.edu/~jgc/publication/The_Use_MMR_Diversity_Based_LTMIR_1998.pdf) among the retrieved documents to avoid passing in duplicate context.\n",
" - Documents can be filtered during vector store retrieval using [`metadata` filters](/docs/use_cases/question_answering/document-context-aware-QA).\n",
" - Documents can be filtered during vector store retrieval using metadata filters, such as with a [Self Query Retriever](/docs/modules/data_connection/retrievers/self_query).\n",
"- [Integrations](/docs/integrations/retrievers/): Integrations with retrieval services.\n",
"- [Interface](https://api.python.langchain.com/en/latest/retrievers/langchain_core.retrievers.BaseRetriever.html): API reference for the base interface."
]

View File

@@ -5,7 +5,7 @@
"metadata": {},
"source": [
"---\n",
"sidebar_position: 0.5\n",
"sidebar_position: 0.1\n",
"---"
]
},

View File

@@ -6,7 +6,6 @@
"metadata": {},
"source": [
"---\n",
"sidebar_position: 1\n",
"title: Summarization\n",
"---"
]
@@ -46,9 +45,9 @@
"\n",
"A central question for building a summarizer is how to pass your documents into the LLM's context window. Two common approaches for this are:\n",
"\n",
"1. `Stuff`: Simply \"stuff\" all your documents into a single prompt. This is the simplest approach (see [here](/docs/modules/chains/document/stuff) for more on the `StuffDocumentsChains`, which is used for this method).\n",
"1. `Stuff`: Simply \"stuff\" all your documents into a single prompt. This is the simplest approach (see [here](/docs/modules/chains#lcel-chains) for more on the `create_stuff_documents_chain` constructor, which is used for this method).\n",
"\n",
"2. `Map-reduce`: Summarize each document on it's own in a \"map\" step and then \"reduce\" the summaries into a final summary (see [here](/docs/modules/chains/document/map_reduce) for more on the `MapReduceDocumentsChain`, which is used for this method)."
"2. `Map-reduce`: Summarize each document on it's own in a \"map\" step and then \"reduce\" the summaries into a final summary (see [here](/docs/modules/chains#legacy-chains) for more on the `MapReduceDocumentsChain`, which is used for this method)."
]
},
{
@@ -524,7 +523,7 @@
"source": [
"## Option 3. Refine\n",
" \n",
"[Refine](/docs/modules/chains/document/refine) is similar to map-reduce:\n",
"[RefineDocumentsChain](/docs/modules/chains#legacy-chains) is similar to map-reduce:\n",
"\n",
"> The refine documents chain constructs a response by looping over the input documents and iteratively updating its answer. For each document, it passes all non-document inputs, the current document, and the latest intermediate answer to an LLM chain to get a new answer.\n",
"\n",
@@ -648,24 +647,10 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": null,
"id": "0ddd522e-30dc-4f6a-b993-c4f97e656c4f",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "`run` not supported when there is not exactly one output key. Got ['output_text', 'intermediate_steps'].",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[17], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mchains\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AnalyzeDocumentChain\n\u001b[1;32m 3\u001b[0m summarize_document_chain \u001b[38;5;241m=\u001b[39m AnalyzeDocumentChain(combine_docs_chain\u001b[38;5;241m=\u001b[39mchain, text_splitter\u001b[38;5;241m=\u001b[39mtext_splitter)\n\u001b[0;32m----> 4\u001b[0m \u001b[43msummarize_document_chain\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdocs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/langchain/libs/langchain/langchain/chains/base.py:496\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, tags, metadata, *args, **kwargs)\u001b[0m\n\u001b[1;32m 459\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Convenience method for executing chain.\u001b[39;00m\n\u001b[1;32m 460\u001b[0m \n\u001b[1;32m 461\u001b[0m \u001b[38;5;124;03mThe main difference between this method and `Chain.__call__` is that this\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 493\u001b[0m \u001b[38;5;124;03m # -> \"The temperature in Boise is...\"\u001b[39;00m\n\u001b[1;32m 494\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 495\u001b[0m \u001b[38;5;66;03m# Run at start to make sure this is possible/defined\u001b[39;00m\n\u001b[0;32m--> 496\u001b[0m _output_key \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run_output_key\u001b[49m\n\u001b[1;32m 498\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m args \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kwargs:\n\u001b[1;32m 499\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n",
"File \u001b[0;32m~/langchain/libs/langchain/langchain/chains/base.py:445\u001b[0m, in \u001b[0;36mChain._run_output_key\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 442\u001b[0m \u001b[38;5;129m@property\u001b[39m\n\u001b[1;32m 443\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_run_output_key\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28mstr\u001b[39m:\n\u001b[1;32m 444\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[0;32m--> 445\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 446\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` not supported when there is not exactly \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mone output key. Got \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 448\u001b[0m )\n\u001b[1;32m 449\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]\n",
"\u001b[0;31mValueError\u001b[0m: `run` not supported when there is not exactly one output key. Got ['output_text', 'intermediate_steps']."
]
}
],
"outputs": [],
"source": [
"from langchain.chains import AnalyzeDocumentChain\n",
"\n",

View File

@@ -6,7 +6,6 @@
"metadata": {},
"source": [
"---\n",
"sidebar_position: 1\n",
"title: Tagging\n",
"---"
]
@@ -415,7 +414,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -6,7 +6,7 @@
"metadata": {},
"source": [
"---\n",
"sidebar_position: 0.9\n",
"sidebar_position: 0.2\n",
"---"
]
},

View File

@@ -6,7 +6,6 @@
"metadata": {},
"source": [
"---\n",
"sidebar_position: 1\n",
"title: Web scraping\n",
"---"
]
@@ -670,7 +669,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -87,11 +87,11 @@ module.exports = {
collapsible: false,
items: [
{ type: "autogenerated", dirName: "integrations/platforms" },
{ type: "category", label: "More", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/providers" }]},
{ type: "category", label: "More", collapsed: true, items: [{type:"autogenerated", dirName: "integrations/providers" }], link: { type: 'generated-index', slug: "integrations/providers", }},
],
link: {
type: 'generated-index',
slug: "integrations/providers",
type: 'doc',
id: 'integrations/platforms/index'
},
},
{

View File

@@ -17,9 +17,9 @@
},
"outputs": [],
"source": [
"from __module_name__.chat_models import __ModuleName__Chat\n",
"from __module_name__.llms import __ModuleName__LLM\n",
"from __module_name__.vectorstores import __ModuleName__VectorStore"
"from __module_name__ import Chat__ModuleName__\n",
"from __module_name__ import __ModuleName__LLM\n",
"from __module_name__ import __ModuleName__VectorStore"
]
}
],

View File

@@ -41,7 +41,7 @@ lint lint_diff lint_package lint_tests:
poetry run ruff .
[ "$(PYTHON_FILES)" = "" ] || poetry run ruff format $(PYTHON_FILES) --diff
[ "$(PYTHON_FILES)" = "" ] || poetry run ruff --select I $(PYTHON_FILES)
[ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) || poetry run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE)
[ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) && poetry run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE)
format format_diff:
poetry run ruff format $(PYTHON_FILES)

View File

@@ -18,6 +18,7 @@ from langchain_community.agent_toolkits.amadeus.toolkit import AmadeusToolkit
from langchain_community.agent_toolkits.azure_cognitive_services import (
AzureCognitiveServicesToolkit,
)
from langchain_community.agent_toolkits.connery import ConneryToolkit
from langchain_community.agent_toolkits.file_management.toolkit import (
FileManagementToolkit,
)
@@ -50,6 +51,7 @@ __all__ = [
"AINetworkToolkit",
"AmadeusToolkit",
"AzureCognitiveServicesToolkit",
"ConneryToolkit",
"FileManagementToolkit",
"GmailToolkit",
"JiraToolkit",

View File

@@ -0,0 +1,7 @@
"""
This module contains the ConneryToolkit.
"""
from .toolkit import ConneryToolkit
__all__ = ["ConneryToolkit"]

View File

@@ -0,0 +1,51 @@
from typing import List
from langchain_core.pydantic_v1 import root_validator
from langchain_core.tools import BaseTool
from langchain_community.agent_toolkits.base import BaseToolkit
from langchain_community.tools.connery import ConneryService
class ConneryToolkit(BaseToolkit):
"""
A LangChain Toolkit with a list of Connery Actions as tools.
"""
tools: List[BaseTool]
def get_tools(self) -> List[BaseTool]:
"""
Returns the list of Connery Actions.
"""
return self.tools
@root_validator()
def validate_attributes(cls, values: dict) -> dict:
"""
Validate the attributes of the ConneryToolkit class.
Parameters:
values (dict): The arguments to validate.
Returns:
dict: The validated arguments.
"""
if not values.get("tools"):
raise ValueError("The attribute 'tools' must be set.")
return values
@classmethod
def create_instance(cls, connery_service: ConneryService) -> "ConneryToolkit":
"""
Creates a Connery Toolkit using a Connery Service.
Parameters:
connery_service (ConneryService): The Connery Service
to to get the list of Connery Actions.
Returns:
ConneryToolkit: The Connery Toolkit.
"""
instance = cls(tools=connery_service.list_actions())
return instance

View File

@@ -1,6 +1,6 @@
from __future__ import annotations
from typing import List, Optional
from typing import Dict, List, Optional, Type
from langchain_core.pydantic_v1 import root_validator
@@ -14,18 +14,17 @@ from langchain_community.tools.file_management.move import MoveFileTool
from langchain_community.tools.file_management.read import ReadFileTool
from langchain_community.tools.file_management.write import WriteFileTool
_FILE_TOOLS = {
# "Type[Runnable[Any, Any]]" has no attribute "__fields__" [attr-defined]
tool_cls.__fields__["name"].default: tool_cls # type: ignore[attr-defined]
for tool_cls in [
CopyFileTool,
DeleteFileTool,
FileSearchTool,
MoveFileTool,
ReadFileTool,
WriteFileTool,
ListDirectoryTool,
]
_FILE_TOOLS: List[Type[BaseTool]] = [
CopyFileTool,
DeleteFileTool,
FileSearchTool,
MoveFileTool,
ReadFileTool,
WriteFileTool,
ListDirectoryTool,
]
_FILE_TOOLS_MAP: Dict[str, Type[BaseTool]] = {
tool_cls.__fields__["name"].default: tool_cls for tool_cls in _FILE_TOOLS
}
@@ -61,20 +60,20 @@ class FileManagementToolkit(BaseToolkit):
def validate_tools(cls, values: dict) -> dict:
selected_tools = values.get("selected_tools") or []
for tool_name in selected_tools:
if tool_name not in _FILE_TOOLS:
if tool_name not in _FILE_TOOLS_MAP:
raise ValueError(
f"File Tool of name {tool_name} not supported."
f" Permitted tools: {list(_FILE_TOOLS)}"
f" Permitted tools: {list(_FILE_TOOLS_MAP)}"
)
return values
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
allowed_tools = self.selected_tools or _FILE_TOOLS.keys()
allowed_tools = self.selected_tools or _FILE_TOOLS_MAP
tools: List[BaseTool] = []
for tool in allowed_tools:
tool_cls = _FILE_TOOLS[tool]
tools.append(tool_cls(root_dir=self.root_dir)) # type: ignore
tool_cls = _FILE_TOOLS_MAP[tool]
tools.append(tool_cls(root_dir=self.root_dir))
return tools

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