Compare commits

..

161 Commits

Author SHA1 Message Date
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
ccurme
a989f82027 core: expand docstring for RunnableParallel (#16600)
- **Description:** expand docstring for RunnableParallel
  - **Issue:** https://github.com/langchain-ai/langchain/issues/16462

Feel free to modify this or let me know how it can be improved!
2024-01-26 10:03:32 -05:00
Ghani
e30c6662df Langchain-community : EdenAI chat integration. (#16377)
- **Description:** This PR adds [EdenAI](https://edenai.co/) for the
chat model (already available in LLM & Embeddings). It supports all
[ChatModel] functionality: generate, async generate, stream, astream and
batch. A detailed notebook was added.

  - **Dependencies**: No dependencies are added as we call a rest API.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2024-01-26 09:56:43 -05:00
Antonio Lanza
08d3fd7f2e langchain[patch]: inconsistent results with RecursiveCharacterTextSplitter's add_start_index=True (#16583)
This PR fixes issue #16579
2024-01-25 15:50:06 -08:00
Eugene Yurtsev
42db96477f docs: Update in code documentation for runnable with message history (#16585)
Update the in code documentation for Runnable With Message History
2024-01-25 15:26:34 -08:00
Jatin Chawda
a79345f199 community[patch]: Fixed tool names snake_case (#16397)
#16396
Fixed
1. golden_query
2. google_lens
3. memorize
4. merriam_webster
5. open_weather_map
6. pub_med
7. stack_exchange
8. generate_image
9. wikipedia
2024-01-25 15:24:19 -08:00
Bagatur
bcc71d1a57 openai[patch]: Release 0.0.5 (#16598) 2024-01-25 15:20:28 -08:00
Bagatur
68f7468754 google-vertexai[patch]: Release 0.0.3 (#16597) 2024-01-25 15:19:00 -08:00
Bagatur
61e876aad8 openai[patch]: Explicitly support embedding dimensions (#16596) 2024-01-25 15:16:04 -08:00
Bagatur
5df8ab574e infra: move indexing documentation test (#16595) 2024-01-25 14:46:50 -08:00
Bagatur
f3d61a6e47 langchain[patch]: Release 0.1.4 (#16592) 2024-01-25 14:19:18 -08:00
Bagatur
61b200947f community[patch]: Release 0.0.16 (#16591) 2024-01-25 14:19:09 -08:00
Bagatur
75ad0bba2d openai[patch]: Release 0.0.4 (#16590) 2024-01-25 14:08:46 -08:00
Bagatur
1e3ce338ca core[patch]: Release 0.1.16 (#16589) 2024-01-25 13:56:00 -08:00
Bagatur
6c89507988 docs: add rag citations page (#16549) 2024-01-25 13:51:41 -08:00
Bagatur
31790d15ec openai[patch]: accept function_call dict in bind_functions (#16483)
Confusing that you can't pass in a dict
2024-01-25 13:47:44 -08:00
Bagatur
db80832e4f docs: output parser nits (#16588) 2024-01-25 13:20:48 -08:00
Bagatur
ef42d9d559 core[patch], community[patch], openai[patch]: consolidate openai tool… (#16485)
… converters

One way to convert anything to an OAI function:
convert_to_openai_function
One way to convert anything to an OAI tool: convert_to_openai_tool
Corresponding bind functions on OAI models: bind_functions, bind_tools
2024-01-25 13:18:46 -08:00
Brian Burgin
148347e858 community[minor]: Add LiteLLM Router Integration (#15588)
community:

  - **Description:**
- Add new ChatLiteLLMRouter class that allows a client to use a LiteLLM
Router as a LangChain chat model.
- Note: The existing ChatLiteLLM integration did not cover the LiteLLM
Router class.
    - Add tests and Jupyter notebook.
  - **Issue:** None
  - **Dependencies:** Relies on existing ChatLiteLLM integration
  - **Twitter handle:** @bburgin_0

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-25 11:03:05 -08:00
Bob Lin
35e60728b7 docs: Fix broken urls (#16559) 2024-01-25 09:20:05 -08:00
Bob Lin
6023953ea7 docs: Fix github link (#16560) 2024-01-25 09:19:09 -08:00
JongRok BAEK
3b8eba32f9 anthropic[patch]: Fix message type lookup in Anthropic Partners (#16563)
- **Description:** 

The parameters for user and assistant in Anthropic should be 'ai ->
assistant,' but they are reversed to 'assistant -> ai.'
Below is error code.
```python
anthropic.BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages: Unexpected role "ai". Allowed roles are "user" or "assistant"'}}
```

[anthropic](7177f3a71f/src/anthropic/types/beta/message_param.py (L13))

  - **Issue:** : #16561
  -  **Dependencies:** : None
   - **Twitter handle:** : None
2024-01-25 09:17:59 -08:00
Dmitry Tyumentsev
e86e66bad7 community[patch]: YandexGPT models - add sleep_interval (#16566)
Added sleep between requests to prevent errors associated with
simultaneous requests.
2024-01-25 09:07:19 -08:00
Bagatur
e510cfaa23 core[patch]: passthrough BaseRetriever.invoke(**kwargs) (#16551)
Fix for #16547
2024-01-25 08:58:39 -08:00
Anders Åhsman
355ef2a4a6 langchain[patch]: Fix doc-string grammar (#16543)
- **Description:** Small grammar fix in docstring for class
`BaseCombineDocumentsChain`.
2024-01-25 10:00:06 -05:00
Aditya
9dd7cbb447 google-genai: added logic for method get_num_tokens() (#16205)
<!-- Thank you for contributing to LangChain!

Please title your PR "partners: google-genai",

Replace this entire comment with:
- **Description:** : added logic for method get_num_tokens() for
ChatGoogleGenerativeAI , GoogleGenerativeAI,
  - **Issue:** : https://github.com/langchain-ai/langchain/issues/16204,
  - **Dependencies:** : None,
  - **Twitter handle:** @Aditya_Rane

---------

Co-authored-by: adityarane@google.com <adityarane@google.com>
Co-authored-by: Leonid Kuligin <lkuligin@yandex.ru>
2024-01-24 21:43:16 -07:00
James Braza
0785432e7b langchain-google-vertexai: perserving grounding metadata (#16309)
Revival of https://github.com/langchain-ai/langchain/pull/14549 that
closes https://github.com/langchain-ai/langchain/issues/14548.
2024-01-24 21:37:43 -07:00
Erick Friis
adc008407e exa: init pkg (#16553) 2024-01-24 20:57:17 -07:00
Rave Harpaz
c4e9c9ca29 community[minor]: Add OCI Generative AI integration (#16548)
<!-- 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:** Adding Oracle Cloud Infrastructure Generative AI
integration. Oracle Cloud Infrastructure (OCI) Generative AI is a fully
managed service that provides a set of state-of-the-art, customizable
large language models (LLMs) that cover a wide range of use cases, and
which is available through a single API. Using the OCI Generative AI
service you can access ready-to-use pretrained models, or create and
host your own fine-tuned custom models based on your own data on
dedicated AI clusters.
https://docs.oracle.com/en-us/iaas/Content/generative-ai/home.htm
  - **Issue:** None,
  - **Dependencies:** OCI Python SDK,
- **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.
Passed

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.

we provide unit tests. However, we cannot provide integration tests due
to Oracle policies that prohibit public sharing of api keys.
 
If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->

---------

Co-authored-by: Arthur Cheng <arthur.cheng@oracle.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-24 18:23:50 -08:00
Bagatur
b8768bd6e7 docs: allow pdf download of api ref (#16550)
https://docs.readthedocs.io/en/stable/config-file/v2.html#formats
2024-01-24 17:17:52 -08:00
Leonid Ganeline
f6a05e964b docs: Hugging Face update (#16490)
- added missed integrations to the platform page
- updated integration examples: added links and fixed formats
2024-01-24 16:59:00 -08:00
Bagatur
c173a69908 langchain[patch]: oai tools output parser nit (#16540)
allow positional init args
2024-01-24 16:57:16 -08:00
arnob-sengupta
f9976b9630 core[patch]: consolidate conditional in BaseTool (#16530)
- **Description:** Refactor contradictory conditional to single line
  - **Issue:** #16528
2024-01-24 16:56:58 -08:00
Bagatur
5c2538b9f7 anthropic[patch]: allow pop by field name (#16544)
allow `ChatAnthropicMessages(model=...)`
2024-01-24 15:48:31 -07:00
Harel Gal
a91181fe6d community[minor]: add support for Guardrails for Amazon Bedrock (#15099)
Added support for optionally supplying 'Guardrails for Amazon Bedrock'
on both types of model invocations (batch/regular and streaming) and for
all models supported by the Amazon Bedrock service.

@baskaryan  @hwchase17

```python 
llm = Bedrock(model_id="<model_id>", client=bedrock,
                  model_kwargs={},
                  guardrails={"id": " <guardrail_id>",
                              "version": "<guardrail_version>",
                               "trace": True}, callbacks=[BedrockAsyncCallbackHandler()])

class BedrockAsyncCallbackHandler(AsyncCallbackHandler):
    """Async callback handler that can be used to handle callbacks from langchain."""

    async def on_llm_error(
            self,
            error: BaseException,
            **kwargs: Any,
    ) -> Any:
        reason = kwargs.get("reason")
        if reason == "GUARDRAIL_INTERVENED":
           # kwargs contains additional trace information sent by 'Guardrails for Bedrock' service.
            print(f"""Guardrails: {kwargs}""")


# streaming 
llm = Bedrock(model_id="<model_id>", client=bedrock,
                  model_kwargs={},
                  streaming=True,
                  guardrails={"id": "<guardrail_id>",
                              "version": "<guardrail_version>"})
```

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-24 14:44:19 -08:00
Martin Kolb
04651f0248 community[minor]: VectorStore integration for SAP HANA Cloud Vector Engine (#16514)
- **Description:**
This PR adds a VectorStore integration for SAP HANA Cloud Vector Engine,
which is an upcoming feature in the SAP HANA Cloud database
(https://blogs.sap.com/2023/11/02/sap-hana-clouds-vector-engine-announcement/).

  - **Issue:** N/A
- **Dependencies:** [SAP HANA Python
Client](https://pypi.org/project/hdbcli/)
  - **Twitter handle:** @sapopensource

Implementation of the integration:
`libs/community/langchain_community/vectorstores/hanavector.py`

Unit tests:
`libs/community/tests/unit_tests/vectorstores/test_hanavector.py`

Integration tests:
`libs/community/tests/integration_tests/vectorstores/test_hanavector.py`

Example notebook:
`docs/docs/integrations/vectorstores/hanavector.ipynb`

Access credentials for execution of the integration tests can be
provided to the maintainers.

---------

Co-authored-by: sascha <sascha.stoll@sap.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-24 14:05:07 -08:00
Leonid Kuligin
1113700b09 google-genai[patch]: better error message when location is not supported (#16535)
Replace this entire comment with:
- **Description:** a better error message when location is not supported
2024-01-24 13:58:46 -08:00
Bob Lin
54dd8e52a8 docs: Updated comments about n_gpu_layers in the Metal section (#16501)
Ref: https://github.com/langchain-ai/langchain/issues/16502
2024-01-24 13:38:48 -08:00
Eugene Yurtsev
fe382fcf20 CI: more qa template changes (#16533)
More qa template changes
2024-01-24 14:40:29 -05:00
Eugene Yurtsev
06f66f25e1 CI: Update q-a template (#16532)
Update template for QA discussions
2024-01-24 14:29:31 -05:00
Eugene Yurtsev
b1b351b37e CI: more updates to feature request template (#16531)
More updates
2024-01-24 14:15:26 -05:00
Eugene Yurtsev
4fad71882e CI: Fix ideas template (#16529)
Fix ideas template
2024-01-24 14:06:53 -05:00
Anastasiia Manokhina
ce595f0203 docs:Updated integration docs structure for chat/google_vertex_ai_palm (#16201)
Description: 

- checked that the doc chat/google_vertex_ai_palm is using new
functions: invoke, stream etc.
- added Gemini example
- fixed wrong output in Sanskrit example

Issue: https://github.com/langchain-ai/langchain/issues/15664
Dependencies: None
Twitter handle: None
2024-01-24 10:21:32 -08:00
Unai Garay Maestre
fdbfa6b2c8 Adds progress bar to VertexAIEmbeddings (#14542)
- **Description:** Adds progress bar to VertexAIEmbeddings 
- **Issue:** related issue
https://github.com/langchain-ai/langchain/issues/13637

Signed-off-by: ugm2 <unaigaraymaestre@gmail.com>

---------

Signed-off-by: ugm2 <unaigaraymaestre@gmail.com>
2024-01-24 11:16:16 -07:00
James Braza
643fb3ab50 langchain-google-vertexai[patch]: more verbose mypy config (#16307)
Flushing out the `mypy` config in `langchain-google-vertexai` to show
error codes and other warnings

This PR also bumps `mypy` to above version 1's stable release
2024-01-24 11:10:45 -07:00
Eugene Yurtsev
8d990ba67b CI: more update to ideas template (#16524)
Update ideas template
2024-01-24 13:05:47 -05:00
Eugene Yurtsev
63da14d620 CI: redirect feature requests to ideas in discussions (#16522)
Redirect feature requests to ideas in discussions
2024-01-24 13:03:10 -05:00
Erick Friis
8d299645f9 docs: rm output (#16519) 2024-01-24 10:19:34 -07:00
Eugene Yurtsev
dfd94fb2f0 CI: Update issue template (#16517)
More updates to the ISSUE template
2024-01-24 12:09:21 -05:00
Lance Martin
0b740ebd49 Update SQL agent toolkit docs (#16409) 2024-01-24 09:03:17 -08:00
Francisco Ingham
13cf4594f4 docs: added a few suggestions for sql docs (#16508) 2024-01-24 08:48:41 -08:00
Eugene Yurtsev
6004e9706f Docs: Add streaming section (#16468)
Adds a streaming section to LangChain documentation, explaining
`stream`/`astream` API and `astream_events` API.
2024-01-24 10:38:39 -05:00
Tipwheal
66aafc0573 Docs: typo in tool use quick start page (#16494)
Minor typo fix
2024-01-24 10:37:12 -05:00
Jeremi Joslin
9e95699277 community[patch]: Fix error message when litellm is not installed (#16316)
The error message was mentioning the wrong package. I updated it to the
correct one.
2024-01-23 21:42:29 -08:00
bachr
b3ed98dec0 community[patch]: avoid KeyError when language not in LANGUAGE_SEGMENTERS (#15212)
**Description:**

Handle unsupported languages in same way as when none is provided 
 
**Issue:**

The following line will throw a KeyError if the language is not
supported.
```python
self.Segmenter = LANGUAGE_SEGMENTERS[language]
```
E.g. when using `Language.CPP` we would get `KeyError: <Language.CPP:
'cpp'>`

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-23 21:09:43 -08:00
Nuno Campos
3f38e1a457 Remove double line (#16426)
<!-- 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-23 20:22:37 -08:00
chyroc
61da2ff24c community[patch]: use SecretStr for yandex model secrets (#15463) 2024-01-23 20:08:53 -08:00
Alessio Serra
d628a80a5d community[patch]: added 'conversational' as a valid task for hugginface endopoint models (#15761)
- **Description:** added the conversational task to hugginFace endpoint
in order to use models designed for chatbot programming.
  - **Dependencies:** None

---------

Co-authored-by: Alessio Serra (ext.) <alessio.serra@partner.bmw.de>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2024-01-23 20:04:15 -08:00
Karim Lalani
4c7755778d community[patch]: SurrealDB fix for asyncio (#16092)
Code fix for asyncio
2024-01-23 19:46:19 -08:00
BeatrixCohere
2b2285dac0 docs: Update cohere rerank and comparison docs (#16198)
- **Description:** Update the cohere rerank docs to use cohere
embeddings
  - **Issue:** n/a
  - **Dependencies:** n/a
  - **Twitter handle:** n/a
2024-01-23 19:39:42 -08:00
Raunak
476bf8b763 community[patch]: Load list of files using UnstructuredFileLoader (#16216)
- **Description:** Updated `_get_elements()` function of
`UnstructuredFileLoader `class to check if the argument self.file_path
is a file or list of files. If it is a list of files then it iterates
over the list of file paths, calls the partition function for each one,
and appends the results to the elements list. If self.file_path is not a
list, it calls the partition function as before.
  
  - **Issue:** Fixed #15607,
  - **Dependencies:** NA
  - **Twitter handle:** NA

Co-authored-by: H161961 <Raunak.Raunak@Honeywell.com>
2024-01-23 19:37:37 -08:00
Xudong Sun
019b6ebe8d community[minor]: Add iFlyTek Spark LLM chat model support (#13389)
- **Description:** This PR enables LangChain to access the iFlyTek's
Spark LLM via the chat_models wrapper.
  - **Dependencies:** websocket-client ^1.6.1
  - **Tag maintainer:** @baskaryan 

### SparkLLM chat model usage

Get SparkLLM's app_id, api_key and api_secret from [iFlyTek SparkLLM API
Console](https://console.xfyun.cn/services/bm3) (for more info, see
[iFlyTek SparkLLM Intro](https://xinghuo.xfyun.cn/sparkapi) ), then set
environment variables `IFLYTEK_SPARK_APP_ID`, `IFLYTEK_SPARK_API_KEY`
and `IFLYTEK_SPARK_API_SECRET` or pass parameters when using it like the
demo below:

```python3
from langchain.chat_models.sparkllm import ChatSparkLLM

client = ChatSparkLLM(
    spark_app_id="<app_id>",
    spark_api_key="<api_key>",
    spark_api_secret="<api_secret>"
)
```
2024-01-23 19:23:46 -08:00
Ali Zendegani
80fcc50c65 langchain[patch]: Minor Fix: Enable Passing custom_headers for Authentication in GraphQL Agent/Tool (#16413)
- **Description:** 

This PR aims to enhance the `langchain` library by enabling the support
for passing `custom_headers` in the `GraphQLAPIWrapper` usage within
`langchain/agents/load_tools.py`.

While the `GraphQLAPIWrapper` from the `langchain_community` module is
inherently capable of handling `custom_headers`, its current invocation
in `load_tools.py` does not facilitate this functionality.
This limitation restricts the use of the `graphql` tool with databases
or APIs that require token-based authentication.

The absence of support for `custom_headers` in this context also leads
to a lack of error messages when attempting to interact with secured
GraphQL endpoints, making debugging and troubleshooting more
challenging.

This update modifies the `load_tools` function to correctly handle
`custom_headers`, thereby allowing secure and authenticated access to
GraphQL services requiring tokens.

Example usage after the proposed change:
```python
tools = load_tools(
    ["graphql"],
    graphql_endpoint="https://your-graphql-endpoint.com/graphql",
    custom_headers={"Authorization": f"Token {api_token}"},
)
```
  - **Issue:** None,
  - **Dependencies:** None,
  - **Twitter handle:** None
2024-01-23 19:19:53 -08:00
Serena Ruan
5c6e123757 community[patch]: Fix MlflowCallback with none artifacts_dir (#16487) 2024-01-23 19:09:02 -08:00
Krista Pratico
0e2e7d8b83 langchain[patch]: allow passing client with OpenAIAssistantRunnable (#16486)
- **Description:** This addresses the issue tagged below where if you
try to pass your own client when creating an OpenAI assistant, a
pydantic error is raised:

Example code:

```python
import openai
from langchain.agents.openai_assistant import OpenAIAssistantRunnable

client = openai.OpenAI()
interpreter_assistant = OpenAIAssistantRunnable.create_assistant(
    name="langchain assistant",
    instructions="You are a personal math tutor. Write and run code to answer math questions.",
    tools=[{"type": "code_interpreter"}],
    model="gpt-4-1106-preview",
    client=client
)

```

Error:
`pydantic.v1.errors.ConfigError: field "client" not yet prepared, so the
type is still a ForwardRef. You might need to call
OpenAIAssistantRunnable.update_forward_refs()`

It additionally updates type hints and docstrings to indicate that an
AzureOpenAI client is permissible as well.

  - **Issue:** https://github.com/langchain-ai/langchain/issues/15948
  - **Dependencies:** N/A
2024-01-23 18:48:29 -08:00
Eugene Yurtsev
d898d2f07b docs: Fix version in which astream_events was released (#16481)
Fix typo in version
2024-01-23 18:41:44 -08:00
bu2kx
ff3163297b community[minor]: Add KDBAI vector store (#12797)
Addition of KDBAI vector store (https://kdb.ai).

Dependencies: `kdbai_client` v0.1.2 Python package.

Sample notebook: `docs/docs/integrations/vectorstores/kdbai.ipynb`

Tag maintainer: @bu2kx
Twitter handle: @kxsystems
2024-01-23 18:37:01 -08:00
JongRok BAEK
4ec3fe4680 docs: Updated integration docs structure for chat/anthropic (#16268)
Description: 
- Added output and environment variables
- Updated the documentation for chat/anthropic, changing references from
`langchain.schema` to `langchain_core.prompts`.

Issue: https://github.com/langchain-ai/langchain/issues/15664
Dependencies: None
Twitter handle: None

Since this is my first open-source PR, please feel free to point out any
mistakes, and I'll be eager to make corrections.
2024-01-23 18:36:28 -08:00
Shivani Modi
4e160540ff community[minor]: Adding Konko Completion endpoint (#15570)
This PR introduces update to Konko Integration with LangChain.

1. **New Endpoint Addition**: Integration of a new endpoint to utilize
completion models hosted on Konko.

2. **Chat Model Updates for Backward Compatibility**: We have updated
the chat models to ensure backward compatibility with previous OpenAI
versions.

4. **Updated Documentation**: Comprehensive documentation has been
updated to reflect these new changes, providing clear guidance on
utilizing the new features and ensuring seamless integration.

Thank you to the LangChain team for their exceptional work and for
considering this PR. Please let me know if any additional information is
needed.

---------

Co-authored-by: Shivani Modi <shivanimodi@Shivanis-MacBook-Pro.local>
Co-authored-by: Shivani Modi <shivanimodi@Shivanis-MBP.lan>
2024-01-23 18:22:32 -08:00
Gianfranco Demarco
c69f599594 langchain[patch]: Extract _aperform_agent_action from _aiter_next_step from AgentExecutor (#15707)
- **Description:** extreact the _aperform_agent_action in the
AgentExecutor class to allow for easier overriding. Extracted logic from
_iter_next_step into a new method _perform_agent_action for consistency
and easier overriding.
- **Issue:** #15706

Closes #15706
2024-01-23 18:22:09 -08:00
i-w-a
95ee69a301 langchain[patch]: In HTMLHeaderTextSplitter set default encoding to utf-8 (#16372)
- **Description:** The HTMLHeaderTextSplitter Class now explicitly
specifies utf-8 encoding in the part of the split_text_from_file method
that calls the HTMLParser.
- **Issue:** Prevent garbled characters due to differences in encoding
of html files (except for English in particular, I noticed that problem
with Japanese).
  - **Dependencies:** No dependencies,
  - **Twitter handle:**  @i_w__a
2024-01-23 18:20:29 -08:00
Noah Stapp
e135e5257c community[patch]: Include scores in MongoDB Atlas QA chain results (#14666)
Adds the ability to return similarity scores when using
`RetrievalQA.from_chain_type` with `MongoDBAtlasVectorSearch`. Requires
that `return_source_documents=True` is set.

Example use:

```
vector_search = MongoDBAtlasVectorSearch.from_documents(...)

qa = RetrievalQA.from_chain_type(
	llm=OpenAI(), 
	chain_type="stuff", 
	retriever=vector_search.as_retriever(search_kwargs={"additional": ["similarity_score"]}),
	return_source_documents=True
)

...

docs = qa({"query": "..."})

docs["source_documents"][0].metadata["score"] # score will be here
```

I've tested this feature locally, using a MongoDB Atlas Cluster with a
vector search index.
2024-01-23 18:18:28 -08:00
Serena Ruan
90f5a1c40e community[minor]: Improve mlflow callback (#15691)
- **Description:** Allow passing run_id to MLflowCallbackHandler to
resume a run instead of creating a new run. Support recording retriever
relevant metrics. Refactor the code to fix some bugs.
---------

Signed-off-by: Serena Ruan <serena.rxy@gmail.com>
2024-01-23 18:16:51 -08:00
Facundo Santiago
92e6a641fd feat: adding paygo api support for Azure ML / Azure AI Studio (#14560)
- **Description:** Introducing support for LLMs and Chat models running
in Azure AI studio and Azure ML using the new deployment mode
pay-as-you-go (model as a service).
- **Issue:** NA
- **Dependencies:** None.
- **Tag maintainer:** @prakharg-msft @gdyre 
- **Twitter handle:** @santiagofacundo

Examples added:
*
[docs/docs/integrations/llms/azure_ml.ipynb](https://github.com/santiagxf/langchain/blob/santiagxf/azureml-endpoints-paygo-community/docs/docs/integrations/chat/azureml_endpoint.ipynb)
*
[docs/docs/integrations/chat/azureml_chat_endpoint.ipynb](https://github.com/santiagxf/langchain/blob/santiagxf/azureml-endpoints-paygo-community/docs/docs/integrations/chat/azureml_chat_endpoint.ipynb)

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-23 17:08:51 -08:00
Davide Menini
9ce177580a community: normalize bedrock embeddings (#15103)
In this PR I added a post-processing function to normalize the
embeddings. This happens only if the new `normalize` flag is `True`.

---------

Co-authored-by: taamedag <Davide.Menini@swisscom.com>
2024-01-23 17:05:24 -08:00
baichuan-assistant
20fcd49348 community: Fix Baichuan Chat. (#15207)
- **Description:** Baichuan Chat (with both Baichuan-Turbo and
Baichuan-Turbo-192K models) has updated their APIs. There are breaking
changes. For example, BAICHUAN_SECRET_KEY is removed in the latest API
but is still required in Langchain. Baichuan's Langchain integration
needs to be updated to the latest version.
  - **Issue:** #15206
  - **Dependencies:** None,
  - **Twitter handle:** None

@hwchase17.

Co-authored-by: BaiChuanHelper <wintergyc@WinterGYCs-MacBook-Pro.local>
2024-01-23 17:01:57 -08:00
gcheron
cfc225ecb3 community: SQLStrStore/SQLDocStore provide an easy SQL alternative to InMemoryStore to persist data remotely in a SQL storage (#15909)
**Description:**

- Implement `SQLStrStore` and `SQLDocStore` classes that inherits from
`BaseStore` to allow to persist data remotely on a SQL server.
- SQL is widely used and sometimes we do not want to install a caching
solution like Redis.
- Multiple issues/comments complain that there is no easy remote and
persistent solution that are not in memory (users want to replace
InMemoryStore), e.g.,
https://github.com/langchain-ai/langchain/issues/14267,
https://github.com/langchain-ai/langchain/issues/15633,
https://github.com/langchain-ai/langchain/issues/14643,
https://stackoverflow.com/questions/77385587/persist-parentdocumentretriever-of-langchain
- This is particularly painful when wanting to use
`ParentDocumentRetriever `
- This implementation is particularly useful when:
     * it's expensive to construct an InMemoryDocstore/dict
     * you want to retrieve documents from remote sources
     * you just want to reuse existing objects
- This implementation integrates well with PGVector, indeed, when using
PGVector, you already have a SQL instance running. `SQLDocStore` is a
convenient way of using this instance to store documents associated to
vectors. An integration example with ParentDocumentRetriever and
PGVector is provided in docs/docs/integrations/stores/sql.ipynb or
[here](https://github.com/gcheron/langchain/blob/sql-store/docs/docs/integrations/stores/sql.ipynb).
- It persists `str` and `Document` objects but can be easily extended.

 **Issue:**

Provide an easy SQL alternative to `InMemoryStore`.

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2024-01-23 16:50:48 -08:00
dudgeon
26b2ad6d5b Fixed typo on quickstart.ipynb (#16482)
- **Description:** Quick typo fix: `inpect` >> `inspect`
  - **Issue:** N/A
  - **Dependencies:** any dependencies required for this change,
  - **Twitter handle:** @geoffdudgeon
2024-01-23 16:50:13 -08:00
Massimiliano Pronesti
e529939c54 feat(llms): support more tasks in HuggingFaceHub LLM and remove deprecated dep (#14406)
- **Description:** this PR upgrades the `HuggingFaceHub` LLM:
   * support more tasks (`translation` and `conversational`)
   * replaced the deprecated `InferenceApi` with `InferenceClient`
* adjusted the overall logic to use the "recommended" model for each
task when no model is provided, and vice-versa.
- **Tag mainter(s)**: @baskaryan @hwchase17
2024-01-23 16:48:56 -08:00
418 changed files with 33887 additions and 6037 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

@@ -1,7 +1,17 @@
name: "\U0001F680 Feature request"
description: Submit a proposal/request for a new LangChain feature
labels: ["02 Feature Request"]
labels: [idea]
body:
- type: checkboxes
id: checks
attributes:
label: Checked
description: Please confirm and check all the following options.
options:
- label: I searched existing ideas and did not find a similar one
required: true
- label: I added a very descriptive title
required: true
- label: I've clearly described the feature request and motivation for it
required: true
- type: textarea
id: feature-request
validations:
@@ -10,7 +20,6 @@ body:
label: Feature request
description: |
A clear and concise description of the feature proposal. Please provide links to any relevant GitHub repos, papers, or other resources if relevant.
- type: textarea
id: motivation
validations:
@@ -19,12 +28,11 @@ body:
label: Motivation
description: |
Please outline the motivation for the proposal. Is your feature request related to a problem? e.g., I'm always frustrated when [...]. If this is related to another GitHub issue, please link here too.
- type: textarea
id: contribution
id: proposal
validations:
required: true
required: false
attributes:
label: Your contribution
label: Proposal (If applicable)
description: |
Is there any way that you could help, e.g. by submitting a PR? Make sure to read the [Contributing Guide](https://python.langchain.com/docs/contributing/)
If you would like to propose a solution, please describe it here.

122
.github/DISCUSSION_TEMPLATE/q-a.yml vendored Normal file
View File

@@ -0,0 +1,122 @@
labels: [Question]
body:
- type: markdown
attributes:
value: |
Thanks for your interest in 🦜️🔗 LangChain!
Please follow these instructions, fill every question, and do every step. 🙏
We're asking for this because answering questions and solving problems in GitHub takes a lot of time --
this is time that we cannot spend on adding new features, fixing bugs, write documentation or reviewing pull requests.
By asking questions in a structured way (following this) it will be much easier to help you.
And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎
As there are too many questions, we will **DISCARD** and close the incomplete ones.
That will allow us (and others) to focus on helping people like you that follow the whole process. 🤓
Relevant links to check before opening a question to see if your question has already been answered, fixed or
if there's another way to solve your problem:
[LangChain documentation with the integrated search](https://python.langchain.com/docs/get_started/introduction),
[API Reference](https://api.python.langchain.com/en/stable/),
[GitHub search](https://github.com/langchain-ai/langchain),
[LangChain Github Discussions](https://github.com/langchain-ai/langchain/discussions),
[LangChain Github Issues](https://github.com/langchain-ai/langchain/issues?q=is%3Aissue),
[LangChain ChatBot](https://chat.langchain.com/)
- type: checkboxes
id: checks
attributes:
label: Checked other resources
description: Please confirm and check all the following options.
options:
- label: I added a very descriptive title to this question.
required: true
- label: I searched the LangChain documentation with the integrated search.
required: true
- label: I used the GitHub search to find a similar question and didn't find it.
required: true
- type: checkboxes
id: help
attributes:
label: Commit to Help
description: |
After submitting this, I commit to one of:
* Read open questions until I find 2 where I can help someone and add a comment to help there.
* I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Once my question is answered, I will mark the answer as "accepted".
options:
- label: I commit to help with one of those options 👆
required: true
- type: textarea
id: example
attributes:
label: Example Code
description: |
Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case.
If a maintainer can copy it, run it, and see it right away, there's a much higher chance that you'll be able to get help.
**Important!**
* Use code tags (e.g., ```python ... ```) to correctly [format your code](https://help.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks#syntax-highlighting).
* INCLUDE the language label (e.g. `python`) after the first three backticks to enable syntax highlighting. (e.g., ```python rather than ```).
* Reduce your code to the minimum required to reproduce the issue if possible. This makes it much easier for others to help you.
* Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.
placeholder: |
from langchain_core.runnables import RunnableLambda
def bad_code(inputs) -> int:
raise NotImplementedError('For demo purpose')
chain = RunnableLambda(bad_code)
chain.invoke('Hello!')
render: python
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: |
What is the problem, question, or error?
Write a short description explaining what you are doing, what you expect to happen, and what is currently happening.
placeholder: |
* I'm trying to use the `langchain` library to do X.
* I expect to see Y.
* Instead, it does Z.
validations:
required: true
- type: textarea
id: system-info
attributes:
label: System Info
description: |
Please share your system info with us.
"pip freeze | grep langchain"
platform (windows / linux / mac)
python version
OR if you're on a recent version of langchain-core you can paste the output of:
python -m langchain_core.sys_info
placeholder: |
"pip freeze | grep langchain"
platform
python version
Alternatively, if you're on a recent version of langchain-core you can paste the output of:
python -m langchain_core.sys_info
These will only surface LangChain packages, don't forget to include any other relevant
packages you're using (if you're not sure what's relevant, you can paste the entire output of `pip freeze`).
validations:
required: true

View File

@@ -1,5 +1,5 @@
name: "\U0001F41B Bug Report"
description: Submit a bug report to help us improve LangChain. To report a security issue, please instead use the security option below.
description: Report a bug in LangChain. To report a security issue, please instead use the security option below. For questions, please use the GitHub Discussions.
labels: ["02 Bug Report"]
body:
- type: markdown
@@ -7,6 +7,11 @@ body:
value: >
Thank you for taking the time to file a bug report.
Use this to report bugs in LangChain.
If you're not certain that your issue is due to a bug in LangChain, please use [GitHub Discussions](https://github.com/langchain-ai/langchain/discussions)
to ask for help with your issue.
Relevant links to check before filing a bug report to see if your issue has already been reported, fixed or
if there's another way to solve your problem:
@@ -14,7 +19,8 @@ body:
[API Reference](https://api.python.langchain.com/en/stable/),
[GitHub search](https://github.com/langchain-ai/langchain),
[LangChain Github Discussions](https://github.com/langchain-ai/langchain/discussions),
[LangChain Github Issues](https://github.com/langchain-ai/langchain/issues?q=is%3Aissue)
[LangChain Github Issues](https://github.com/langchain-ai/langchain/issues?q=is%3Aissue),
[LangChain ChatBot](https://chat.langchain.com/)
- type: checkboxes
id: checks
attributes:
@@ -27,6 +33,8 @@ body:
required: true
- label: I used the GitHub search to find a similar question and didn't find it.
required: true
- label: I am sure that this is a bug in LangChain rather than my code.
required: true
- type: textarea
id: reproduction
validations:
@@ -38,10 +46,12 @@ body:
If a maintainer can copy it, run it, and see it right away, there's a much higher chance that you'll be able to get help.
If you're including an error message, please include the full stack trace not just the last error.
**Important!**
**Important!** Use code tags to correctly format your code. See https://help.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks#syntax-highlighting
Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.
* Use code tags (e.g., ```python ... ```) to correctly [format your code](https://help.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks#syntax-highlighting).
* INCLUDE the language label (e.g. `python`) after the first three backticks to enable syntax highlighting. (e.g., ```python rather than ```).
* Reduce your code to the minimum required to reproduce the issue if possible. This makes it much easier for others to help you.
* Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.
placeholder: |
The following code:
@@ -55,9 +65,16 @@ body:
chain = RunnableLambda(bad_code)
chain.invoke('Hello!')
```
Include both the error and the full stack trace if reporting an exception!
- type: textarea
id: error
validations:
required: false
attributes:
label: Error Message and Stack Trace (if applicable)
description: |
If you are reporting an error, please include the full error message and stack trace.
placeholder: |
Exception + full stack trace
- type: textarea
id: description
attributes:
@@ -76,28 +93,26 @@ body:
id: system-info
attributes:
label: System Info
description: Please share your system info with us.
description: |
Please share your system info with us.
"pip freeze | grep langchain"
platform (windows / linux / mac)
python version
OR if you're on a recent version of langchain-core you can paste the output of:
python -m langchain_core.sys_info
placeholder: |
"pip freeze | grep langchain"
platform
python version
Alternatively, if you're on a recent version of langchain-core you can paste the output of:
python -m langchain_core.sys_info
These will only surface LangChain packages, don't forget to include any other relevant
packages you're using (if you're not sure what's relevant, you can paste the entire output of `pip freeze`).
validations:
required: true
- type: checkboxes
id: related-components
attributes:
label: Related Components
description: "Select the components related to the issue (if applicable):"
options:
- label: "LLMs/Chat Models"
- label: "Embedding Models"
- label: "Prompts / Prompt Templates / Prompt Selectors"
- label: "Output Parsers"
- label: "Document Loaders"
- label: "Vector Stores / Retrievers"
- label: "Memory"
- label: "Agents / Agent Executors"
- label: "Tools / Toolkits"
- label: "Chains"
- label: "Callbacks/Tracing"
- label: "Async"

View File

@@ -7,6 +7,9 @@ contact_links:
- name: Discord
url: https://discord.gg/6adMQxSpJS
about: General community discussions
- name: Feature Request
url: https://www.github.com/langchain-ai/langchain/discussions/categories/ideas
about: Suggest a feature or an idea
- name: Show and tell
about: Show what you built with LangChain
url: https://www.github.com/langchain-ai/langchain/discussions/categories/show-and-tell

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

@@ -55,6 +55,8 @@ jobs:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
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

@@ -174,6 +174,8 @@ jobs:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
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

@@ -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

@@ -4,6 +4,9 @@
# Required
version: 2
formats:
- pdf
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04

View File

@@ -0,0 +1,301 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "d8da6094-30c7-43f3-a608-c91717b673db",
"metadata": {},
"source": [
"# Nomic Embeddings\n",
"\n",
"Nomic has released a new embedding model with strong performance for long context retrieval (8k context window).\n",
"\n",
"## Signup\n",
"\n",
"Get your API token, then run:\n",
"```\n",
"! nomic login\n",
"```\n",
"\n",
"Then run with your generated API token \n",
"```\n",
"! nomic login < token > \n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f737ec15-e9ab-4629-b54c-24be69e8b60b",
"metadata": {},
"outputs": [],
"source": [
"! nomic login"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8ab7434a-2930-42b5-9164-dc2c03abe232",
"metadata": {},
"outputs": [],
"source": [
"! nomic login token"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a3501e2a-4686-4b95-8a1c-f19e035ea354",
"metadata": {},
"outputs": [],
"source": [
"! pip install -U langchain-nomic"
]
},
{
"cell_type": "markdown",
"id": "134475f2-f256-4c13-9712-c55783e6a4e2",
"metadata": {},
"source": [
"## Document Loading\n",
"\n",
"Let's test 3 interesting blog posts."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "01c4d270-171e-45c2-a1b6-e350faa74117",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.document_loaders import WebBaseLoader\n",
"\n",
"urls = [\n",
" \"https://lilianweng.github.io/posts/2023-06-23-agent/\",\n",
" \"https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/\",\n",
" \"https://lilianweng.github.io/posts/2023-10-25-adv-attack-llm/\",\n",
"]\n",
"\n",
"docs = [WebBaseLoader(url).load() for url in urls]\n",
"docs_list = [item for sublist in docs for item in sublist]"
]
},
{
"cell_type": "markdown",
"id": "75ab7f74-873c-4d84-af5a-5cf19c61239d",
"metadata": {},
"source": [
"## Splitting \n",
"\n",
"Long context retrieval "
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f512e128-629e-4304-926f-94fe5c999527",
"metadata": {},
"outputs": [],
"source": [
"from langchain.text_splitter import CharacterTextSplitter\n",
"\n",
"text_splitter = CharacterTextSplitter.from_tiktoken_encoder(\n",
" chunk_size=7500, chunk_overlap=100\n",
")\n",
"doc_splits = text_splitter.split_documents(docs_list)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "d2a69cf0-e3ab-4c92-a1d0-10da45c08b3b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The document is 6562 tokens\n",
"The document is 3037 tokens\n",
"The document is 6092 tokens\n",
"The document is 1050 tokens\n",
"The document is 6933 tokens\n",
"The document is 5560 tokens\n"
]
}
],
"source": [
"import tiktoken\n",
"\n",
"encoding = tiktoken.get_encoding(\"cl100k_base\")\n",
"encoding = tiktoken.encoding_for_model(\"gpt-3.5-turbo\")\n",
"for d in doc_splits:\n",
" print(\"The document is %s tokens\" % len(encoding.encode(d.page_content)))"
]
},
{
"cell_type": "markdown",
"id": "c58d1e9b-e98e-4bd9-b52f-4dfc2a4e69f4",
"metadata": {},
"source": [
"## Index \n",
"\n",
"Nomic embeddings [here](https://docs.nomic.ai/reference/endpoints/nomic-embed-text). "
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "76447866-bf8b-412b-93bc-d6ea8ec35952",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"from langchain_community.vectorstores import Chroma\n",
"from langchain_core.output_parsers import StrOutputParser\n",
"from langchain_core.runnables import RunnableLambda, RunnablePassthrough\n",
"from langchain_nomic import NomicEmbeddings\n",
"from langchain_nomic.embeddings import NomicEmbeddings"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "15b3eab2-2689-49d4-8cb0-67ef2adcbc49",
"metadata": {},
"outputs": [],
"source": [
"# Add to vectorDB\n",
"vectorstore = Chroma.from_documents(\n",
" documents=doc_splits,\n",
" collection_name=\"rag-chroma\",\n",
" embedding=NomicEmbeddings(model=\"nomic-embed-text-v1\"),\n",
")\n",
"retriever = vectorstore.as_retriever()"
]
},
{
"cell_type": "markdown",
"id": "41131122-3591-4566-aac1-ed19d496820a",
"metadata": {},
"source": [
"## RAG Chain\n",
"\n",
"We can use the Mistral `v0.2`, which is [fine-tuned for 32k context](https://x.com/dchaplot/status/1734198245067243629?s=20).\n",
"\n",
"We can [use Ollama](https://ollama.ai/library/mistral) -\n",
"```\n",
"ollama pull mistral:instruct\n",
"```\n",
"\n",
"We can also run [GPT-4 128k](https://openai.com/blog/new-models-and-developer-products-announced-at-devday). "
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "1397de64-5b4a-4001-adc5-570ff8d31ff6",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.chat_models import ChatOllama\n",
"from langchain_core.prompts import ChatPromptTemplate\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"# Prompt\n",
"template = \"\"\"Answer the question based only on the following context:\n",
"{context}\n",
"\n",
"Question: {question}\n",
"\"\"\"\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"# LLM API\n",
"model = ChatOpenAI(temperature=0, model=\"gpt-4-1106-preview\")\n",
"\n",
"# Local LLM\n",
"ollama_llm = \"mistral:instruct\"\n",
"model_local = ChatOllama(model=ollama_llm)\n",
"\n",
"# Chain\n",
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model_local\n",
" | StrOutputParser()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "1548e00c-1ff6-4e88-aa13-69badf2088fb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' Agents, especially those used in artificial intelligence and natural language processing, can have different types of memory. Here are some common types:\\n\\n1. **Short-term memory** or working memory: This is a small capacity, high-turnover memory that holds information temporarily while the agent processes it. Short-term memory is essential for tasks requiring attention and quick response, such as parsing sentences or following instructions.\\n\\n2. **Long-term memory**: This is a large capacity, low-turnover memory where agents store information for extended periods. Long-term memory enables learning from experiences, accessing past knowledge, and improving performance over time.\\n\\n3. **Explicit memory** or declarative memory: Agents use explicit memory to store and recall facts, concepts, and rules that can be expressed in natural language. This type of memory is crucial for problem solving and reasoning.\\n\\n4. **Implicit memory** or procedural memory: Implicit memory refers to the acquisition and retention of skills and habits. The agent learns through repeated experiences without necessarily being aware of it.\\n\\n5. **Connectionist memory**: Connectionist memory, also known as neural networks, is inspired by the structure and function of biological brains. Connectionist models learn and store information in interconnected nodes or artificial neurons. This type of memory enables the model to recognize patterns and generalize knowledge.\\n\\n6. **Hybrid memory systems**: Many advanced agents employ a combination of different memory types to maximize their learning potential and performance. These hybrid systems can integrate short-term, long-term, explicit, implicit, and connectionist memories.'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Question\n",
"chain.invoke(\"What are the types of agent memory?\")"
]
},
{
"cell_type": "markdown",
"id": "5ec5b4c3-757d-44df-92ea-dd5f08017dd6",
"metadata": {},
"source": [
"**Mistral**\n",
"\n",
"Trace: 24k prompt tokens.\n",
"\n",
"* https://smith.langchain.com/public/3e04d475-ea08-4ee3-ae66-6416a93d8b08/r\n",
"\n",
"--- \n",
"\n",
"Some considerations are noted in the [needle in a haystack analysis](https://twitter.com/GregKamradt/status/1722386725635580292?lang=en):\n",
"\n",
"* LLMs may suffer with retrieval from large context depending on where the information is placed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6ffb6b63-17ee-42d8-b1fb-d6a866e98458",
"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.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,464 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "41ce62a8-251f-4f9e-b375-e93a5861c3fe",
"metadata": {},
"source": [
"## Enviornment\n",
"\n",
"`(1) Packages`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e4bef162-17e2-4a27-9a97-1f63dcf9726a",
"metadata": {},
"outputs": [],
"source": [
"! pip[ install langchain_community tiktoken langchain-openai langchainhub chromadb"
]
},
{
"cell_type": "markdown",
"id": "75a8ab66-8477-429f-bbbe-ba439322d085",
"metadata": {},
"source": [
"`(2) LangSmith`\n",
"\n",
"https://docs.smith.langchain.com/"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b76f68a8-4745-4377-8057-6090b87377d1",
"metadata": {},
"outputs": [],
"source": [
"os.environ['LANGCHAIN_TRACING_V2'] = 'true'\n",
"os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com'\n",
"os.environ['LANGCHAIN_API_KEY'] = <your-api-key>"
]
},
{
"cell_type": "markdown",
"id": "1eae0ab7-d43b-43e0-8b99-6122a636fe0c",
"metadata": {},
"source": [
"## Part 1: Overview\n",
" \n",
"[RAG quickstart](https://python.langchain.com/docs/use_cases/question_answering/quickstart)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "98070313-0c2f-4ba6-ae3e-79e2418ce4df",
"metadata": {},
"outputs": [],
"source": [
"import bs4\n",
"from langchain import hub\n",
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"from langchain_community.document_loaders import WebBaseLoader\n",
"from langchain_community.vectorstores import Chroma\n",
"from langchain_core.output_parsers import StrOutputParser\n",
"from langchain_core.runnables import RunnablePassthrough\n",
"from langchain_openai import ChatOpenAI, OpenAIEmbeddings\n",
"\n",
"#### INDEXING ####\n",
"\n",
"# Load Documents\n",
"loader = WebBaseLoader(\n",
" web_paths=(\"https://lilianweng.github.io/posts/2023-06-23-agent/\",),\n",
" bs_kwargs=dict(\n",
" parse_only=bs4.SoupStrainer(\n",
" class_=(\"post-content\", \"post-title\", \"post-header\")\n",
" )\n",
" ),\n",
")\n",
"docs = loader.load()\n",
"\n",
"# Split\n",
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n",
"splits = text_splitter.split_documents(docs)\n",
"\n",
"# Embed\n",
"vectorstore = Chroma.from_documents(documents=splits, \n",
" embedding=OpenAIEmbeddings())\n",
"\n",
"retriever = vectorstore.as_retriever()\n",
"\n",
"#### RETRIEVAL and GENERATION ####\n",
"\n",
"# Prompt\n",
"prompt = hub.pull(\"rlm/rag-prompt\")\n",
"\n",
"# LLM\n",
"llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0)\n",
"\n",
"# Post-processing\n",
"def format_docs(docs):\n",
" return \"\\n\\n\".join(doc.page_content for doc in docs)\n",
"\n",
"# Chain\n",
"rag_chain = (\n",
" {\"context\": retriever | format_docs, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | llm\n",
" | StrOutputParser()\n",
")\n",
"\n",
"# Question\n",
"rag_chain.invoke(\"What is Task Decomposition?\")"
]
},
{
"cell_type": "markdown",
"id": "18e8e856-bafd-469e-b99a-11596b18aad4",
"metadata": {},
"source": [
"## Part 2: Indexing"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "edd7beeb-21fa-4f4b-b8fa-5a4f70489a16",
"metadata": {},
"outputs": [],
"source": [
"# Documents\n",
"question = \"What kinds of pets do I like?\"\n",
"document = \"My favorite pet is a cat.\""
]
},
{
"cell_type": "markdown",
"id": "e0552ea4-935d-4dfa-bd2b-56d148e96304",
"metadata": {},
"source": [
"[Count tokens](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) considering [~4 char / token](https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "df119cca-1676-4caa-bad4-11805d69e616",
"metadata": {},
"outputs": [],
"source": [
"import tiktoken\n",
"\n",
"def num_tokens_from_string(string: str, encoding_name: str) -> int:\n",
" \"\"\"Returns the number of tokens in a text string.\"\"\"\n",
" encoding = tiktoken.get_encoding(encoding_name)\n",
" num_tokens = len(encoding.encode(string))\n",
" return num_tokens\n",
"\n",
"num_tokens_from_string(question, \"cl100k_base\")"
]
},
{
"cell_type": "markdown",
"id": "4f04fd74-829f-472c-a1bc-ec6521a0529f",
"metadata": {},
"source": [
"[Text embedding models](https://python.langchain.com/docs/integrations/text_embedding/openai)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6bd98786-755d-4d49-ba97-30c5a623b74e",
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import OpenAIEmbeddings\n",
"embd = OpenAIEmbeddings()\n",
"query_result = embd.embed_query(question)\n",
"document_result = embd.embed_query(document)\n",
"len(query_result)"
]
},
{
"cell_type": "markdown",
"id": "f5e0e35f-6861-4c5e-9301-04fd5408f8f8",
"metadata": {},
"source": [
"[Cosine similarity](https://platform.openai.com/docs/guides/embeddings/frequently-asked-questions) is reccomended (1 indicates identical)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b8001998-b08c-4560-b124-bfa1fced8958",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"def cosine_similarity(vec1, vec2):\n",
" dot_product = np.dot(vec1, vec2)\n",
" norm_vec1 = np.linalg.norm(vec1)\n",
" norm_vec2 = np.linalg.norm(vec2)\n",
" return dot_product / (norm_vec1 * norm_vec2)\n",
"\n",
"similarity = cosine_similarity(query_result, document_result)\n",
"print(\"Cosine Similarity:\", similarity)"
]
},
{
"cell_type": "markdown",
"id": "8aea73bc-98e3-4fdc-ba72-d190736bed20",
"metadata": {},
"source": [
"[Document Loaders](https://python.langchain.com/docs/integrations/document_loaders/)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5778c31a-6138-4130-8865-31a08e82b9fb",
"metadata": {},
"outputs": [],
"source": [
"#### INDEXING ####\n",
"\n",
"# Load blog\n",
"import bs4\n",
"from langchain_community.document_loaders import WebBaseLoader\n",
"loader = WebBaseLoader(\n",
" web_paths=(\"https://lilianweng.github.io/posts/2023-06-23-agent/\",),\n",
" bs_kwargs=dict(\n",
" parse_only=bs4.SoupStrainer(\n",
" class_=(\"post-content\", \"post-title\", \"post-header\")\n",
" )\n",
" ),\n",
")\n",
"blog_docs = loader.load()"
]
},
{
"cell_type": "markdown",
"id": "798e731e-c6ff-46e3-a8bc-386832362af2",
"metadata": {},
"source": [
"[Splitter](https://python.langchain.com/docs/modules/data_connection/document_transformers/recursive_text_splitter)\n",
"\n",
"> This text splitter is the recommended one for generic text. It is parameterized by a list of characters. It tries to split on them in order until the chunks are small enough. The default list is [\"\\n\\n\", \"\\n\", \" \", \"\"]. This has the effect of trying to keep all paragraphs (and then sentences, and then words) together as long as possible, as those would generically seem to be the strongest semantically related pieces of text."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e668d339-3951-4662-8387-c3d296646906",
"metadata": {},
"outputs": [],
"source": [
"# Split\n",
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(\n",
" chunk_size=300, \n",
" chunk_overlap=50)\n",
"\n",
"# Make splits\n",
"splits = text_splitter.split_documents(blog_docs)"
]
},
{
"cell_type": "markdown",
"id": "427303a1-3ed4-430c-bfc7-cb3e48022f1d",
"metadata": {},
"source": [
"[Vectorstores](https://python.langchain.com/docs/integrations/vectorstores/)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "baa90aaf-cc1b-46a1-9fba-cf20804dcb41",
"metadata": {},
"outputs": [],
"source": [
"# Index\n",
"from langchain_openai import OpenAIEmbeddings\n",
"from langchain_community.vectorstores import Chroma\n",
"vectorstore = Chroma.from_documents(documents=splits, \n",
" embedding=OpenAIEmbeddings())\n",
"\n",
"retriever = vectorstore.as_retriever()"
]
},
{
"cell_type": "markdown",
"id": "ba890329-1411-4922-bd27-fe0490dd1208",
"metadata": {},
"source": [
"## Part 3: Retrieval"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "57c2de7a-93e6-4072-bc5b-db6516f96dda",
"metadata": {},
"outputs": [],
"source": [
"docs = retriever.get_relevant_documents(\"What is Task Decomposition?\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0582e6bd-8e97-4cf4-80b9-a04434ea7135",
"metadata": {},
"outputs": [],
"source": [
"len(docs)"
]
},
{
"cell_type": "markdown",
"id": "beda1b07-7bd2-4f5b-8d44-1fc52f5d2ce2",
"metadata": {},
"source": [
"## Part 4: Generation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8beb6c14-5e18-43e7-9d04-59e3b8a81cc9",
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"from langchain.prompts import ChatPromptTemplate\n",
"\n",
"# Prompt\n",
"template = \"\"\"Answer the question based only on the following context:\n",
"{context}\n",
"\n",
"Question: {question}\n",
"\"\"\"\n",
"\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"prompt"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e4461264-5cac-479a-917c-9bf589826da4",
"metadata": {},
"outputs": [],
"source": [
"# LLM\n",
"llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "55d6629f-18ec-4372-a557-b254fbb1dd2d",
"metadata": {},
"outputs": [],
"source": [
"# Chain\n",
"chain = prompt | llm"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94470770-8df4-4359-9504-ef6c8b3137ff",
"metadata": {},
"outputs": [],
"source": [
"# Run\n",
"chain.invoke({\"context\":docs,\"question\":\"What is Task Decomposition?\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "65770e2d-3d5e-4371-abc9-0aeca9646885",
"metadata": {},
"outputs": [],
"source": [
"from langchain import hub\n",
"prompt_hub_rag = hub.pull(\"rlm/rag-prompt\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f53e5840-0a0f-4428-a4a4-6922800aff89",
"metadata": {},
"outputs": [],
"source": [
"prompt_hub_rag"
]
},
{
"cell_type": "markdown",
"id": "8ffe29a1-5527-419e-9f12-8a3061d12885",
"metadata": {},
"source": [
"[RAG chains](https://python.langchain.com/docs/expression_language/get_started#rag-search-example)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8208a8bc-c75f-4e8e-8601-680746cd6276",
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.output_parsers import StrOutputParser\n",
"from langchain_core.runnables import RunnablePassthrough\n",
"\n",
"rag_chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | llm\n",
" | StrOutputParser()\n",
")\n",
"\n",
"rag_chain.invoke(\"What is Task Decomposition?\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d21023fb-c570-4163-aa46-56dae4c67122",
"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.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

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]
```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -85,21 +85,10 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"id": "2448b6c2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Graph(nodes={'7308e6063c6d40818c5a0cc1cc7444f2': Node(id='7308e6063c6d40818c5a0cc1cc7444f2', data=<class 'pydantic.main.RunnableParallel<context,question>Input'>), '292bbd8021d44ec3a31fbe724d9002c1': Node(id='292bbd8021d44ec3a31fbe724d9002c1', data=<class 'pydantic.main.RunnableParallel<context,question>Output'>), '9212f219cf05488f95229c56ea02b192': Node(id='9212f219cf05488f95229c56ea02b192', data=VectorStoreRetriever(tags=['FAISS', 'OpenAIEmbeddings'], vectorstore=<langchain_community.vectorstores.faiss.FAISS object at 0x117334f70>)), 'c7a8e65fa5cf44b99dbe7d1d6e36886f': Node(id='c7a8e65fa5cf44b99dbe7d1d6e36886f', data=RunnablePassthrough()), '818b9bfd40a341008373d5b9f9d0784b': Node(id='818b9bfd40a341008373d5b9f9d0784b', data=ChatPromptTemplate(input_variables=['context', 'question'], messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['context', 'question'], template='Answer the question based only on the following context:\\n{context}\\n\\nQuestion: {question}\\n'))])), 'b9f1d3ddfa6b4334a16ea439df22b11e': Node(id='b9f1d3ddfa6b4334a16ea439df22b11e', data=ChatOpenAI(client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, openai_api_key='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', openai_proxy='')), '2bf84f6355c44731848345ca7d0f8ab9': Node(id='2bf84f6355c44731848345ca7d0f8ab9', data=StrOutputParser()), '1aeb2da5da5a43bb8771d3f338a473a2': Node(id='1aeb2da5da5a43bb8771d3f338a473a2', data=<class 'pydantic.main.StrOutputParserOutput'>)}, edges=[Edge(source='7308e6063c6d40818c5a0cc1cc7444f2', target='9212f219cf05488f95229c56ea02b192'), Edge(source='9212f219cf05488f95229c56ea02b192', target='292bbd8021d44ec3a31fbe724d9002c1'), Edge(source='7308e6063c6d40818c5a0cc1cc7444f2', target='c7a8e65fa5cf44b99dbe7d1d6e36886f'), Edge(source='c7a8e65fa5cf44b99dbe7d1d6e36886f', target='292bbd8021d44ec3a31fbe724d9002c1'), Edge(source='292bbd8021d44ec3a31fbe724d9002c1', target='818b9bfd40a341008373d5b9f9d0784b'), Edge(source='818b9bfd40a341008373d5b9f9d0784b', target='b9f1d3ddfa6b4334a16ea439df22b11e'), Edge(source='2bf84f6355c44731848345ca7d0f8ab9', target='1aeb2da5da5a43bb8771d3f338a473a2'), Edge(source='b9f1d3ddfa6b4334a16ea439df22b11e', target='2bf84f6355c44731848345ca7d0f8ab9')])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"outputs": [],
"source": [
"chain.get_graph()"
]

View File

@@ -30,7 +30,7 @@
"- [`ainvoke`](#async-invoke): call the chain on an input async\n",
"- [`abatch`](#async-batch): call the chain on a list of inputs async\n",
"- [`astream_log`](#async-stream-intermediate-steps): stream back intermediate steps as they happen, in addition to the final response\n",
"- [`astream_events`](#async-stream-events): **beta** stream events as they happen in the chain (introduced in `langchain-core` 0.2.0)\n",
"- [`astream_events`](#async-stream-events): **beta** stream events as they happen in the chain (introduced in `langchain-core` 0.1.14)\n",
"\n",
"The **input type** and **output type** varies by component:\n",
"\n",

File diff suppressed because it is too large Load Diff

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

@@ -35,6 +35,22 @@
"from langchain_openai import OpenAI"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3dd69cb4",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"# get a new token: https://dashboard.cohere.ai/\n",
"os.environ[\"COHERE_API_KEY\"] = getpass.getpass(\"Cohere API Key:\")\n",
"os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"Open API Key:\")\n",
"os.environ[\"HUGGINGFACEHUB_API_TOKEN\"] = getpass.getpass(\"Hugging Face API Key:\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
@@ -44,7 +60,7 @@
"source": [
"llms = [\n",
" OpenAI(temperature=0),\n",
" Cohere(model=\"command-xlarge-20221108\", max_tokens=20, temperature=0),\n",
" Cohere(temperature=0),\n",
" HuggingFaceHub(repo_id=\"google/flan-t5-xl\", model_kwargs={\"temperature\": 1}),\n",
"]"
]
@@ -160,7 +176,7 @@
" llm=open_ai_llm, search_chain=search, verbose=True\n",
")\n",
"\n",
"cohere_llm = Cohere(temperature=0, model=\"command-xlarge-20221108\")\n",
"cohere_llm = Cohere(temperature=0)\n",
"search = SerpAPIWrapper()\n",
"self_ask_with_search_cohere = SelfAskWithSearchChain(\n",
" llm=cohere_llm, search_chain=search, verbose=True\n",
@@ -241,14 +257,6 @@
"source": [
"model_lab.compare(\"What is the hometown of the reigning men's U.S. Open champion?\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94159131",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@@ -22,44 +22,84 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"id": "d4a7c55d-b235-4ca4-a579-c90cc9570da9",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:00.590587Z",
"start_time": "2024-01-19T11:25:00.127293Z"
},
"tags": []
},
"outputs": [],
"source": [
"from langchain.schema import HumanMessage\n",
"from langchain_community.chat_models import ChatAnthropic"
"from langchain_community.chat_models import ChatAnthropic\n",
"from langchain_core.prompts import ChatPromptTemplate"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"id": "70cf04e8-423a-4ff6-8b09-f11fb711c817",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:04.349676Z",
"start_time": "2024-01-19T11:25:03.964930Z"
},
"tags": []
},
"outputs": [],
"source": [
"chat = ChatAnthropic()"
"chat = ChatAnthropic(temperature=0, model_name=\"claude-2\")"
]
},
{
"cell_type": "markdown",
"id": "d1f9df276476f0bc",
"metadata": {
"collapsed": false
},
"source": [
"The code provided assumes that your ANTHROPIC_API_KEY is set in your environment variables. If you would like to manually specify your API key and also choose a different model, you can use the following code:\n",
"```python\n",
"chat = ChatAnthropic(temperature=0, anthropic_api_key=\"YOUR_API_KEY\", model_name=\"claude-instant-1.2\")\n",
"\n",
"```\n",
"Please note that the default model is \"claude-2,\" and you can check the available models at [here](https://docs.anthropic.com/claude/reference/selecting-a-model)."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"id": "8199ef8f-eb8b-4253-9ea0-6c24a013ca4c",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:07.274418Z",
"start_time": "2024-01-19T11:25:05.898031Z"
},
"tags": []
},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": "AIMessage(content=' 저는 파이썬을 좋아합니다.')"
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
"]\n",
"chat.invoke(messages)"
"system = \"You are a helpful assistant that translates {input_language} to {output_language}.\"\n",
"human = \"{text}\"\n",
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n",
"\n",
"chain = prompt | chat\n",
"chain.invoke({\n",
" \"input_language\": \"English\",\n",
" \"output_language\": \"Korean\",\n",
" \"text\": \"I love Python\",\n",
"})"
]
},
{
@@ -72,44 +112,78 @@
},
{
"cell_type": "code",
"execution_count": null,
"id": "93a21c5c-6ef9-4688-be60-b2e1f94842fb",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.callbacks.manager import CallbackManager\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"id": "c5fac0e9-05a4-4fc1-a3b3-e5bbb24b971b",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:10.448733Z",
"start_time": "2024-01-19T11:25:08.866277Z"
},
"tags": []
},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": "AIMessage(content=\" Why don't bears like fast food? Because they can't catch it!\")"
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await chat.ainvoke([messages])"
"chat = ChatAnthropic(temperature=0, model_name=\"claude-2\")\n",
"prompt = ChatPromptTemplate.from_messages([(\"human\", \"Tell me a joke about {topic}\")])\n",
"chain = prompt | chat\n",
"await chain.ainvoke({\"topic\": \"bear\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"id": "025be980-e50d-4a68-93dc-c9c7b500ce34",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:24.438696Z",
"start_time": "2024-01-19T11:25:14.687480Z"
},
"tags": []
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" Here are some of the most famous tourist attractions in Japan:\n",
"\n",
"- Tokyo - Tokyo Tower, Tokyo Skytree, Imperial Palace, Sensoji Temple, Meiji Shrine, Shibuya Crossing\n",
"\n",
"- Kyoto - Kinkakuji (Golden Pavilion), Fushimi Inari Shrine, Kiyomizu-dera Temple, Arashiyama Bamboo Grove, Gion Geisha District\n",
"\n",
"- Osaka - Osaka Castle, Dotonbori, Universal Studios Japan, Osaka Aquarium Kaiyukan \n",
"\n",
"- Hiroshima - Hiroshima Peace Memorial Park and Museum, Itsukushima Shrine (Miyajima Island)\n",
"\n",
"- Mount Fuji - Iconic and famous mountain, popular for hiking and viewing from places like Hakone and Kawaguchiko Lake\n",
"\n",
"- Himeji - Himeji Castle, one of Japan's most impressive feudal castles\n",
"\n",
"- Nara - Todaiji Temple, Nara Park with its bowing deer, Horyuji Temple with some of world's oldest wooden structures \n",
"\n",
"- Nikko - Elaborate shrines and temples nestled around Nikko National Park\n",
"\n",
"- Sapporo - Snow"
]
}
],
"source": [
"chat = ChatAnthropic(\n",
" streaming=True,\n",
" verbose=True,\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),\n",
"chat = ChatAnthropic(temperature=0.3, model_name=\"claude-2\")\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"human\", \"Give me a list of famous tourist attractions in Japan\")]\n",
")\n",
"chat.stream(messages)"
"chain = prompt | chat\n",
"for chunk in chain.stream({}):\n",
" print(chunk.content, end=\"\", flush=True)"
]
},
{
@@ -134,15 +208,130 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"id": "07c47c2a",
"metadata": {},
"outputs": [],
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:25.288133Z",
"start_time": "2024-01-19T11:25:24.438968Z"
}
},
"outputs": [
{
"data": {
"text/plain": "AIMessage(content='파이썬을 사랑합니다.')"
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_anthropic import ChatAnthropicMessages\n",
"\n",
"chat = ChatAnthropicMessages(model_name=\"claude-instant-1.2\")\n",
"chat.invoke(messages)"
"system = (\n",
" \"You are a helpful assistant that translates {input_language} to {output_language}.\"\n",
")\n",
"human = \"{text}\"\n",
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n",
"\n",
"chain = prompt | chat\n",
"chain.invoke(\n",
" {\n",
" \"input_language\": \"English\",\n",
" \"output_language\": \"Korean\",\n",
" \"text\": \"I love Python\",\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"id": "19e53d75935143fd",
"metadata": {
"collapsed": false
},
"source": [
"ChatAnthropicMessages also requires the anthropic_api_key argument, or the ANTHROPIC_API_KEY environment variable must be set. \n",
"\n",
"ChatAnthropicMessages also supports async and streaming functionality:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "e20a139d30e3d333",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:26.012325Z",
"start_time": "2024-01-19T11:25:25.288358Z"
},
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": "AIMessage(content='파이썬을 사랑합니다.')"
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await chain.ainvoke(\n",
" {\n",
" \"input_language\": \"English\",\n",
" \"output_language\": \"Korean\",\n",
" \"text\": \"I love Python\",\n",
" }\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "6f34f1073d7e7120",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:28.323455Z",
"start_time": "2024-01-19T11:25:26.012040Z"
},
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Here are some of the most famous tourist attractions in Japan:\n",
"\n",
"- Tokyo Tower - A communication and observation tower in Tokyo modeled after the Eiffel Tower. It offers stunning views of the city.\n",
"\n",
"- Mount Fuji - Japan's highest and most famous mountain. It's a iconic symbol of Japan and a UNESCO World Heritage Site. \n",
"\n",
"- Itsukushima Shrine (Miyajima) - A shrine located on an island in Hiroshima prefecture, known for its \"floating\" torii gate that seems to float on water during high tide.\n",
"\n",
"- Himeji Castle - A UNESCO World Heritage Site famous for having withstood numerous battles without destruction to its intricate white walls and sloping, triangular roofs. \n",
"\n",
"- Kawaguchiko Station - Near Mount Fuji, this area is known for its scenic Fuji Five Lakes region. \n",
"\n",
"- Hiroshima Peace Memorial Park and Museum - Commemorates the world's first atomic bombing in Hiroshima on August 6, 1945. \n",
"\n",
"- Arashiyama Bamboo Grove - A renowned bamboo forest located in Kyoto that draws many visitors.\n",
"\n",
"- Kegon Falls - One of Japan's largest waterfalls"
]
}
],
"source": [
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"human\", \"Give me a list of famous tourist attractions in Japan\")]\n",
")\n",
"chain = prompt | chat\n",
"for chunk in chain.stream({}):\n",
" print(chunk.content, end=\"\", flush=True)"
]
}
],

View File

@@ -15,9 +15,9 @@
"source": [
"# AzureMLChatOnlineEndpoint\n",
"\n",
">[Azure Machine Learning](https://azure.microsoft.com/en-us/products/machine-learning/) is a platform used to build, train, and deploy machine learning models. Users can explore the types of models to deploy in the Model Catalog, which provides Azure Foundation Models and OpenAI Models. `Azure Foundation Models` include various open-source models and popular Hugging Face models. Users can also import models of their liking into AzureML.\n",
">[Azure Machine Learning](https://azure.microsoft.com/en-us/products/machine-learning/) is a platform used to build, train, and deploy machine learning models. Users can explore the types of models to deploy in the Model Catalog, which provides foundational and general purpose models from different providers.\n",
">\n",
">[Azure Machine Learning Online Endpoints](https://learn.microsoft.com/en-us/azure/machine-learning/concept-endpoints). After you train machine learning models or pipelines, you need to deploy them to production so that others can use them for inference. Inference is the process of applying new input data to the machine learning model or pipeline to generate outputs. While these outputs are typically referred to as \"predictions,\" inferencing can be used to generate outputs for other machine learning tasks, such as classification and clustering. In `Azure Machine Learning`, you perform inferencing by using endpoints and deployments. `Endpoints` and `Deployments` allow you to decouple the interface of your production workload from the implementation that serves it.\n",
">In general, you need to deploy models in order to consume its predictions (inference). In `Azure Machine Learning`, [Online Endpoints](https://learn.microsoft.com/en-us/azure/machine-learning/concept-endpoints) are used to deploy these models with a real-time serving. They are based on the ideas of `Endpoints` and `Deployments` which allow you to decouple the interface of your production workload from the implementation that serves it.\n",
"\n",
"This notebook goes over how to use a chat model hosted on an `Azure Machine Learning Endpoint`."
]
@@ -37,10 +37,11 @@
"source": [
"## Set up\n",
"\n",
"To use the wrapper, you must [deploy a model on AzureML](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-use-foundation-models?view=azureml-api-2#deploying-foundation-models-to-endpoints-for-inferencing) and obtain the following parameters:\n",
"You must [deploy a model on Azure ML](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-use-foundation-models?view=azureml-api-2#deploying-foundation-models-to-endpoints-for-inferencing) or [to Azure AI studio](https://learn.microsoft.com/en-us/azure/ai-studio/how-to/deploy-models-open) and obtain the following parameters:\n",
"\n",
"* `endpoint_api_key`: The API key provided by the endpoint\n",
"* `endpoint_url`: The REST endpoint url provided by the endpoint"
"* `endpoint_url`: The REST endpoint url provided by the endpoint.\n",
"* `endpoint_api_type`: Use `endpoint_type='realtime'` when deploying models to **Realtime endpoints** (hosted managed infrastructure). Use `endpoint_type='serverless'` when deploying models using the **Pay-as-you-go** offering (model as a service).\n",
"* `endpoint_api_key`: The API key provided by the endpoint"
]
},
{
@@ -51,7 +52,40 @@
"\n",
"The `content_formatter` parameter is a handler class for transforming the request and response of an AzureML endpoint to match with required schema. Since there are a wide range of models in the model catalog, each of which may process data differently from one another, a `ContentFormatterBase` class is provided to allow users to transform data to their liking. The following content formatters are provided:\n",
"\n",
"* `LLamaContentFormatter`: Formats request and response data for LLaMa2-chat"
"* `LLamaChatContentFormatter`: Formats request and response data for LLaMa2-chat\n",
"\n",
"*Note: `langchain.chat_models.azureml_endpoint.LLamaContentFormatter` is being deprecated and replaced with `langchain.chat_models.azureml_endpoint.LLamaChatContentFormatter`.*\n",
"\n",
"You can implement custom content formatters specific for your model deriving from the class `langchain_community.llms.azureml_endpoint.ContentFormatterBase`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Examples\n",
"\n",
"The following section cotain examples about how to use this class:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.schema import HumanMessage\n",
"from langchain_community.chat_models.azureml_endpoint import (\n",
" AzureMLEndpointApiType,\n",
" LlamaChatContentFormatter,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Chat completions with real-time endpoints"
]
},
{
@@ -76,11 +110,79 @@
"\n",
"chat = AzureMLChatOnlineEndpoint(\n",
" endpoint_url=\"https://<your-endpoint>.<your_region>.inference.ml.azure.com/score\",\n",
" endpoint_api_type=AzureMLEndpointApiType.realtime,\n",
" endpoint_api_key=\"my-api-key\",\n",
" content_formatter=LlamaContentFormatter,\n",
" content_formatter=LlamaChatContentFormatter(),\n",
")\n",
"response = chat(\n",
" messages=[HumanMessage(content=\"Will the Collatz conjecture ever be solved?\")]\n",
"response = chat.invoke(\n",
" [HumanMessage(content=\"Will the Collatz conjecture ever be solved?\")]\n",
")\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Chat completions with pay-as-you-go deployments (model as a service)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"chat = AzureMLChatOnlineEndpoint(\n",
" endpoint_url=\"https://<your-endpoint>.<your_region>.inference.ml.azure.com/v1/chat/completions\",\n",
" endpoint_api_type=AzureMLEndpointApiType.serverless,\n",
" endpoint_api_key=\"my-api-key\",\n",
" content_formatter=LlamaChatContentFormatter,\n",
")\n",
"response = chat.invoke(\n",
" [HumanMessage(content=\"Will the Collatz conjecture ever be solved?\")]\n",
")\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you need to pass additional parameters to the model, use `model_kwards` argument:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"chat = AzureMLChatOnlineEndpoint(\n",
" endpoint_url=\"https://<your-endpoint>.<your_region>.inference.ml.azure.com/v1/chat/completions\",\n",
" endpoint_api_type=AzureMLEndpointApiType.serverless,\n",
" endpoint_api_key=\"my-api-key\",\n",
" content_formatter=LlamaChatContentFormatter,\n",
" model_kwargs={\"temperature\": 0.8},\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Parameters can also be passed during invocation:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"response = chat.invoke(\n",
" [HumanMessage(content=\"Will the Collatz conjecture ever be solved?\")],\n",
" max_tokens=512,\n",
")\n",
"response"
]

View File

@@ -13,7 +13,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# ChatBaichuan\n",
"# Chat with Baichuan-192K\n",
"\n",
"Baichuan chat models API by Baichuan Intelligent Technology. For more information, see [https://platform.baichuan-ai.com/docs/api](https://platform.baichuan-ai.com/docs/api)"
]
@@ -44,20 +44,25 @@
},
"outputs": [],
"source": [
"chat = ChatBaichuan(\n",
" baichuan_api_key=\"YOUR_API_KEY\", baichuan_secret_key=\"YOUR_SECRET_KEY\"\n",
")"
"chat = ChatBaichuan(baichuan_api_key=\"YOUR_API_KEY\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"or you can set `api_key` and `secret_key` in your environment variables\n",
"```bash\n",
"export BAICHUAN_API_KEY=YOUR_API_KEY\n",
"export BAICHUAN_SECRET_KEY=YOUR_SECRET_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\""
]
},
{
@@ -91,7 +96,7 @@
"collapsed": false
},
"source": [
"## For ChatBaichuan with Streaming"
"## Chat with Baichuan-192K with Streaming"
]
},
{
@@ -108,7 +113,6 @@
"source": [
"chat = ChatBaichuan(\n",
" baichuan_api_key=\"YOUR_API_KEY\",\n",
" baichuan_secret_key=\"YOUR_SECRET_KEY\",\n",
" streaming=True,\n",
")"
]

View File

@@ -0,0 +1,272 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Eden AI"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Eden AI is revolutionizing the AI landscape by uniting the best AI providers, empowering users to unlock limitless possibilities and tap into the true potential of artificial intelligence. With an all-in-one comprehensive and hassle-free platform, it allows users to deploy AI features to production lightning fast, enabling effortless access to the full breadth of AI capabilities via a single API. (website: https://edenai.co/)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This example goes over how to use LangChain to interact with Eden AI models\n",
"\n",
"-----------------------------------------------------------------------------------"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`EdenAI` goes beyond mere model invocation. It empowers you with advanced features, including:\n",
"\n",
"- **Multiple Providers**: Gain access to a diverse range of language models offered by various providers, giving you the freedom to choose the best-suited model for your use case.\n",
"\n",
"- **Fallback Mechanism**: Set a fallback mechanism to ensure seamless operations even if the primary provider is unavailable, you can easily switches to an alternative provider.\n",
"\n",
"- **Usage Tracking**: Track usage statistics on a per-project and per-API key basis. This feature allows you to monitor and manage resource consumption effectively.\n",
"\n",
"- **Monitoring and Observability**: `EdenAI` provides comprehensive monitoring and observability tools on the platform. Monitor the performance of your language models, analyze usage patterns, and gain valuable insights to optimize your applications.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Accessing the EDENAI's API requires an API key, \n",
"\n",
"which you can get by creating an account https://app.edenai.run/user/register and heading here https://app.edenai.run/admin/iam/api-keys\n",
"\n",
"Once we have a key we'll want to set it as an environment variable by running:\n",
"\n",
"```bash\n",
"export EDENAI_API_KEY=\"...\"\n",
"```\n",
"\n",
"You can find more details on the API reference : https://docs.edenai.co/reference"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you'd prefer not to set an environment variable you can pass the key in directly via the edenai_api_key named parameter\n",
"\n",
" when initiating the EdenAI Chat Model class."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.chat_models.edenai import ChatEdenAI\n",
"from langchain_core.messages import HumanMessage"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"chat = ChatEdenAI(\n",
" edenai_api_key=\"...\", provider=\"openai\", temperature=0.2, max_tokens=250\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='Hello! How can I assist you today?')"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [HumanMessage(content=\"Hello !\")]\n",
"chat.invoke(messages)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='Hello! How can I assist you today?')"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await chat.ainvoke(messages)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Streaming and Batching\n",
"\n",
"`ChatEdenAI` supports streaming and batching. Below is an example."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello! How can I assist you today?"
]
}
],
"source": [
"for chunk in chat.stream(messages):\n",
" print(chunk.content, end=\"\", flush=True)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[AIMessage(content='Hello! How can I assist you today?')]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat.batch([messages])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fallback mecanism\n",
"\n",
"With Eden AI you can set a fallback mechanism to ensure seamless operations even if the primary provider is unavailable, you can easily switches to an alternative provider."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"chat = ChatEdenAI(\n",
" edenai_api_key=\"...\",\n",
" provider=\"openai\",\n",
" temperature=0.2,\n",
" max_tokens=250,\n",
" fallback_providers=\"google\",\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example, you can use Google as a backup provider if OpenAI encounters any issues.\n",
"\n",
"For more information and details about Eden AI, check out this link: : https://docs.edenai.co/docs/additional-parameters"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Chaining Calls\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.prompts import ChatPromptTemplate\n",
"\n",
"prompt = ChatPromptTemplate.from_template(\n",
" \"What is a good name for a company that makes {product}?\"\n",
")\n",
"chain = prompt | chat"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='VitalBites')"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"product\": \"healthy snacks\"})"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "langchain-pr",
"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.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -18,6 +18,14 @@
"\n",
"Note: This is separate from the Google PaLM integration. Google has chosen to offer an enterprise version of PaLM through GCP, and this supports the models made available through there. \n",
"\n",
"ChatVertexAI exposes all foundational models available in Google Cloud:\n",
"\n",
"- Gemini (`gemini-pro` and `gemini-pro-vision`)\n",
"- PaLM 2 for Text (`text-bison`)\n",
"- Codey for Code Generation (`codechat-bison`)\n",
"\n",
"For a full and updated list of available models visit [VertexAI documentation](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/overview).\n",
"\n",
"By default, Google Cloud [does not use](https://cloud.google.com/vertex-ai/docs/generative-ai/data-governance#foundation_model_development) customer data to train its foundation models as part of Google Cloud`s AI/ML Privacy Commitment. More details about how Google processes data can also be found in [Google's Customer Data Processing Addendum (CDPA)](https://cloud.google.com/terms/data-processing-addendum).\n",
"\n",
"To use `Google Cloud Vertex AI` PaLM you must have the `langchain-google-vertexai` Python package installed and either:\n",
@@ -35,9 +43,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": []
},
"metadata": {},
"outputs": [],
"source": [
"%pip install --upgrade --quiet langchain-google-vertexai"
@@ -45,7 +51,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -64,7 +70,7 @@
"AIMessage(content=\" J'aime la programmation.\")"
]
},
"execution_count": 8,
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
@@ -98,7 +104,7 @@
"AIMessage(content=\"J'aime la programmation.\")"
]
},
"execution_count": 9,
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
@@ -123,7 +129,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {},
"outputs": [
{
@@ -132,7 +138,7 @@
"AIMessage(content=' プログラミングが大好きです')"
]
},
"execution_count": 4,
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
@@ -159,28 +165,17 @@
},
{
"cell_type": "markdown",
"metadata": {
"execution": {
"iopub.execute_input": "2023-06-17T21:09:25.423568Z",
"iopub.status.busy": "2023-06-17T21:09:25.423213Z",
"iopub.status.idle": "2023-06-17T21:09:25.429641Z",
"shell.execute_reply": "2023-06-17T21:09:25.429060Z",
"shell.execute_reply.started": "2023-06-17T21:09:25.423546Z"
},
"tags": []
},
"metadata": {},
"source": [
"## Code generation chat models\n",
"You can now leverage the Codey API for code chat within Vertex AI. The model name is:\n",
"- codechat-bison: for code assistance"
"You can now leverage the Codey API for code chat within Vertex AI. The model available is:\n",
"- `codechat-bison`: for code assistance"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": []
},
"metadata": {},
"outputs": [
{
"name": "stdout",
@@ -242,7 +237,7 @@
" model_name=\"codechat-bison\", max_output_tokens=1000, temperature=0.5\n",
")\n",
"\n",
"message = chat.invoke(\"Write a Python function to identify all prime numbers\")\n",
"message = chat.invoke(\"Write a Python function generating all prime numbers\")\n",
"print(message.content)"
]
},
@@ -266,7 +261,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": null,
"metadata": {},
"outputs": [
{
@@ -320,7 +315,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {},
"outputs": [
{
@@ -353,7 +348,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {},
"outputs": [
{
@@ -362,7 +357,7 @@
"MyModel(name='Erick', age=27)"
]
},
"execution_count": 3,
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
@@ -389,7 +384,7 @@
"source": [
"## Asynchronous calls\n",
"\n",
"We can make asynchronous calls via the Runnables [Async Interface](/docs/expression_language/interface)"
"We can make asynchronous calls via the Runnables [Async Interface](/docs/expression_language/interface)."
]
},
{
@@ -414,10 +409,10 @@
{
"data": {
"text/plain": [
"AIMessage(content=' Why do you love programming?')"
"AIMessage(content=' अहं प्रोग्रामनं प्रेमामि')"
]
},
"execution_count": 6,
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
@@ -428,6 +423,10 @@
")\n",
"human = \"{text}\"\n",
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n",
"\n",
"chat = ChatVertexAI(\n",
" model_name=\"chat-bison\", max_output_tokens=1000, temperature=0.5\n",
")\n",
"chain = prompt | chat\n",
"\n",
"asyncio.run(\n",
@@ -483,43 +482,15 @@
" sys.stdout.write(chunk.content)\n",
" sys.stdout.flush()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"environment": {
"kernel": "python3",
"name": "common-cpu.m108",
"type": "gcloud",
"uri": "gcr.io/deeplearning-platform-release/base-cpu:m108"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
"display_name": "",
"name": ""
},
"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.10"
},
"vscode": {
"interpreter": {
"hash": "cc99336516f23363341912c6723b01ace86f02e26b4290be1efc0677e2e2ec24"
}
"name": "python"
}
},
"nbformat": 4,

View File

@@ -4,9 +4,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Hugging Face Chat Wrapper\n",
"# Hugging Face\n",
"\n",
"This notebook shows how to get started using Hugging Face LLM's as chat models.\n",
"This notebook shows how to get started using `Hugging Face` LLM's as chat models.\n",
"\n",
"In particular, we will:\n",
"1. Utilize the [HuggingFaceTextGenInference](https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain/llms/huggingface_text_gen_inference.py), [HuggingFaceEndpoint](https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain/llms/huggingface_endpoint.py), or [HuggingFaceHub](https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain/llms/huggingface_hub.py) integrations to instantiate an `LLM`.\n",
@@ -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"
]
}
@@ -49,23 +47,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `HuggingFaceTextGenInference`"
"### `HuggingFaceTextGenInference`"
]
},
{
"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",
@@ -93,7 +82,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `HuggingFaceEndpoint`"
"### `HuggingFaceEndpoint`"
]
},
{
@@ -121,7 +110,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `HuggingFaceHub`"
"### `HuggingFaceHub`"
]
},
{
@@ -291,7 +280,7 @@
"source": [
"## 3. Take it for a spin as an agent!\n",
"\n",
"Here we'll test out `Zephyr-7B-beta` as a zero-shot ReAct Agent. The example below is taken from [here](https://python.langchain.com/docs/modules/agents/agent_types/react#using-chat-models).\n",
"Here we'll test out `Zephyr-7B-beta` as a zero-shot `ReAct` Agent. The example below is taken from [here](https://python.langchain.com/docs/modules/agents/agent_types/react#using-chat-models).\n",
"\n",
"> Note: To run this section, you'll need to have a [SerpAPI Token](https://serpapi.com/) saved as an environment variable: `SERPAPI_API_KEY`"
]
@@ -448,7 +437,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.5"
"version": "3.10.12"
}
},
"nbformat": 4,

View File

@@ -21,17 +21,31 @@
"\n",
"1. Select the right LLM(s) for their application\n",
"2. Prototype with various open-source and proprietary LLMs\n",
"3. Move to production in-line with their security, privacy, throughput, latency SLAs without infrastructure set-up or administration using Konko AI's SOC 2 compliant infrastructure\n",
"3. Access Fine Tuning for open-source LLMs to get industry-leading performance at a fraction of the cost\n",
"4. Setup low-cost production APIs according to security, privacy, throughput, latency SLAs without infrastructure set-up or administration using Konko AI's SOC 2 compliant, multi-cloud infrastructure\n",
"\n",
"### Steps to Access Models\n",
"1. **Explore Available Models:** Start by browsing through the [available models](https://docs.konko.ai/docs/list-of-models) on Konko. Each model caters to different use cases and capabilities.\n",
"\n",
"This example goes over how to use LangChain to interact with `Konko` [models](https://docs.konko.ai/docs/overview)"
"2. **Identify Suitable Endpoints:** Determine which [endpoint](https://docs.konko.ai/docs/list-of-models#list-of-available-models) (ChatCompletion or Completion) supports your selected model.\n",
"\n",
"3. **Selecting a Model:** [Choose a model](https://docs.konko.ai/docs/list-of-models#list-of-available-models) based on its metadata and how well it fits your use case.\n",
"\n",
"4. **Prompting Guidelines:** Once a model is selected, refer to the [prompting guidelines](https://docs.konko.ai/docs/prompting) to effectively communicate with it.\n",
"\n",
"5. **Using the API:** Finally, use the appropriate Konko [API endpoint](https://docs.konko.ai/docs/quickstart-for-completion-and-chat-completion-endpoint) to call the model and receive responses.\n",
"\n",
"To run this notebook, you'll need Konko API key. You can create one by signing up on [Konko](https://www.konko.ai/).\n",
"\n",
"This example goes over how to use LangChain to interact with `Konko` ChatCompletion [models](https://docs.konko.ai/docs/list-of-models#konko-hosted-models-for-chatcompletion)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To run this notebook, you'll need Konko API key. You can request it by messaging support@konko.ai."
"To run this notebook, you'll need Konko API key. You can create one by signing up on [Konko](https://www.konko.ai/)."
]
},
{
@@ -84,36 +98,34 @@
"source": [
"## Calling a model\n",
"\n",
"Find a model on the [Konko overview page](https://docs.konko.ai/docs/overview)\n",
"Find a model on the [Konko overview page](https://docs.konko.ai/v0.5.0/docs/list-of-models)\n",
"\n",
"For example, for this [LLama 2 model](https://docs.konko.ai/docs/meta-llama-2-13b-chat). The model id would be: `\"meta-llama/Llama-2-13b-chat-hf\"`\n",
"\n",
"Another way to find the list of models running on the Konko instance is through this [endpoint](https://docs.konko.ai/reference/listmodels).\n",
"Another way to find the list of models running on the Konko instance is through this [endpoint](https://docs.konko.ai/reference/get-models).\n",
"\n",
"From here, we can initialize our model:\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"chat = ChatKonko(max_tokens=400, model=\"meta-llama/Llama-2-13b-chat-hf\")"
"chat = ChatKonko(max_tokens=400, model=\"meta-llama/llama-2-13b-chat\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\" Sure, I'd be happy to explain the Big Bang Theory briefly!\\n\\nThe Big Bang Theory is the leading explanation for the origin and evolution of the universe, based on a vast amount of observational evidence from many fields of science. In essence, the theory posits that the universe began as an infinitely hot and dense point, known as a singularity, around 13.8 billion years ago. This singularity expanded rapidly, and as it did, it cooled and formed subatomic particles, which eventually coalesced into the first atoms, and later into the stars and galaxies we see today.\\n\\nThe theory gets its name from the idea that the universe began in a state of incredibly high energy and temperature, and has been expanding and cooling ever since. This expansion is thought to have been driven by a mysterious force known as dark energy, which is thought to be responsible for the accelerating expansion of the universe.\\n\\nOne of the key predictions of the Big Bang Theory is that the universe should be homogeneous and isotropic on large scales, meaning that it should look the same in all directions and have the same properties everywhere. This prediction has been confirmed by a wealth of observational evidence, including the cosmic microwave background radiation, which is thought to be a remnant of the early universe.\\n\\nOverall, the Big Bang Theory is a well-established and widely accepted explanation for the origins of the universe, and it has been supported by a vast amount of observational evidence from many fields of science.\", additional_kwargs={}, example=False)"
"AIMessage(content=\" Sure thing! The Big Bang Theory is a scientific theory that explains the origins of the universe. In short, it suggests that the universe began as an infinitely hot and dense point around 13.8 billion years ago and expanded rapidly. This expansion continues to this day, and it's what makes the universe look the way it does.\\n\\nHere's a brief overview of the key points:\\n\\n1. The universe started as a singularity, a point of infinite density and temperature.\\n2. The singularity expanded rapidly, causing the universe to cool and expand.\\n3. As the universe expanded, particles began to form, including protons, neutrons, and electrons.\\n4. These particles eventually came together to form atoms, and later, stars and galaxies.\\n5. The universe is still expanding today, and the rate of this expansion is accelerating.\\n\\nThat's the Big Bang Theory in a nutshell! It's a pretty mind-blowing idea when you think about it, and it's supported by a lot of scientific evidence. Do you have any other questions about it?\")"
]
},
"execution_count": 7,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -125,13 +137,6 @@
"]\n",
"chat(messages)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@@ -0,0 +1,218 @@
{
"cells": [
{
"cell_type": "raw",
"id": "59148044",
"metadata": {},
"source": [
"---\n",
"sidebar_label: LiteLLM Router\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "247da7a6",
"metadata": {},
"source": []
},
{
"attachments": {},
"cell_type": "markdown",
"id": "bf733a38-db84-4363-89e2-de6735c37230",
"metadata": {},
"source": [
"# ChatLiteLLMRouter\n",
"\n",
"[LiteLLM](https://github.com/BerriAI/litellm) is a library that simplifies calling Anthropic, Azure, Huggingface, Replicate, etc. \n",
"\n",
"This notebook covers how to get started with using Langchain + the LiteLLM Router I/O library. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "d4a7c55d-b235-4ca4-a579-c90cc9570da9",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.schema import HumanMessage\n",
"from langchain_community.chat_models import ChatLiteLLMRouter\n",
"from litellm import Router"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "70cf04e8-423a-4ff6-8b09-f11fb711c817",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"model_list = [\n",
" {\n",
" \"model_name\": \"gpt-4\",\n",
" \"litellm_params\": {\n",
" \"model\": \"azure/gpt-4-1106-preview\",\n",
" \"api_key\": \"<your-api-key>\",\n",
" \"api_version\": \"2023-05-15\",\n",
" \"api_base\": \"https://<your-endpoint>.openai.azure.com/\",\n",
" },\n",
" },\n",
" {\n",
" \"model_name\": \"gpt-4\",\n",
" \"litellm_params\": {\n",
" \"model\": \"azure/gpt-4-1106-preview\",\n",
" \"api_key\": \"<your-api-key>\",\n",
" \"api_version\": \"2023-05-15\",\n",
" \"api_base\": \"https://<your-endpoint>.openai.azure.com/\",\n",
" },\n",
" },\n",
"]\n",
"litellm_router = Router(model_list=model_list)\n",
"chat = ChatLiteLLMRouter(router=litellm_router)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "8199ef8f-eb8b-4253-9ea0-6c24a013ca4c",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"J'aime programmer.\")"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"messages = [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
"]\n",
"chat(messages)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "c361ab1e-8c0c-4206-9e3c-9d1424a12b9c",
"metadata": {},
"source": [
"## `ChatLiteLLMRouter` also supports async and streaming functionality:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "93a21c5c-6ef9-4688-be60-b2e1f94842fb",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.callbacks.manager import CallbackManager\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c5fac0e9-05a4-4fc1-a3b3-e5bbb24b971b",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"LLMResult(generations=[[ChatGeneration(text=\"J'adore programmer.\", generation_info={'finish_reason': 'stop'}, message=AIMessage(content=\"J'adore programmer.\"))]], llm_output={'token_usage': {'completion_tokens': 6, 'prompt_tokens': 19, 'total_tokens': 25}, 'model_name': None}, run=[RunInfo(run_id=UUID('75003ec9-1e2b-43b7-a216-10dcc0f75e00'))])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await chat.agenerate([messages])"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "025be980-e50d-4a68-93dc-c9c7b500ce34",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"J'adore programmer."
]
},
{
"data": {
"text/plain": [
"AIMessage(content=\"J'adore programmer.\")"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat = ChatLiteLLMRouter(\n",
" router=litellm_router,\n",
" streaming=True,\n",
" verbose=True,\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),\n",
")\n",
"chat(messages)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c253883f",
"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.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,99 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "3ddface67cd10a87",
"metadata": {
"collapsed": false
},
"source": [
"# SparkLLM Chat\n",
"\n",
"SparkLLM chat models API by iFlyTek. For more information, see [iFlyTek Open Platform](https://www.xfyun.cn/)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic use"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "43daa39972d4c533",
"metadata": {
"collapsed": false,
"is_executing": true
},
"outputs": [],
"source": [
"\"\"\"For basic init and call\"\"\"\n",
"from langchain.chat_models import ChatSparkLLM\n",
"from langchain.schema import HumanMessage\n",
"\n",
"chat = ChatSparkLLM(\n",
" spark_app_id=\"<app_id>\", spark_api_key=\"<api_key>\", spark_api_secret=\"<api_secret>\"\n",
")\n",
"message = HumanMessage(content=\"Hello\")\n",
"chat([message])"
]
},
{
"cell_type": "markdown",
"id": "df755f4c5689510",
"metadata": {
"collapsed": false
},
"source": [
"- Get SparkLLM's app_id, api_key and api_secret from [iFlyTek SparkLLM API Console](https://console.xfyun.cn/services/bm3) (for more info, see [iFlyTek SparkLLM Intro](https://xinghuo.xfyun.cn/sparkapi) ), then set environment variables `IFLYTEK_SPARK_APP_ID`, `IFLYTEK_SPARK_API_KEY` and `IFLYTEK_SPARK_API_SECRET` or pass parameters when creating `ChatSparkLLM` as the demo above."
]
},
{
"cell_type": "markdown",
"id": "984e32ee47bc6772",
"metadata": {
"collapsed": false
},
"source": [
"## For ChatSparkLLM with Streaming"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7dc162bd65fec08f",
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"chat = ChatSparkLLM(streaming=True)\n",
"for chunk in chat.stream(\"Hello!\"):\n",
" print(chunk.content, end=\"\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -12,7 +12,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 2,
"id": "497736aa",
"metadata": {},
"outputs": [],
@@ -24,7 +24,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"id": "009e0036",
"metadata": {},
"outputs": [],
@@ -34,19 +34,19 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 8,
"id": "910fb6ee",
"metadata": {},
"outputs": [],
"source": [
"loader = ToMarkdownLoader.from_api_key(\n",
" url=\"https://python.langchain.com/en/latest/\", api_key=api_key\n",
"loader = ToMarkdownLoader(\n",
" url=\"https://python.langchain.com/docs/get_started/introduction\", api_key=api_key\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 9,
"id": "ac8db139",
"metadata": {},
"outputs": [],
@@ -56,7 +56,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 10,
"id": "706304e9",
"metadata": {},
"outputs": [
@@ -64,130 +64,106 @@
"name": "stdout",
"output_type": "stream",
"text": [
"## Contents\n",
"**LangChain** is a framework for developing applications powered by language models. It enables applications that:\n",
"\n",
"- [Getting Started](#getting-started)\n",
"- [Modules](#modules)\n",
"- [Use Cases](#use-cases)\n",
"- [Reference Docs](#reference-docs)\n",
"- [LangChain Ecosystem](#langchain-ecosystem)\n",
"- [Additional Resources](#additional-resources)\n",
"- **Are context-aware**: connect a language model to sources of context (prompt instructions, few shot examples, content to ground its response in, etc.)\n",
"- **Reason**: rely on a language model to reason (about how to answer based on provided context, what actions to take, etc.)\n",
"\n",
"## Welcome to LangChain [\\#](\\#welcome-to-langchain \"Permalink to this headline\")\n",
"This framework consists of several parts.\n",
"\n",
"**LangChain** is a framework for developing applications powered by language models. We believe that the most powerful and differentiated applications will not only call out to a language model, but will also be:\n",
"- **LangChain Libraries**: The Python and JavaScript libraries. Contains interfaces and integrations for a myriad of components, a basic run time for combining these components into chains and agents, and off-the-shelf implementations of chains and agents.\n",
"- **[LangChain Templates](https://python.langchain.com/docs/templates)**: A collection of easily deployable reference architectures for a wide variety of tasks.\n",
"- **[LangServe](https://python.langchain.com/docs/langserve)**: A library for deploying LangChain chains as a REST API.\n",
"- **[LangSmith](https://python.langchain.com/docs/langsmith)**: A developer platform that lets you debug, test, evaluate, and monitor chains built on any LLM framework and seamlessly integrates with LangChain.\n",
"\n",
"1. _Data-aware_: connect a language model to other sources of data\n",
"![Diagram outlining the hierarchical organization of the LangChain framework, displaying the interconnected parts across multiple layers.](https://python.langchain.com/assets/images/langchain_stack-f21828069f74484521f38199910007c1.svg)\n",
"\n",
"2. _Agentic_: allow a language model to interact with its environment\n",
"Together, these products simplify the entire application lifecycle:\n",
"\n",
"- **Develop**: Write your applications in LangChain/LangChain.js. Hit the ground running using Templates for reference.\n",
"- **Productionize**: Use LangSmith to inspect, test and monitor your chains, so that you can constantly improve and deploy with confidence.\n",
"- **Deploy**: Turn any chain into an API with LangServe.\n",
"\n",
"The LangChain framework is designed around these principles.\n",
"## LangChain Libraries [](\\#langchain-libraries \"Direct link to LangChain Libraries\")\n",
"\n",
"This is the Python specific portion of the documentation. For a purely conceptual guide to LangChain, see [here](https://docs.langchain.com/docs/). For the JavaScript documentation, see [here](https://js.langchain.com/docs/).\n",
"The main value props of the LangChain packages are:\n",
"\n",
"## Getting Started [\\#](\\#getting-started \"Permalink to this headline\")\n",
"1. **Components**: composable tools and integrations for working with language models. Components are modular and easy-to-use, whether you are using the rest of the LangChain framework or not\n",
"2. **Off-the-shelf chains**: built-in assemblages of components for accomplishing higher-level tasks\n",
"\n",
"How to get started using LangChain to create an Language Model application.\n",
"Off-the-shelf chains make it easy to get started. Components make it easy to customize existing chains and build new ones.\n",
"\n",
"- [Quickstart Guide](https://python.langchain.com/en/latest/getting_started/getting_started.html)\n",
"The LangChain libraries themselves are made up of several different packages.\n",
"\n",
"- **`langchain-core`**: Base abstractions and LangChain Expression Language.\n",
"- **`langchain-community`**: Third party integrations.\n",
"- **`langchain`**: Chains, agents, and retrieval strategies that make up an application's cognitive architecture.\n",
"\n",
"Concepts and terminology.\n",
"## Get started [](\\#get-started \"Direct link to Get started\")\n",
"\n",
"- [Concepts and terminology](https://python.langchain.com/en/latest/getting_started/concepts.html)\n",
"[Heres](https://python.langchain.com/docs/get_started/installation) how to install LangChain, set up your environment, and start building.\n",
"\n",
"We recommend following our [Quickstart](https://python.langchain.com/docs/get_started/quickstart) guide to familiarize yourself with the framework by building your first LangChain application.\n",
"\n",
"Tutorials created by community experts and presented on YouTube.\n",
"Read up on our [Security](https://python.langchain.com/docs/security) best practices to make sure you're developing safely with LangChain.\n",
"\n",
"- [Tutorials](https://python.langchain.com/en/latest/getting_started/tutorials.html)\n",
"note\n",
"\n",
"These docs focus on the Python LangChain library. [Head here](https://js.langchain.com) for docs on the JavaScript LangChain library.\n",
"\n",
"## Modules [\\#](\\#modules \"Permalink to this headline\")\n",
"## LangChain Expression Language (LCEL) [](\\#langchain-expression-language-lcel \"Direct link to LangChain Expression Language (LCEL)\")\n",
"\n",
"These modules are the core abstractions which we view as the building blocks of any LLM-powered application.\n",
"LCEL is a declarative way to compose chains. LCEL was designed from day 1 to support putting prototypes in production, with no code changes, from the simplest “prompt + LLM” chain to the most complex chains.\n",
"\n",
"For each module LangChain provides standard, extendable interfaces. LanghChain also provides external integrations and even end-to-end implementations for off-the-shelf use.\n",
"- **[Overview](https://python.langchain.com/docs/expression_language/)**: LCEL and its benefits\n",
"- **[Interface](https://python.langchain.com/docs/expression_language/interface)**: The standard interface for LCEL objects\n",
"- **[How-to](https://python.langchain.com/docs/expression_language/how_to)**: Key features of LCEL\n",
"- **[Cookbook](https://python.langchain.com/docs/expression_language/cookbook)**: Example code for accomplishing common tasks\n",
"\n",
"The docs for each module contain quickstart examples, how-to guides, reference docs, and conceptual guides.\n",
"## Modules [](\\#modules \"Direct link to Modules\")\n",
"\n",
"The modules are (from least to most complex):\n",
"LangChain provides standard, extendable interfaces and integrations for the following modules:\n",
"\n",
"- [Models](https://python.langchain.com/docs/modules/model_io/models/): Supported model types and integrations.\n",
"#### [Model I/O](https://python.langchain.com/docs/modules/model_io/) [](\\#model-io \"Direct link to model-io\")\n",
"\n",
"- [Prompts](https://python.langchain.com/en/latest/modules/prompts.html): Prompt management, optimization, and serialization.\n",
"Interface with language models\n",
"\n",
"- [Memory](https://python.langchain.com/en/latest/modules/memory.html): Memory refers to state that is persisted between calls of a chain/agent.\n",
"#### [Retrieval](https://python.langchain.com/docs/modules/data_connection/) [](\\#retrieval \"Direct link to retrieval\")\n",
"\n",
"- [Indexes](https://python.langchain.com/en/latest/modules/data_connection.html): Language models become much more powerful when combined with application-specific data - this module contains interfaces and integrations for loading, querying and updating external data.\n",
"Interface with application-specific data\n",
"\n",
"- [Chains](https://python.langchain.com/en/latest/modules/chains.html): Chains are structured sequences of calls (to an LLM or to a different utility).\n",
"#### [Agents](https://python.langchain.com/docs/modules/agents/) [](\\#agents \"Direct link to agents\")\n",
"\n",
"- [Agents](https://python.langchain.com/en/latest/modules/agents.html): An agent is a Chain in which an LLM, given a high-level directive and a set of tools, repeatedly decides an action, executes the action and observes the outcome until the high-level directive is complete.\n",
"Let models choose which tools to use given high-level directives\n",
"\n",
"- [Callbacks](https://python.langchain.com/en/latest/modules/callbacks/getting_started.html): Callbacks let you log and stream the intermediate steps of any chain, making it easy to observe, debug, and evaluate the internals of an application.\n",
"## Examples, ecosystem, and resources [](\\#examples-ecosystem-and-resources \"Direct link to Examples, ecosystem, and resources\")\n",
"\n",
"### [Use cases](https://python.langchain.com/docs/use_cases/question_answering/) [](\\#use-cases \"Direct link to use-cases\")\n",
"\n",
"## Use Cases [\\#](\\#use-cases \"Permalink to this headline\")\n",
"Walkthroughs and techniques for common end-to-end use cases, like:\n",
"\n",
"Best practices and built-in implementations for common LangChain use cases:\n",
"- [Document question answering](https://python.langchain.com/docs/use_cases/question_answering/)\n",
"- [Chatbots](https://python.langchain.com/docs/use_cases/chatbots/)\n",
"- [Analyzing structured data](https://python.langchain.com/docs/use_cases/sql/)\n",
"- and much more...\n",
"\n",
"- [Autonomous Agents](https://python.langchain.com/en/latest/use_cases/autonomous_agents.html): Autonomous agents are long-running agents that take many steps in an attempt to accomplish an objective. Examples include AutoGPT and BabyAGI.\n",
"### [Integrations](https://python.langchain.com/docs/integrations/providers/) [](\\#integrations \"Direct link to integrations\")\n",
"\n",
"- [Agent Simulations](https://python.langchain.com/en/latest/use_cases/agent_simulations.html): Putting agents in a sandbox and observing how they interact with each other and react to events can be an effective way to evaluate their long-range reasoning and planning abilities.\n",
"LangChain is part of a rich ecosystem of tools that integrate with our framework and build on top of it. Check out our growing list of [integrations](https://python.langchain.com/docs/integrations/providers/).\n",
"\n",
"- [Personal Assistants](https://python.langchain.com/en/latest/use_cases/personal_assistants.html): One of the primary LangChain use cases. Personal assistants need to take actions, remember interactions, and have knowledge about your data.\n",
"### [Guides](https://python.langchain.com/docs/guides/debugging) [](\\#guides \"Direct link to guides\")\n",
"\n",
"- [Question Answering](https://python.langchain.com/en/latest/use_cases/question_answering.html): Another common LangChain use case. Answering questions over specific documents, only utilizing the information in those documents to construct an answer.\n",
"Best practices for developing with LangChain.\n",
"\n",
"- [Chatbots](https://python.langchain.com/en/latest/use_cases/chatbots.html): Language models love to chat, making this a very natural use of them.\n",
"### [API reference](https://api.python.langchain.com) [](\\#api-reference \"Direct link to api-reference\")\n",
"\n",
"- [Querying Tabular Data](https://python.langchain.com/en/latest/use_cases/tabular.html): Recommended reading if you want to use language models to query structured data (CSVs, SQL, dataframes, etc).\n",
"Head to the reference section for full documentation of all classes and methods in the LangChain and LangChain Experimental Python packages.\n",
"\n",
"- [Code Understanding](https://python.langchain.com/en/latest/use_cases/code.html): Recommended reading if you want to use language models to analyze code.\n",
"### [Developer's guide](https://python.langchain.com/docs/contributing) [](\\#developers-guide \"Direct link to developers-guide\")\n",
"\n",
"- [Interacting with APIs](https://python.langchain.com/en/latest/use_cases/apis.html): Enabling language models to interact with APIs is extremely powerful. It gives them access to up-to-date information and allows them to take actions.\n",
"Check out the developer's guide for guidelines on contributing and help getting your dev environment set up.\n",
"\n",
"- [Extraction](https://python.langchain.com/en/latest/use_cases/extraction.html): Extract structured information from text.\n",
"\n",
"- [Summarization](https://python.langchain.com/en/latest/use_cases/summarization.html): Compressing longer documents. A type of Data-Augmented Generation.\n",
"\n",
"- [Evaluation](https://python.langchain.com/en/latest/use_cases/evaluation.html): Generative models are hard to evaluate with traditional metrics. One promising approach is to use language models themselves to do the evaluation.\n",
"\n",
"\n",
"## Reference Docs [\\#](\\#reference-docs \"Permalink to this headline\")\n",
"\n",
"Full documentation on all methods, classes, installation methods, and integration setups for LangChain.\n",
"\n",
"- [Reference Documentation](https://python.langchain.com/en/latest/reference.html)\n",
"\n",
"\n",
"## LangChain Ecosystem [\\#](\\#langchain-ecosystem \"Permalink to this headline\")\n",
"\n",
"Guides for how other companies/products can be used with LangChain.\n",
"\n",
"- [LangChain Ecosystem](https://python.langchain.com/en/latest/ecosystem.html)\n",
"\n",
"\n",
"## Additional Resources [\\#](\\#additional-resources \"Permalink to this headline\")\n",
"\n",
"Additional resources we think may be useful as you develop your application!\n",
"\n",
"- [LangChainHub](https://github.com/hwchase17/langchain-hub): The LangChainHub is a place to share and explore other prompts, chains, and agents.\n",
"\n",
"- [Gallery](https://python.langchain.com/en/latest/additional_resources/gallery.html): A collection of our favorite projects that use LangChain. Useful for finding inspiration or seeing how things were done in other applications.\n",
"\n",
"- [Deployments](https://python.langchain.com/en/latest/additional_resources/deployments.html): A collection of instructions, code snippets, and template repositories for deploying LangChain apps.\n",
"\n",
"- [Tracing](https://python.langchain.com/en/latest/additional_resources/tracing.html): A guide on using tracing in LangChain to visualize the execution of chains and agents.\n",
"\n",
"- [Model Laboratory](https://python.langchain.com/en/latest/additional_resources/model_laboratory.html): Experimenting with different prompts, models, and chains is a big part of developing the best possible application. The ModelLaboratory makes it easy to do so.\n",
"\n",
"- [Discord](https://discord.gg/6adMQxSpJS): Join us on our Discord to discuss all things LangChain!\n",
"\n",
"- [YouTube](https://python.langchain.com/en/latest/additional_resources/youtube.html): A collection of the LangChain tutorials and videos.\n",
"\n",
"- [Production Support](https://forms.gle/57d8AmXBYp8PP8tZA): As you move your LangChains into production, wed love to offer more comprehensive support. Please fill out this form and well set up a dedicated support Slack channel.\n"
"Head to the [Community navigator](https://python.langchain.com/docs/community) to find places to ask questions, share feedback, meet other developers, and dream about the future of LLMs.\n"
]
}
],
@@ -198,7 +174,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "5dde17e7",
"id": "7c89b313-adb6-4aa2-9cd8-952a5724a2ce",
"metadata": {},
"outputs": [],
"source": []
@@ -220,7 +196,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.11.6"
}
},
"nbformat": 4,

View File

@@ -12,7 +12,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "2886982e",
"metadata": {},
"outputs": [],
@@ -100,6 +100,54 @@
"docs[0].page_content[:400]"
]
},
{
"cell_type": "markdown",
"id": "b4ab0a79",
"metadata": {},
"source": [
"### Load list of files"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "092d9a0b",
"metadata": {},
"outputs": [],
"source": [
"files = [\"./example_data/whatsapp_chat.txt\", \"./example_data/layout-parser-paper.pdf\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f841c4f8",
"metadata": {},
"outputs": [],
"source": [
"loader = UnstructuredFileLoader(files)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "993c240b",
"metadata": {},
"outputs": [],
"source": [
"docs = loader.load()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5ce4ff07",
"metadata": {},
"outputs": [],
"source": [
"docs[0].page_content[:400]"
]
},
{
"cell_type": "markdown",
"id": "7874d01d",
@@ -495,7 +543,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.9.0"
}
},
"nbformat": 4,

View File

@@ -6,9 +6,9 @@
"source": [
"# Azure ML\n",
"\n",
"[Azure ML](https://azure.microsoft.com/en-us/products/machine-learning/) is a platform used to build, train, and deploy machine learning models. Users can explore the types of models to deploy in the Model Catalog, which provides Azure Foundation Models and OpenAI Models. Azure Foundation Models include various open-source models and popular Hugging Face models. Users can also import models of their liking into AzureML.\n",
"[Azure ML](https://azure.microsoft.com/en-us/products/machine-learning/) is a platform used to build, train, and deploy machine learning models. Users can explore the types of models to deploy in the Model Catalog, which provides foundational and general purpose models from different providers.\n",
"\n",
"This notebook goes over how to use an LLM hosted on an `AzureML online endpoint`"
"This notebook goes over how to use an LLM hosted on an `Azure ML Online Endpoint`."
]
},
{
@@ -26,11 +26,12 @@
"source": [
"## Set up\n",
"\n",
"To use the wrapper, you must [deploy a model on AzureML](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-use-foundation-models?view=azureml-api-2#deploying-foundation-models-to-endpoints-for-inferencing) and obtain the following parameters:\n",
"You must [deploy a model on Azure ML](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-use-foundation-models?view=azureml-api-2#deploying-foundation-models-to-endpoints-for-inferencing) or [to Azure AI studio](https://learn.microsoft.com/en-us/azure/ai-studio/how-to/deploy-models-open) and obtain the following parameters:\n",
"\n",
"* `endpoint_api_key`: Required - The API key provided by the endpoint\n",
"* `endpoint_url`: Required - The REST endpoint url provided by the endpoint\n",
"* `deployment_name`: Not required - The deployment name of the model using the endpoint"
"* `endpoint_url`: The REST endpoint url provided by the endpoint.\n",
"* `endpoint_api_type`: Use `endpoint_type='realtime'` when deploying models to **Realtime endpoints** (hosted managed infrastructure). Use `endpoint_type='serverless'` when deploying models using the **Pay-as-you-go** offering (model as a service).\n",
"* `endpoint_api_key`: The API key provided by the endpoint.\n",
"* `deployment_name`: (Optional) The deployment name of the model using the endpoint."
]
},
{
@@ -46,31 +47,107 @@
"* `HFContentFormatter`: Formats request and response data for text-generation Hugging Face models\n",
"* `LLamaContentFormatter`: Formats request and response data for LLaMa2\n",
"\n",
"*Note: `OSSContentFormatter` is being deprecated and replaced with `GPT2ContentFormatter`. The logic is the same but `GPT2ContentFormatter` is a more suitable name. You can still continue to use `OSSContentFormatter` as the changes are backwards compatible.*\n",
"\n",
"Below is an example using a summarization model from Hugging Face."
"*Note: `OSSContentFormatter` is being deprecated and replaced with `GPT2ContentFormatter`. The logic is the same but `GPT2ContentFormatter` is a more suitable name. You can still continue to use `OSSContentFormatter` as the changes are backwards compatible.*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Custom Content Formatter"
"## Examples"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: LlaMa 2 completions with real-time endpoints"
]
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"HaSeul won her first music show trophy with \"So What\" on Mnet's M Countdown. Loona released their second EP titled [#] (read as hash] on February 5, 2020. HaSeul did not take part in the promotion of the album because of mental health issues. On October 19, 2020, they released their third EP called [12:00]. It was their first album to enter the Billboard 200, debuting at number 112. On June 2, 2021, the group released their fourth EP called Yummy-Yummy. On August 27, it was announced that they are making their Japanese debut on September 15 under Universal Music Japan sublabel EMI Records.\n"
]
}
],
"outputs": [],
"source": [
"from langchain.schema import HumanMessage\n",
"from langchain_community.llms.azureml_endpoint import (\n",
" AzureMLEndpointApiType,\n",
" LlamaContentFormatter,\n",
")\n",
"\n",
"llm = AzureMLOnlineEndpoint(\n",
" endpoint_url=\"https://<your-endpoint>.<your_region>.inference.ml.azure.com/score\",\n",
" endpoint_api_type=AzureMLEndpointApiType.realtime,\n",
" endpoint_api_key=\"my-api-key\",\n",
" content_formatter=LlamaContentFormatter(),\n",
" model_kwargs={\"temperature\": 0.8, \"max_new_tokens\": 400},\n",
")\n",
"response = llm.invoke(\"Write me a song about sparkling water:\")\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Model parameters can also be indicated during invocation:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"response = llm.invoke(\"Write me a song about sparkling water:\", temperature=0.5)\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Chat completions with pay-as-you-go deployments (model as a service)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.schema import HumanMessage\n",
"from langchain_community.llms.azureml_endpoint import (\n",
" AzureMLEndpointApiType,\n",
" LlamaContentFormatter,\n",
")\n",
"\n",
"llm = AzureMLOnlineEndpoint(\n",
" endpoint_url=\"https://<your-endpoint>.<your_region>.inference.ml.azure.com/v1/completions\",\n",
" endpoint_api_type=AzureMLEndpointApiType.serverless,\n",
" endpoint_api_key=\"my-api-key\",\n",
" content_formatter=LlamaContentFormatter(),\n",
" model_kwargs={\"temperature\": 0.8, \"max_new_tokens\": 400},\n",
")\n",
"response = llm.invoke(\"Write me a song about sparkling water:\")\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Custom content formatter\n",
"\n",
"Below is an example using a summarization model from Hugging Face."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"import os\n",
@@ -104,6 +181,7 @@
"content_formatter = CustomFormatter()\n",
"\n",
"llm = AzureMLOnlineEndpoint(\n",
" endpoint_api_type=\"realtime\",\n",
" endpoint_api_key=os.getenv(\"BART_ENDPOINT_API_KEY\"),\n",
" endpoint_url=os.getenv(\"BART_ENDPOINT_URL\"),\n",
" model_kwargs={\"temperature\": 0.8, \"max_new_tokens\": 400},\n",
@@ -132,7 +210,7 @@
"that Loona will release the double A-side single, \"Hula Hoop / Star Seed\" on September 15, with a physical CD release on October \n",
"20.[53] In December, Chuu filed an injunction to suspend her exclusive contract with Blockberry Creative.[54][55]\n",
"\"\"\"\n",
"summarized_text = llm(large_text)\n",
"summarized_text = llm.invoke(large_text)\n",
"print(summarized_text)"
]
},
@@ -140,22 +218,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Dolly with LLMChain"
"### Example: Dolly with LLMChain"
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Many people are willing to talk about themselves; it's others who seem to be stuck up. Try to understand others where they're coming from. Like minded people can build a tribe together.\n"
]
}
],
"outputs": [],
"source": [
"from langchain.chains import LLMChain\n",
"from langchain.prompts import PromptTemplate\n",
@@ -177,31 +247,22 @@
")\n",
"\n",
"chain = LLMChain(llm=llm, prompt=prompt)\n",
"print(chain.run({\"word_count\": 100, \"topic\": \"how to make friends\"}))"
"print(chain.invoke({\"word_count\": 100, \"topic\": \"how to make friends\"}))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Serializing an LLM\n",
"## Serializing an LLM\n",
"You can also save and load LLM configurations"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1mAzureMLOnlineEndpoint\u001b[0m\n",
"Params: {'deployment_name': 'databricks-dolly-v2-12b-4', 'model_kwargs': {'temperature': 0.2, 'max_tokens': 150, 'top_p': 0.8, 'frequency_penalty': 0.32, 'presence_penalty': 0.072}}\n"
]
}
],
"outputs": [],
"source": [
"from langchain_community.llms.loading import load_llm\n",
"\n",
@@ -224,9 +285,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "langchain",
"language": "python",
"name": "python3"
"name": "langchain"
},
"language_info": {
"codemirror_mode": {
@@ -238,7 +299,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.11.5"
}
},
"nbformat": 4,

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

@@ -106,6 +106,45 @@
"\n",
"conversation.predict(input=\"Hi there!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Guardrails for Amazon Bedrock example \n",
"\n",
"In this section, we are going to set up a Bedrock language model with specific guardrails that include tracing capabilities. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from typing import Any\n",
"\n",
"from langchain_core.callbacks import AsyncCallbackHandler\n",
"\n",
"\n",
"class BedrockAsyncCallbackHandler(AsyncCallbackHandler):\n",
" # Async callback handler that can be used to handle callbacks from langchain.\n",
"\n",
" async def on_llm_error(self, error: BaseException, **kwargs: Any) -> Any:\n",
" reason = kwargs.get(\"reason\")\n",
" if reason == \"GUARDRAIL_INTERVENED\":\n",
" print(f\"Guardrails: {kwargs}\")\n",
"\n",
"\n",
"# guardrails for Amazon Bedrock with trace\n",
"llm = Bedrock(\n",
" credentials_profile_name=\"bedrock-admin\",\n",
" model_id=\"<Model_ID>\",\n",
" model_kwargs={},\n",
" guardrails={\"id\": \"<Guardrail_ID>\", \"version\": \"<Version>\", \"trace\": True},\n",
" callbacks=[BedrockAsyncCallbackHandler()],\n",
")"
]
}
],
"metadata": {

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

@@ -0,0 +1,100 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "136d9ba6-c42a-435b-9e19-77ebcc7a3145",
"metadata": {},
"source": [
"# ChatKonko\n",
"\n",
">[Konko](https://www.konko.ai/) API is a fully managed Web API designed to help application developers:\n",
"\n",
"Konko API is a fully managed API designed to help application developers:\n",
"\n",
"1. Select the right LLM(s) for their application\n",
"2. Prototype with various open-source and proprietary LLMs\n",
"3. Access Fine Tuning for open-source LLMs to get industry-leading performance at a fraction of the cost\n",
"4. Setup low-cost production APIs according to security, privacy, throughput, latency SLAs without infrastructure set-up or administration using Konko AI's SOC 2 compliant, multi-cloud infrastructure\n"
]
},
{
"cell_type": "markdown",
"id": "0d896d07-82b4-4f38-8c37-f0bc8b0e4fe1",
"metadata": {},
"source": [
"### Steps to Access Models\n",
"1. **Explore Available Models:** Start by browsing through the [available models](https://docs.konko.ai/docs/list-of-models) on Konko. Each model caters to different use cases and capabilities.\n",
"\n",
"2. **Identify Suitable Endpoints:** Determine which [endpoint](https://docs.konko.ai/docs/list-of-models#list-of-available-models) (ChatCompletion or Completion) supports your selected model.\n",
"\n",
"3. **Selecting a Model:** [Choose a model](https://docs.konko.ai/docs/list-of-models#list-of-available-models) based on its metadata and how well it fits your use case.\n",
"\n",
"4. **Prompting Guidelines:** Once a model is selected, refer to the [prompting guidelines](https://docs.konko.ai/docs/prompting) to effectively communicate with it.\n",
"\n",
"5. **Using the API:** Finally, use the appropriate Konko [API endpoint](https://docs.konko.ai/docs/quickstart-for-completion-and-chat-completion-endpoint) to call the model and receive responses.\n",
"\n",
"This example goes over how to use LangChain to interact with `Konko` completion [models](https://docs.konko.ai/docs/list-of-models#konko-hosted-models-for-completion)\n",
"\n",
"To run this notebook, you'll need Konko API key. You can create one by signing up on [Konko](https://www.konko.ai/)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "dd70bccb-7a65-42d0-a3f2-8116f3549da7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"Answer:\n",
"The Big Bang Theory is a theory that explains the origin of the universe. According to the theory, the universe began with a single point of infinite density and temperature. This point is called the singularity. The singularity exploded and expanded rapidly. The expansion of the universe is still continuing.\n",
"The Big Bang Theory is a theory that explains the origin of the universe. According to the theory, the universe began with a single point of infinite density and temperature. This point is called the singularity. The singularity exploded and expanded rapidly. The expansion of the universe is still continuing.\n",
"\n",
"Question\n"
]
}
],
"source": [
"from langchain.llms import Konko\n",
"\n",
"llm = Konko(model=\"mistralai/mistral-7b-v0.1\", temperature=0.1, max_tokens=128)\n",
"\n",
"input_ = \"\"\"You are a helpful assistant. Explain Big Bang Theory briefly.\"\"\"\n",
"print(llm(input_))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "78148bf7-2211-40b4-93a7-e90139ab1169",
"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.11.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

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": {},
@@ -186,7 +202,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 1,
"metadata": {
"tags": []
},
@@ -223,7 +239,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"metadata": {
"tags": []
},
@@ -406,7 +422,7 @@
"- `n_gpu_layers` - determines how many layers of the model are offloaded to your GPU.\n",
"- `n_batch` - how many tokens are processed in parallel. \n",
"\n",
"Setting these parameters correctly will dramatically improve the evaluation speed (see [wrapper code](https://github.com/mmagnesium/langchain/blob/master/langchain/llms/llamacpp.py) for more details)."
"Setting these parameters correctly will dramatically improve the evaluation speed (see [wrapper code](https://github.com/langchain-ai/langchain/blob/master/libs/community/langchain_community/llms/llamacpp.py) for more details)."
]
},
{
@@ -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",
@@ -487,12 +503,12 @@
"\n",
"Two of the most important GPU parameters are:\n",
"\n",
"- `n_gpu_layers` - determines how many layers of the model are offloaded to your Metal GPU, in the most case, set it to `1` is enough for Metal\n",
"- `n_gpu_layers` - determines how many layers of the model are offloaded to your Metal GPU.\n",
"- `n_batch` - how many tokens are processed in parallel, default is 8, set to bigger number.\n",
"- `f16_kv` - for some reason, Metal only support `True`, otherwise you will get error such as `Asserting on type 0\n",
"GGML_ASSERT: .../ggml-metal.m:706: false && \"not implemented\"`\n",
"\n",
"Setting these parameters correctly will dramatically improve the evaluation speed (see [wrapper code](https://github.com/mmagnesium/langchain/blob/master/langchain/llms/llamacpp.py) for more details)."
"Setting these parameters correctly will dramatically improve the evaluation speed (see [wrapper code](https://github.com/langchain-ai/langchain/blob/master/libs/community/langchain_community/llms/llamacpp.py) for more details)."
]
},
{
@@ -501,7 +517,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",
@@ -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",
@@ -680,7 +696,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.12 ('langchain_venv': venv)",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -694,7 +710,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.11.6"
},
"vscode": {
"interpreter": {

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

@@ -0,0 +1,191 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Oracle Cloud Infrastructure Generative AI"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Oracle Cloud Infrastructure (OCI) Generative AI is a fully managed service that provides a set of state-of-the-art, customizable large language models (LLMs) that cover a wide range of use cases, and which is available through a single API.\n",
"Using the OCI Generative AI service you can access ready-to-use pretrained models, or create and host your own fine-tuned custom models based on your own data on dedicated AI clusters. Detailed documentation of the service and API is available __[here](https://docs.oracle.com/en-us/iaas/Content/generative-ai/home.htm)__ and __[here](https://docs.oracle.com/en-us/iaas/api/#/en/generative-ai/20231130/)__.\n",
"\n",
"This notebook explains how to use OCI's Genrative AI models with LangChain."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Prerequisite\n",
"We will need to install the oci sdk"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -U oci"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### OCI Generative AI API endpoint \n",
"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Authentication\n",
"The authentication methods supported for this langchain integration are:\n",
"\n",
"1. API Key\n",
"2. Session token\n",
"3. Instance principal\n",
"4. Resource principal \n",
"\n",
"These follows the standard SDK authentication methods detailed __[here](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdk_authentication_methods.htm)__.\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Usage"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.llms import OCIGenAI\n",
"\n",
"# use default authN method API-key\n",
"llm = OCIGenAI(\n",
" model_id=\"MY_MODEL\",\n",
" service_endpoint=\"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com\",\n",
" compartment_id=\"MY_OCID\",\n",
")\n",
"\n",
"response = llm.invoke(\"Tell me one fact about earth\", temperature=0.7)\n",
"print(response)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains import LLMChain\n",
"from langchain_core.prompts import PromptTemplate\n",
"\n",
"# Use Session Token to authN\n",
"llm = OCIGenAI(\n",
" model_id=\"MY_MODEL\",\n",
" service_endpoint=\"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com\",\n",
" compartment_id=\"MY_OCID\",\n",
")\n",
"\n",
"prompt = PromptTemplate(input_variables=[\"query\"], template=\"{query}\")\n",
"\n",
"llm_chain = LLMChain(llm=llm, prompt=prompt)\n",
"\n",
"response = llm_chain.invoke(\"what is the capital of france?\")\n",
"print(response)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain.schema.runnable import RunnablePassthrough\n",
"from langchain_community.embeddings import OCIGenAIEmbeddings\n",
"from langchain_community.vectorstores import FAISS\n",
"\n",
"embeddings = OCIGenAIEmbeddings(\n",
" model_id=\"MY_EMBEDDING_MODEL\",\n",
" service_endpoint=\"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com\",\n",
" compartment_id=\"MY_OCID\",\n",
")\n",
"\n",
"vectorstore = FAISS.from_texts(\n",
" [\n",
" \"Larry Ellison co-founded Oracle Corporation in 1977 with Bob Miner and Ed Oates.\",\n",
" \"Oracle Corporation is an American multinational computer technology company headquartered in Austin, Texas, United States.\",\n",
" ],\n",
" embedding=embeddings,\n",
")\n",
"\n",
"retriever = vectorstore.as_retriever()\n",
"\n",
"template = \"\"\"Answer the question based only on the following context:\n",
"{context}\n",
" \n",
"Question: {question}\n",
"\"\"\"\n",
"prompt = PromptTemplate.from_template(template)\n",
"\n",
"llm = OCIGenAI(\n",
" model_id=\"MY_MODEL\",\n",
" service_endpoint=\"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com\",\n",
" compartment_id=\"MY_OCID\",\n",
")\n",
"\n",
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | llm\n",
" | StrOutputParser()\n",
")\n",
"\n",
"print(chain.invoke(\"when was oracle founded?\"))\n",
"print(chain.invoke(\"where is oracle headquartered?\"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "oci_langchain",
"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.18"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

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

@@ -14,7 +14,7 @@
"\n",
"This example showcases how to connect to [PromptLayer](https://www.promptlayer.com) to start recording your OpenAI requests.\n",
"\n",
"Another example is [here](https://python.langchain.com/en/latest/ecosystem/promptlayer.html)."
"Another example is [here](https://python.langchain.com/docs/integrations/providers/promptlayer)."
]
},
{
@@ -225,7 +225,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.11.6"
},
"vscode": {
"interpreter": {

View File

@@ -58,31 +58,24 @@ See a [usage example](/docs/integrations/llms/huggingface_textgen_inference).
from langchain_community.llms import HuggingFaceTextGenInference
```
## Chat models
### Models from Hugging Face
## Document Loaders
We can use the `Hugging Face` LLM classes or directly use the `ChatHuggingFace` class.
### Hugging Face dataset
>[Hugging Face Hub](https://huggingface.co/docs/hub/index) is home to over 75,000
> [datasets](https://huggingface.co/docs/hub/index#datasets) in more than 100 languages
> that can be used for a broad range of tasks across NLP, Computer Vision, and Audio.
> They used for a diverse range of tasks such as translation, automatic speech
> recognition, and image classification.
We need to install `datasets` python package.
We need to install several python packages.
```bash
pip install datasets
pip install huggingface_hub
pip install transformers
```
See a [usage example](/docs/integrations/document_loaders/hugging_face_dataset).
See a [usage example](/docs/integrations/chat/huggingface).
```python
from langchain_community.document_loaders.hugging_face_dataset import HuggingFaceDatasetLoader
from langchain_community.chat_models.huggingface import ChatHuggingFace
```
## Embedding Models
### Hugging Face Hub
@@ -126,6 +119,48 @@ See a [usage example](/docs/integrations/text_embedding/bge_huggingface).
from langchain_community.embeddings import HuggingFaceBgeEmbeddings
```
### Hugging Face Text Embeddings Inference (TEI)
>[Hugging Face Text Embeddings Inference (TEI)](https://huggingface.co/docs/text-generation-inference/index) is a toolkit for deploying and serving open-source
> text embeddings and sequence classification models. `TEI` enables high-performance extraction for the most popular models,
>including `FlagEmbedding`, `Ember`, `GTE` and `E5`.
We need to install `huggingface-hub` python package.
```bash
pip install huggingface-hub
```
See a [usage example](/docs/integrations/text_embedding/text_embeddings_inference).
```python
from langchain_community.embeddings import HuggingFaceHubEmbeddings
```
## Document Loaders
### Hugging Face dataset
>[Hugging Face Hub](https://huggingface.co/docs/hub/index) is home to over 75,000
> [datasets](https://huggingface.co/docs/hub/index#datasets) in more than 100 languages
> that can be used for a broad range of tasks across NLP, Computer Vision, and Audio.
> They used for a diverse range of tasks such as translation, automatic speech
> recognition, and image classification.
We need to install `datasets` python package.
```bash
pip install datasets
```
See a [usage example](/docs/integrations/document_loaders/hugging_face_dataset).
```python
from langchain_community.document_loaders.hugging_face_dataset import HuggingFaceDatasetLoader
```
## Tools

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,24 @@
# KDB.AI
>[KDB.AI](https://kdb.ai) is a powerful knowledge-based vector database and search engine that allows you to build scalable, reliable AI applications, using real-time data, by providing advanced search, recommendation and personalization.
## Installation and Setup
Install the Python SDK:
```bash
pip install kdbai-client
```
## Vector store
There exists a wrapper around KDB.AI indexes, allowing you to use it as a vectorstore,
whether for semantic search or example selection.
```python
from langchain_community.vectorstores import KDBAI
```
For a more detailed walkthrough of the KDB.AI vectorstore, see [this notebook](/docs/integrations/vectorstores/kdbai)

View File

@@ -60,21 +60,27 @@ konko.Model.list()
## Calling a model
Find a model on the [Konko Introduction page](https://docs.konko.ai/docs#available-models)
For example, for this [LLama 2 model](https://docs.konko.ai/docs/meta-llama-2-13b-chat). The model id would be: `"meta-llama/Llama-2-13b-chat-hf"`
Find a model on the [Konko Introduction page](https://docs.konko.ai/docs/list-of-models)
Another way to find the list of models running on the Konko instance is through this [endpoint](https://docs.konko.ai/reference/listmodels).
From here, we can initialize our model:
## Examples of Endpoint Usage
```python
chat_instance = ChatKonko(max_tokens=10, model = 'meta-llama/Llama-2-13b-chat-hf')
```
And run it:
- **ChatCompletion with Mistral-7B:**
```python
chat_instance = ChatKonko(max_tokens=10, model = 'mistralai/mistral-7b-instruct-v0.1')
msg = HumanMessage(content="Hi")
chat_response = chat_instance([msg])
```
```python
msg = HumanMessage(content="Hi")
chat_response = chat_instance([msg])
```
- **Completion with mistralai/Mistral-7B-v0.1:**
```python
from langchain.llms import Konko
llm = Konko(max_tokens=800, model='mistralai/Mistral-7B-v0.1')
prompt = "Generate a Product Description for Apple Iphone 15"
response = llm(prompt)
```
For further assistance, contact [support@konko.ai](mailto:support@konko.ai) or join our [Discord](https://discord.gg/TXV2s3z7RZ).

View File

@@ -0,0 +1,53 @@
{
"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",
"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

@@ -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

@@ -5,9 +5,7 @@
"id": "134a0785",
"metadata": {},
"source": [
"# Chat Over Documents with Vectara\n",
"\n",
"This notebook is based on the [chat_vector_db](https://github.com/hwchase17/langchain/blob/master/docs/modules/chains/index_examples/chat_vector_db.html) notebook, but using Vectara as the vector database."
"# Chat Over Documents with Vectara"
]
},
{
@@ -186,9 +184,7 @@
"cell_type": "code",
"execution_count": 8,
"id": "e8ce4fe9",
"metadata": {
"scrolled": false
},
"metadata": {},
"outputs": [],
"source": [
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
@@ -547,7 +543,6 @@
"execution_count": 26,
"id": "e2badd21",
"metadata": {
"scrolled": false,
"tags": []
},
"outputs": [],
@@ -755,7 +750,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
"version": "3.11.6"
}
},
"nbformat": 4,

View File

@@ -24,7 +24,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "b37bd138-4f3c-4d2c-bc4b-be705ce27a09",
"metadata": {
"tags": []
@@ -40,7 +40,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 13,
"id": "c47b0b26-6d51-4beb-aedb-ad09740a9a2b",
"metadata": {},
"outputs": [],
@@ -55,19 +55,12 @@
},
{
"cell_type": "code",
"execution_count": null,
"id": "2268c17f-5cc3-457b-928b-0d470154c3a8",
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"OpenAI API Key:\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "28e8dc12",
"metadata": {},
"execution_count": 14,
"id": "6fa3d916",
"metadata": {
"jp-MarkdownHeadingCollapsed": true,
"tags": []
},
"outputs": [],
"source": [
"# Helper function for printing docs\n",
@@ -95,8 +88,8 @@
},
{
"cell_type": "code",
"execution_count": 22,
"id": "9fbcc58f",
"execution_count": 15,
"id": "b7648612",
"metadata": {},
"outputs": [
{
@@ -111,28 +104,20 @@
"----------------------------------------------------------------------------------------------------\n",
"Document 2:\n",
"\n",
"We cannot let this happen. \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",
"Document 3:\n",
"\n",
"As I said last year, especially to our younger transgender Americans, I will always have your back as your President, so you can be yourself and reach your God-given potential. \n",
"\n",
"While it often appears that we never agree, that isnt true. I signed 80 bipartisan bills into law last year. From preventing government shutdowns to protecting Asian-Americans from still-too-common hate crimes to reforming military justice.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 3:\n",
"\n",
"A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since shes been nominated, shes received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. \n",
"\n",
"And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 4:\n",
"\n",
"He met the Ukrainian people. \n",
"\n",
"From President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world. \n",
"\n",
"Groups of citizens blocking tanks with their bodies. Everyone from students to retirees teachers turned soldiers defending their homeland. \n",
"\n",
"In this struggle as President Zelenskyy said in his speech to the European Parliament “Light will win over darkness.” The Ukrainian Ambassador to the United States is here tonight.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 5:\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",
@@ -141,64 +126,86 @@
"\n",
"So lets not abandon our streets. Or choose between safety and equal justice.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 5:\n",
"\n",
"He met the Ukrainian people. \n",
"\n",
"From President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world. \n",
"\n",
"Groups of citizens blocking tanks with their bodies. Everyone from students to retirees teachers turned soldiers defending their homeland. \n",
"\n",
"In this struggle as President Zelenskyy said in his speech to the European Parliament “Light will win over darkness.” The Ukrainian Ambassador to the United States is here tonight.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 6:\n",
"\n",
"So lets not abandon our streets. Or choose between safety and equal justice. \n",
"\n",
"Lets come together to protect our communities, restore trust, and hold law enforcement accountable. \n",
"\n",
"Thats why the Justice Department required body cameras, banned chokeholds, and restricted no-knock warrants for its officers.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 7:\n",
"\n",
"But that trickle-down theory led to weaker economic growth, lower wages, bigger deficits, and the widest gap between those at the top and everyone else in nearly a century. \n",
"\n",
"Vice President Harris and I ran for office with a new economic vision for America. \n",
"\n",
"Invest in America. Educate Americans. Grow the workforce. Build the economy from the bottom up \n",
"and the middle out, not from the top down. \n",
"\n",
"Because we know that when the middle class grows, the poor have a ladder up and the wealthy do very well. \n",
"\n",
"America used to have the best roads, bridges, and airports on Earth. \n",
"\n",
"Now our infrastructure is ranked 13th in the world.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 7:\n",
"\n",
"And tonight, Im announcing that the Justice Department will name a chief prosecutor for pandemic fraud. \n",
"\n",
"By the end of this year, the deficit will be down to less than half what it was before I took office. \n",
"\n",
"The only president ever to cut the deficit by more than one trillion dollars in a single year. \n",
"\n",
"Lowering your costs also means demanding more competition. \n",
"\n",
"Im a capitalist, but capitalism without competition isnt capitalism. \n",
"\n",
"Its exploitation—and it drives up prices.\n",
"and the middle out, not from the top down.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 8:\n",
"\n",
"For the past 40 years we were told that if we gave tax breaks to those at the very top, the benefits would trickle down to everyone else. \n",
"A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since shes been nominated, shes received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. \n",
"\n",
"But that trickle-down theory led to weaker economic growth, lower wages, bigger deficits, and the widest gap between those at the top and everyone else in nearly a century. \n",
"\n",
"Vice President Harris and I ran for office with a new economic vision for America.\n",
"And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 9:\n",
"\n",
"All told, we created 369,000 new manufacturing jobs in America just last year. \n",
"The widow of Sergeant First Class Heath Robinson. \n",
"\n",
"Powered by people Ive met like JoJo Burgess, from generations of union steelworkers from Pittsburgh, whos here with us tonight. \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",
"\n",
"But cancer from prolonged exposure to burn pits ravaged Heaths lungs and body. \n",
"\n",
"Danielle says Heath was a fighter to the very end.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 10:\n",
"\n",
"As Ive told Xi Jinping, it is never a good bet to bet against the American people. \n",
"\n",
"Well create good jobs for millions of Americans, modernizing roads, airports, ports, and waterways all across America. \n",
"\n",
"And well do it all to withstand the devastating effects of the climate crisis and promote environmental justice.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 11:\n",
"\n",
"As Ohio Senator Sherrod Brown says, “Its time to bury the label “Rust Belt.” \n",
"\n",
"Its time. \n",
"\n",
"But with all the bright spots in our economy, record job growth and higher wages, too many families are struggling to keep up with the bills.\n",
"But with all the bright spots in our economy, record job growth and higher wages, too many families are struggling to keep up with the bills. \n",
"\n",
"Inflation is robbing them of the gains they might otherwise feel. \n",
"\n",
"I get it. Thats why my top priority is getting prices under control.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 10:\n",
"Document 12:\n",
"\n",
"Im also calling on Congress: pass a law to make sure veterans devastated by toxic exposures in Iraq and Afghanistan finally get the benefits and comprehensive health care they deserve. \n",
"This was a bipartisan effort, and I want to thank the members of both parties who worked to make it happen. \n",
"\n",
"And fourth, lets end cancer as we know it. \n",
"Were done talking about infrastructure weeks. \n",
"\n",
"This is personal to me and Jill, to Kamala, and to so many of you. \n",
"Were going to have an infrastructure decade. \n",
"\n",
"Cancer is the #2 cause of death in Americasecond only to heart disease.\n",
"It is going to transform America and put us on a path to win the economic competition of the 21st Century that we face with the rest of the world—particularly with China. \n",
"\n",
"As Ive told Xi Jinping, it is never a good bet to bet against the American people.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 11:\n",
"Document 13:\n",
"\n",
"He will never extinguish their love of freedom. He will never weaken the resolve of the free world. \n",
"\n",
@@ -210,100 +217,8 @@
"\n",
"I understand.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 12:\n",
"\n",
"Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \n",
"\n",
"Last year COVID-19 kept us apart. This year we are finally together again. \n",
"\n",
"Tonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \n",
"\n",
"With a duty to one another to the American people to the Constitution. \n",
"\n",
"And with an unwavering resolve that freedom will always triumph over tyranny.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 13:\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",
"Document 14:\n",
"\n",
"And soon, well strengthen the Violence Against Women Act that I first wrote three decades ago. It is important for us to show the nation that we can come together and do big things. \n",
"\n",
"So tonight Im offering a Unity Agenda for the Nation. Four big things we can do together. \n",
"\n",
"First, beat the opioid epidemic. \n",
"\n",
"There is so much we can do. Increase funding for prevention, treatment, harm reduction, and recovery.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 15:\n",
"\n",
"Third, support our veterans. \n",
"\n",
"Veterans are the best of us. \n",
"\n",
"Ive always believed that we have a sacred obligation to equip all those we send to war and care for them and their families when they come home. \n",
"\n",
"My administration is providing assistance with job training and housing, and now helping lower-income veterans get VA care debt-free. \n",
"\n",
"Our troops in Iraq and Afghanistan faced many dangers.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 16:\n",
"\n",
"When we invest in our workers, when we build the economy from the bottom up and the middle out together, we can do something we havent done in a long time: build a better America. \n",
"\n",
"For more than two years, COVID-19 has impacted every decision in our lives and the life of the nation. \n",
"\n",
"And I know youre tired, frustrated, and exhausted. \n",
"\n",
"But I also know this.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 17:\n",
"\n",
"Now is the hour. \n",
"\n",
"Our moment of responsibility. \n",
"\n",
"Our test of resolve and conscience, of history itself. \n",
"\n",
"It is in this moment that our character is formed. Our purpose is found. Our future is forged. \n",
"\n",
"Well I know this nation. \n",
"\n",
"We will meet the test. \n",
"\n",
"To protect freedom and liberty, to expand fairness and opportunity. \n",
"\n",
"We will save democracy. \n",
"\n",
"As hard as these times have been, I am more optimistic about America today than I have been my whole life.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 18:\n",
"\n",
"He didnt know how to stop fighting, and neither did she. \n",
"\n",
"Through her pain she found purpose to demand we do better. \n",
"\n",
"Tonight, Danielle—we are. \n",
"\n",
"The VA is pioneering new ways of linking toxic exposures to diseases, already helping more veterans get benefits. \n",
"\n",
"And tonight, Im announcing were expanding eligibility to veterans suffering from nine respiratory cancers.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 19:\n",
"\n",
"I understand. \n",
"\n",
"I remember when my Dad had to leave our home in Scranton, Pennsylvania to find work. I grew up in a family where if the price of food went up, you felt it. \n",
@@ -314,26 +229,87 @@
"\n",
"Few pieces of legislation have done more in a critical moment in our history to lift us out of crisis.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 15:\n",
"\n",
"My administration is providing assistance with job training and housing, and now helping lower-income veterans get VA care debt-free. \n",
"\n",
"Our troops in Iraq and Afghanistan faced many dangers. \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",
"Document 16:\n",
"\n",
"Danielle says Heath was a fighter to the very end. \n",
"\n",
"He didnt know how to stop fighting, and neither did she. \n",
"\n",
"Through her pain she found purpose to demand we do better. \n",
"\n",
"Tonight, Danielle—we are. \n",
"\n",
"The VA is pioneering new ways of linking toxic exposures to diseases, already helping more veterans get benefits. \n",
"\n",
"And tonight, Im announcing were expanding eligibility to veterans suffering from nine respiratory cancers.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 17:\n",
"\n",
"Cancer is the #2 cause of death in Americasecond only to heart disease. \n",
"\n",
"Last month, I announced our plan to supercharge \n",
"the Cancer Moonshot that President Obama asked me to lead six years ago. \n",
"\n",
"Our goal is to cut the cancer death rate by at least 50% over the next 25 years, turn more cancers from death sentences into treatable diseases. \n",
"\n",
"More support for patients and families. \n",
"\n",
"To get there, I call on Congress to fund ARPA-H, the Advanced Research Projects Agency for Health.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 18:\n",
"\n",
"My plan to fight inflation will lower your costs and lower the deficit. \n",
"\n",
"17 Nobel laureates in economics say my plan will ease long-term inflationary pressures. Top business leaders and most Americans support my plan. And heres the plan: \n",
"\n",
"First cut the cost of prescription drugs. Just look at insulin. One in ten Americans has diabetes. In Virginia, I met a 13-year-old boy named Joshua Davis.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 19:\n",
"\n",
"Lets pass the Paycheck Fairness Act and paid leave. \n",
"\n",
"Raise the minimum wage to $15 an hour and extend the Child Tax Credit, so no one has to raise a family in poverty. \n",
"\n",
"Lets increase Pell Grants and increase our historic support of HBCUs, and invest in what Jill—our First Lady who teaches full-time—calls Americas best-kept secret: community colleges. \n",
"\n",
"And lets pass the PRO Act when a majority of workers want to form a union—they shouldnt be stopped.\n",
"----------------------------------------------------------------------------------------------------\n",
"Document 20:\n",
"\n",
"So lets not abandon our streets. Or choose between safety and equal justice. \n",
"Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \n",
"\n",
"Lets come together to protect our communities, restore trust, and hold law enforcement accountable. \n",
"Last year COVID-19 kept us apart. This year we are finally together again. \n",
"\n",
"Thats why the Justice Department required body cameras, banned chokeholds, and restricted no-knock warrants for its officers.\n"
"Tonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \n",
"\n",
"With a duty to one another to the American people to the Constitution. \n",
"\n",
"And with an unwavering resolve that freedom will always triumph over tyranny.\n"
]
}
],
"source": [
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"from langchain_community.document_loaders import TextLoader\n",
"from langchain_community.embeddings import CohereEmbeddings\n",
"from langchain_community.vectorstores import FAISS\n",
"from langchain_openai import OpenAIEmbeddings\n",
"\n",
"documents = TextLoader(\"../../modules/state_of_the_union.txt\").load()\n",
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)\n",
"texts = text_splitter.split_documents(documents)\n",
"retriever = FAISS.from_documents(texts, OpenAIEmbeddings()).as_retriever(\n",
"retriever = FAISS.from_documents(texts, CohereEmbeddings()).as_retriever(\n",
" search_kwargs={\"k\": 20}\n",
")\n",
"\n",
@@ -353,8 +329,8 @@
},
{
"cell_type": "code",
"execution_count": 31,
"id": "9a658023",
"execution_count": 16,
"id": "b83dfedb",
"metadata": {},
"outputs": [
{
@@ -388,9 +364,9 @@
"source": [
"from langchain.retrievers import ContextualCompressionRetriever\n",
"from langchain.retrievers.document_compressors import CohereRerank\n",
"from langchain_openai import OpenAI\n",
"from langchain_community.llms import Cohere\n",
"\n",
"llm = OpenAI(temperature=0)\n",
"llm = Cohere(temperature=0)\n",
"compressor = CohereRerank()\n",
"compression_retriever = ContextualCompressionRetriever(\n",
" base_compressor=compressor, base_retriever=retriever\n",
@@ -412,7 +388,7 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 17,
"id": "367dafe0",
"metadata": {},
"outputs": [],
@@ -422,19 +398,19 @@
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": 18,
"id": "ae697ca4",
"metadata": {},
"outputs": [],
"source": [
"chain = RetrievalQA.from_chain_type(\n",
" llm=OpenAI(temperature=0), retriever=compression_retriever\n",
" llm=Cohere(temperature=0), retriever=compression_retriever\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 34,
"execution_count": 19,
"id": "46ee62fc",
"metadata": {},
"outputs": [
@@ -442,10 +418,10 @@
"data": {
"text/plain": [
"{'query': 'What did the president say about Ketanji Brown Jackson',\n",
" 'result': \" The president said that Ketanji Brown Jackson is one of the nation's top legal minds and that she is a consensus builder who has received a broad range of support from the Fraternal Order of Police to former judges appointed by Democrats and Republicans.\"}"
" 'result': \" The president speaks highly of Ketanji Brown Jackson, stating that she is one of the nation's top legal minds, and will continue the legacy of excellence of Justice Breyer. The president also mentions that he worked with her family and that she comes from a family of public school educators and police officers. Since her nomination, she has received support from various groups, including the Fraternal Order of Police and judges from both major political parties. \\n\\nWould you like me to extract another sentence from the provided text? \"}"
]
},
"execution_count": 34,
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
@@ -453,14 +429,6 @@
"source": [
"chain({\"query\": query})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "700a8133",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@@ -0,0 +1,186 @@
{
"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

@@ -10,9 +10,42 @@
"Let's load the OpenAI Embedding class."
]
},
{
"cell_type": "markdown",
"id": "40ff98ff-58e9-4716-8788-227a5c3f473d",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"First we install langchain-openai and set the required env vars"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"id": "c66c4613-6c67-40ca-b3b1-c026750d1742",
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-openai"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "62e3710e-55a0-44fb-ba51-2f1d520dfc38",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "0be1af71",
"metadata": {},
"outputs": [],
@@ -22,17 +55,17 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 5,
"id": "2c66e5da",
"metadata": {},
"outputs": [],
"source": [
"embeddings = OpenAIEmbeddings()"
"embeddings = OpenAIEmbeddings(model=\"text-embedding-3-large\")"
]
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 6,
"id": "01370375",
"metadata": {},
"outputs": [],
@@ -40,33 +73,50 @@
"text = \"This is a test document.\""
]
},
{
"cell_type": "markdown",
"id": "f012c222-3fa9-470a-935c-758b2048d9af",
"metadata": {},
"source": [
"## Usage\n",
"### Embed query"
]
},
{
"cell_type": "code",
"execution_count": 31,
"execution_count": 7,
"id": "bfb6142c",
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Warning: model not found. Using cl100k_base encoding.\n"
]
}
],
"source": [
"query_result = embeddings.embed_query(text)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 8,
"id": "91bc875d-829b-4c3d-8e6f-fc2dda30a3bd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[-0.003186025367556387,\n",
" 0.011071979803637493,\n",
" -0.004020420763285827,\n",
" -0.011658221276953042,\n",
" -0.0010534035786864363]"
"[-0.014380056377383358,\n",
" -0.027191711627651764,\n",
" -0.020042716111860304,\n",
" 0.057301379620345545,\n",
" -0.022267658631828974]"
]
},
"execution_count": 32,
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@@ -75,33 +125,49 @@
"query_result[:5]"
]
},
{
"cell_type": "markdown",
"id": "6b733391-1e23-438b-a6bc-0d77eed9426e",
"metadata": {},
"source": [
"## Embed documents"
]
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": 9,
"id": "0356c3b7",
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Warning: model not found. Using cl100k_base encoding.\n"
]
}
],
"source": [
"doc_result = embeddings.embed_documents([text])"
]
},
{
"cell_type": "code",
"execution_count": 34,
"execution_count": 10,
"id": "a4b0d49e-0c73-44b6-aed5-5b426564e085",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[-0.003186025367556387,\n",
" 0.011071979803637493,\n",
" -0.004020420763285827,\n",
" -0.011658221276953042,\n",
" -0.0010534035786864363]"
"[-0.014380056377383358,\n",
" -0.027191711627651764,\n",
" -0.020042716111860304,\n",
" 0.057301379620345545,\n",
" -0.022267658631828974]"
]
},
"execution_count": 34,
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
@@ -112,131 +178,87 @@
},
{
"cell_type": "markdown",
"id": "bb61bbeb",
"id": "e7dc464a-6fa2-4cff-ab2e-49a0566d819b",
"metadata": {},
"source": [
"Let's load the OpenAI Embedding class with first generation models (e.g. text-search-ada-doc-001/text-search-ada-query-001). Note: These are not recommended models - see [here](https://platform.openai.com/docs/guides/embeddings/what-are-embeddings)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "c0b072cc",
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import OpenAIEmbeddings"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "a56b70f5",
"metadata": {},
"outputs": [],
"source": [
"embeddings = OpenAIEmbeddings(model=\"text-embedding-ada-002\")"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "14aefb64",
"metadata": {},
"outputs": [],
"source": [
"text = \"This is a test document.\""
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "3c39ed33",
"metadata": {},
"outputs": [],
"source": [
"query_result = embeddings.embed_query(text)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "2ee7ce9f-d506-4810-8897-e44334412714",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0.004452846988523035,\n",
" 0.034550655976098514,\n",
" -0.015029939040690051,\n",
" 0.03827273883655212,\n",
" 0.005785414075152477]"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"query_result[:5]"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "e3221db6",
"metadata": {},
"outputs": [],
"source": [
"doc_result = embeddings.embed_documents([text])"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "a0865409-3a6d-468f-939f-abde17c7cac3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0.004452846988523035,\n",
" 0.034550655976098514,\n",
" -0.015029939040690051,\n",
" 0.03827273883655212,\n",
" 0.005785414075152477]"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"doc_result[0][:5]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aaad49f8",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"## Specify dimensions\n",
"\n",
"# if you are behind an explicit proxy, you can use the OPENAI_PROXY environment variable to pass through\n",
"os.environ[\"OPENAI_PROXY\"] = \"http://proxy.yourcompany.com:8080\""
"With the `text-embedding-3` class of models, you can specify the size of the embeddings you want returned. For example by default `text-embedding-3-large` returned embeddings of dimension 3072:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "f7be1e7b-54c6-4893-b8ad-b872e6705735",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3072"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(doc_result[0])"
]
},
{
"cell_type": "markdown",
"id": "33287142-0835-4958-962f-385ae4447431",
"metadata": {},
"source": [
"But by passing in `dimensions=1024` we can reduce the size of our embeddings to 1024:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "854ee772-2de9-4a83-84e0-908033d98e4e",
"metadata": {},
"outputs": [],
"source": [
"embeddings_1024 = OpenAIEmbeddings(model=\"text-embedding-3-large\", dimensions=1024)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "3b464396-8d94-478b-8329-849b56e1ae23",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Warning: model not found. Using cl100k_base encoding.\n"
]
},
{
"data": {
"text/plain": [
"1024"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(embeddings_1024.embed_documents([text])[0])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "poetry-venv",
"language": "python",
"name": "python3"
"name": "poetry-venv"
},
"language_info": {
"codemirror_mode": {
@@ -248,7 +270,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.9.1"
},
"vscode": {
"interpreter": {

View File

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

View File

@@ -7,7 +7,9 @@
"source": [
"# Text Embeddings Inference\n",
"\n",
"Text Embeddings Inference (TEI) is a toolkit for deploying and serving open source text embeddings and sequence classification models. TEI enables high-performance extraction for the most popular models, including FlagEmbedding, Ember, GTE and E5.\n",
">[Hugging Face Text Embeddings Inference (TEI)](https://huggingface.co/docs/text-generation-inference/index) is a toolkit for deploying and serving open-source\n",
"> text embeddings and sequence classification models. `TEI` enables high-performance extraction for the most popular models,\n",
">including `FlagEmbedding`, `Ember`, `GTE` and `E5`.\n",
"\n",
"To use it within langchain, first install `huggingface-hub`."
]
@@ -21,7 +23,7 @@
},
"outputs": [],
"source": [
"%pip install --upgrade --quiet huggingface-hub -q"
"%pip install --upgrade huggingface-hub"
]
},
{
@@ -146,9 +148,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "conda_python3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "conda_python3"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
@@ -160,7 +162,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.13"
"version": "3.10.12"
}
},
"nbformat": 4,

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,

File diff suppressed because it is too large Load Diff

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

@@ -6,7 +6,7 @@
"id": "4x4kQ0VcodAC"
},
"source": [
"# Metaphor Search"
"# Exa Search"
]
},
{
@@ -15,13 +15,13 @@
"id": "V1x8wEUhodAH"
},
"source": [
"Metaphor is a search engine fully designed for use by LLMs. Search for documents on the internet using **natural language queries**, then retrieve **cleaned HTML content** from desired documents.\n",
"Exa (formerly Metaphor Search) is a search engine fully designed for use by LLMs. Search for documents on the internet using **natural language queries**, then retrieve **cleaned HTML content** from desired documents.\n",
"\n",
"Unlike keyword-based search (Google), Metaphor's neural search capabilities allow it to semantically understand queries and return relevant documents. For example, we could search `\"fascinating article about cats\"` and compare the search results from [Google](https://www.google.com/search?q=fascinating+article+about+cats) and [Metaphor](https://metaphor.systems/search?q=fascinating%20article%20about%20cats&autopromptString=Here%20is%20a%20fascinating%20article%20about%20cats%3A). Google gives us SEO-optimized listicles based on the keyword \"fascinating\". Metaphor just works.\n",
"Unlike keyword-based search (Google), Exa's neural search capabilities allow it to semantically understand queries and return relevant documents. For example, we could search `\"fascinating article about cats\"` and compare the search results from [Google](https://www.google.com/search?q=fascinating+article+about+cats) and [Exa](https://search.exa.ai/search?q=fascinating%20article%20about%20cats&autopromptString=Here%20is%20a%20fascinating%20article%20about%20cats%3A). Google gives us SEO-optimized listicles based on the keyword \"fascinating\". Exa just works.\n",
"\n",
"This notebook goes over how to use Metaphor Search with LangChain.\n",
"This notebook goes over how to use Exa Search with LangChain.\n",
"\n",
"First, get a Metaphor API key and add it as an environment variable. Get 1000 free searches/month by [signing up here](https://platform.metaphor.systems/)."
"First, get an Exa API key and add it as an environment variable. Get 1000 free searches/month by [signing up here](https://dashboard.exa.ai/)."
]
},
{
@@ -34,7 +34,88 @@
"source": [
"import os\n",
"\n",
"os.environ[\"METAPHOR_API_KEY\"] = \"...\""
"os.environ[\"EXA_API_KEY\"] = \"...\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And install the integration package"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install --upgrade --quiet langchain-exa\n",
"\n",
"# and some deps for this notebook\n",
"%pip install --upgrade --quiet langchain langchain-openai"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Using ExaSearchRetriever\n",
"\n",
"ExaSearchRetriever is a retriever that uses Exa Search to retrieve relevant documents."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[Result(title='Find Us:', url='https://travelila.com/best-time-to-visit-japan/', id='UFLQGtanQffaDErhngnzgA', score=0.1865834891796112, published_date='2021-01-05', author=None, text='If you are planning to spend your next vacation in Japan, then hold your excitement a bit. It would help if you planned which places you will visit in Japan and the countrys best things. Its entirel', highlights=None, highlight_scores=None), Result(title='When Is The Best Time of Year To Visit Japan?', url='https://boutiquejapan.com/when-is-the-best-time-of-year-to-visit-japan/', id='70b0IMuaQpshjpBpnwsfUg', score=0.17796635627746582, published_date='2022-09-26', author='Andres Zuleta', text='The good news for travelers is that there is no single best time of year to travel to Japan — yet this makes it hard to decide when to visit, as each season has its own special highlights.When plannin', highlights=None, highlight_scores=None), Result(title='Here is the Best Time to Visit Japan - Cooking Sun', url='https://www.cooking-sun.com/best-time-to-visit-japan/', id='2mh-xvoqGPT-ZRvX9GezNQ', score=0.17497511208057404, published_date='2018-12-17', author='Cooking Sun', text='Japan is a diverse and beautiful country thats brimming with culture. For some travelers, visiting Japan is a dream come true, since it grazes bucket lists across the globe. One of the best parts abo', highlights=None, highlight_scores=None), Result(title='When to Visit Japan? Bests Times and 2023 Travel Tips', url='https://www.jrailpass.com/blog/when-visit-japan-times', id='KqCnY8fF-nc76n1wNpIo1Q', score=0.17359933257102966, published_date='2020-02-18', author='JRailPass', text='When is the best time to visit Japan? This is a question without a simple answer. Japan is a year-round destination, with interesting activities, attractions, and festivities throughout the year.Your ', highlights=None, highlight_scores=None), Result(title='Complete Guide To Visiting Japan In February 2023: Weather, What To See & Do | LIVE JAPAN travel guide', url='https://livejapan.com/en/article-a0002948/', id='i3nmekOdM8_VBxPfcJmxng', score=0.17215865850448608, published_date='2019-11-13', author='Lucio Maurizi', text='\\n \\n \\n HOME\\n Complete Guide To Visiting Japan In February 2023: Weather, What To See & Do\\n \\n \\n \\n \\n \\n \\n Date published: 13 November 2019 \\n Last updated: 26 January 2021 \\n \\n \\n So youre planning your tra', highlights=None, highlight_scores=None)]\n"
]
},
{
"data": {
"text/plain": [
"AIMessage(content='Based on the given context, there is no specific best time mentioned to visit Japan. Each season has its own special highlights, and Japan is a year-round destination with interesting activities, attractions, and festivities throughout the year. Therefore, the best time to visit Japan depends on personal preferences and the specific activities or events one wants to experience.')"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.prompts import PromptTemplate\n",
"from langchain_core.runnables import RunnableParallel, RunnablePassthrough\n",
"from langchain_exa import ExaSearchRetriever, TextContentsOptions\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"# retrieve 5 documents, with content truncated at 1000 characters\n",
"retriever = ExaSearchRetriever(\n",
" k=5, text_contents_options=TextContentsOptions(max_length=200)\n",
")\n",
"\n",
"prompt = PromptTemplate.from_template(\n",
" \"\"\"Answer the following query based on the following context:\n",
"query: {query}\n",
"<context>\n",
"{context}\n",
"</context\"\"\"\n",
")\n",
"\n",
"llm = ChatOpenAI()\n",
"\n",
"chain = (\n",
" RunnableParallel({\"context\": retriever, \"query\": RunnablePassthrough()})\n",
" | prompt\n",
" | llm\n",
")\n",
"\n",
"chain.invoke(\"When is the best time to visit japan?\")"
]
},
{
@@ -43,14 +124,14 @@
"id": "ip5_D9MkodAK"
},
"source": [
"## Using the Metaphor SDK as LangChain Agent Tools\n",
"## Using the Exa SDK as LangChain Agent Tools\n",
"\n",
"The [Metaphor SDK](https://docs.metaphor.systems/) creates a client that can use the Metaphor API to perform three functions:\n",
"The [Exa SDK](https://docs.exa.ai/) creates a client that can use the Exa API to perform three functions:\n",
"- `search`: Given a natural language search query, retrieve a list of search results.\n",
"- `find_similar`: Given a URL, retrieve a list of search results corresponding to webpages which are similar to the document at the provided URL.\n",
"- `get_content`: Given a list of document ids fetched from `search` or `find_similar`, get cleaned HTML content for each document.\n",
"\n",
"We can use the `@tool` decorator and docstrings to create LangChain Tool wrappers that tell an LLM agent how to use Metaphor."
"We can use the `@tool` decorator and docstrings to create LangChain Tool wrappers that tell an LLM agent how to use Exa."
]
},
{
@@ -61,7 +142,7 @@
},
"outputs": [],
"source": [
"%pip install --upgrade --quiet metaphor-python"
"%pip install --upgrade --quiet langchain-exa"
]
},
{
@@ -72,16 +153,16 @@
},
"outputs": [],
"source": [
"from exa_py import Exa\n",
"from langchain.agents import tool\n",
"from metaphor_python import Metaphor\n",
"\n",
"metaphor = Metaphor(api_key=os.environ[\"METAPHOR_API_KEY\"])\n",
"exa = Exa(api_key=os.environ[\"EXA_API_KEY\"])\n",
"\n",
"\n",
"@tool\n",
"def search(query: str):\n",
" \"\"\"Search for a webpage based on the query.\"\"\"\n",
" return metaphor.search(f\"{query}\", use_autoprompt=True, num_results=5)\n",
" return exa.search(f\"{query}\", use_autoprompt=True, num_results=5)\n",
"\n",
"\n",
"@tool\n",
@@ -89,7 +170,7 @@
" \"\"\"Search for webpages similar to a given URL.\n",
" The url passed in should be a URL returned from `search`.\n",
" \"\"\"\n",
" return metaphor.find_similar(url, num_results=5)\n",
" return exa.find_similar(url, num_results=5)\n",
"\n",
"\n",
"@tool\n",
@@ -97,7 +178,7 @@
" \"\"\"Get the contents of a webpage.\n",
" The ids passed in should be a list of ids returned from `search`.\n",
" \"\"\"\n",
" return metaphor.get_contents(ids)\n",
" return exa.get_contents(ids)\n",
"\n",
"\n",
"tools = [search, get_contents, find_similar]"
@@ -109,9 +190,9 @@
"id": "sVe2ca9OodAO"
},
"source": [
"### Providing Metaphor Tools to an Agent\n",
"### Providing Exa Tools to an Agent\n",
"\n",
"We can provide the Metaphor tools we just created to a LangChain `OpenAIFunctionsAgent`. When asked to `Summarize for me a fascinating article about cats`, the agent uses the `search` tool to perform a Metaphor search with an appropriate search query, uses the `get_contents` tool to perform Metaphor content retrieval, and then returns a summary of the retrieved content."
"We can provide the Exa tools we just created to a LangChain `OpenAIFunctionsAgent`. When asked to `Summarize for me a fascinating article about cats`, the agent uses the `search` tool to perform a Exa search with an appropriate search query, uses the `get_contents` tool to perform Exa content retrieval, and then returns a summary of the retrieved content."
]
},
{
@@ -237,9 +318,11 @@
"id": "e3FHjxT-RoIH"
},
"source": [
"## Advanced Metaphor Features\n",
"## Advanced Exa Features\n",
"\n",
"Metaphor supports powerful filters by domain and date. We can provide a more powerful `search` tool to the agent that lets it decide to apply filters if they are useful for the objective. See all of Metaphor's search features [here](https://github.com/metaphorsystems/metaphor-python/)."
"Exa supports powerful filters by domain and date. We can provide a more powerful `search` tool to the agent that lets it decide to apply filters if they are useful for the objective. See all of Exa's search features [here](https://github.com/metaphorsystems/metaphor-python/).\n",
"\n",
"[//]: # \"TODO(erick): switch metaphor github link to exa github link when sdk published\""
]
},
{
@@ -250,10 +333,10 @@
},
"outputs": [],
"source": [
"from exa_py import Exa\n",
"from langchain.agents import tool\n",
"from metaphor_python import Metaphor\n",
"\n",
"metaphor = Metaphor(api_key=os.environ[\"METAPHOR_API_KEY\"])\n",
"exa = Exa(api_key=os.environ[\"Exa_API_KEY\"])\n",
"\n",
"\n",
"@tool\n",
@@ -262,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 metaphor.search(\n",
" return exa.search(\n",
" f\"{query}\",\n",
" use_autoprompt=True,\n",
" num_results=5,\n",
@@ -276,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 metaphor.find_similar(url, num_results=5)\n",
" return exa.find_similar(url, num_results=5)\n",
"\n",
"\n",
"@tool\n",
@@ -284,7 +367,7 @@
" \"\"\"Get the contents of a webpage.\n",
" The ids passed in should be a list of ids returned from `search`.\n",
" \"\"\"\n",
" return metaphor.get_contents(ids)\n",
" return exa.get_contents(ids)\n",
"\n",
"\n",
"tools = [search, get_contents, find_similar]"
@@ -449,7 +532,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.0"
"version": "3.11.4"
}
},
"nbformat": 4,

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

@@ -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

@@ -0,0 +1,703 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SAP HANA Cloud Vector Engine\n",
"\n",
">SAP HANA Cloud Vector Engine is a vector store fully integrated into the SAP HANA Cloud database."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Installation of the HANA database driver."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Pip install necessary package\n",
"%pip install --upgrade --quiet hdbcli"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To use `OpenAIEmbeddings` so we use the OpenAI API Key."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"ExecuteTime": {
"end_time": "2023-09-09T08:02:16.802456Z",
"start_time": "2023-09-09T08:02:07.065604Z"
}
},
"outputs": [],
"source": [
"import os\n",
"# Use OPENAI_API_KEY env variable\n",
"# os.environ[\"OPENAI_API_KEY\"] = \"Your OpenAI API key\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Load the sample document \"state_of_the_union.txt\" and create chunks from it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2023-09-09T08:02:25.452472Z",
"start_time": "2023-09-09T08:02:25.441563Z"
}
},
"outputs": [],
"source": [
"from langchain.docstore.document import Document\n",
"from langchain.text_splitter import CharacterTextSplitter\n",
"from langchain_community.document_loaders import TextLoader\n",
"from langchain_community.vectorstores.hanavector import HanaDB\n",
"from langchain_openai import OpenAIEmbeddings\n",
"\n",
"text_documents = TextLoader(\"../../modules/state_of_the_union.txt\").load()\n",
"text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0)\n",
"text_chunks = text_splitter.split_documents(text_documents)\n",
"print(f\"Number of document chunks: {len(text_chunks)}\")\n",
"\n",
"embeddings = OpenAIEmbeddings()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create a database connection to a HANA Cloud instance"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"ExecuteTime": {
"end_time": "2023-09-09T08:02:28.174088Z",
"start_time": "2023-09-09T08:02:28.162698Z"
}
},
"outputs": [],
"source": [
"from hdbcli import dbapi\n",
"\n",
"# Use connection settings from the environment\n",
"connection = dbapi.connect(\n",
" address=os.environ.get(\"HANA_DB_ADDRESS\"),\n",
" port=os.environ.get(\"HANA_DB_PORT\"),\n",
" user=os.environ.get(\"HANA_DB_USER\"),\n",
" password=os.environ.get(\"HANA_DB_PASSWORD\"),\n",
" autocommit=True,\n",
" sslValidateCertificate=False,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create a LangChain VectorStore interface for the HANA database and specify the table (collection) to use for accessing the vector embeddings"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"ExecuteTime": {
"end_time": "2023-09-09T08:04:16.696625Z",
"start_time": "2023-09-09T08:02:31.817790Z"
}
},
"outputs": [],
"source": [
"db = HanaDB(\n",
" embedding=embeddings, connection=connection, table_name=\"STATE_OF_THE_UNION\"\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add the loaded document chunks to the table. For this example, we delete any previous content from the table which might exist from previous runs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Delete already existing documents from the table\n",
"db.delete(filter={})\n",
"\n",
"# add the loaded document chunks\n",
"db.add_documents(text_chunks)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Perform a query to get the two best matching document chunks from the ones that we added in the previous step.\n",
"By default \"Cosine Similarity\" is used for the search."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"docs = db.similarity_search(query, k=2)\n",
"\n",
"for doc in docs:\n",
" print(\"-\" * 80)\n",
" print(doc.page_content)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Query the same content with \"Euclidian Distance\". The results shoud be the same as with \"Cosine Similarity\"."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.vectorstores.utils import DistanceStrategy\n",
"\n",
"db = HanaDB(\n",
" embedding=embeddings,\n",
" connection=connection,\n",
" distance_strategy=DistanceStrategy.EUCLIDEAN_DISTANCE,\n",
" table_name=\"STATE_OF_THE_UNION\",\n",
")\n",
"\n",
"query = \"What did the president say about Ketanji Brown Jackson\"\n",
"docs = db.similarity_search(query, k=2)\n",
"for doc in docs:\n",
" print(\"-\" * 80)\n",
" print(doc.page_content)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"Maximal Marginal Relevance Search (MMR)\n",
"\n",
"Maximal marginal relevance optimizes for similarity to query AND diversity among selected documents. First 20 (fetch_k) items will be retrieved from the DB. The MMR algorithm will then find the best 2 (k) matches."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2023-09-09T08:05:23.276819Z",
"start_time": "2023-09-09T08:05:21.972256Z"
},
"collapsed": false
},
"outputs": [],
"source": [
"docs = db.max_marginal_relevance_search(query, k=2, fetch_k=20)\n",
"for doc in docs:\n",
" print(\"-\" * 80)\n",
" print(doc.page_content)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic Vectorstore Operations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"db = HanaDB(\n",
" connection=connection, embedding=embeddings, table_name=\"LANGCHAIN_DEMO_BASIC\"\n",
")\n",
"\n",
"# Delete already existing documents from the table\n",
"db.delete(filter={})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can add simple text documents to the existing table."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"docs = [Document(page_content=\"Some text\"), Document(page_content=\"Other docs\")]\n",
"db.add_documents(docs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add documents with metadata."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"docs = [\n",
" Document(\n",
" page_content=\"foo\",\n",
" metadata={\"start\": 100, \"end\": 150, \"doc_name\": \"foo.txt\", \"quality\": \"bad\"},\n",
" ),\n",
" Document(\n",
" page_content=\"bar\",\n",
" metadata={\"start\": 200, \"end\": 250, \"doc_name\": \"bar.txt\", \"quality\": \"good\"},\n",
" ),\n",
"]\n",
"db.add_documents(docs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Query documents with specific metadata."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"docs = db.similarity_search(\"foobar\", k=2, filter={\"quality\": \"bad\"})\n",
"# With filtering on \"quality\"==\"bad\", only one document should be returned\n",
"for doc in docs:\n",
" print(\"-\" * 80)\n",
" print(doc.page_content)\n",
" print(doc.metadata)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Delete documents with specific metadata."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"db.delete(filter={\"quality\": \"bad\"})\n",
"\n",
"# Now the similarity search with the same filter will return no results\n",
"docs = db.similarity_search(\"foobar\", k=2, filter={\"quality\": \"bad\"})\n",
"print(len(docs))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Using a VectorStore as a retriever in chains for retrieval augmented generation (RAG)\n"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
"from langchain.memory import ConversationBufferMemory\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"# Access the vector DB with a new table\n",
"db = HanaDB(\n",
" connection=connection,\n",
" embedding=embeddings,\n",
" table_name=\"LANGCHAIN_DEMO_RETRIEVAL_CHAIN\",\n",
")\n",
"\n",
"# Delete already existing entries from the table\n",
"db.delete(filter={})\n",
"\n",
"# add the loaded document chunks from the \"State Of The Union\" file\n",
"db.add_documents(text_chunks)\n",
"\n",
"# Create a retriever instance of the vector store\n",
"retriever = db.as_retriever()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define the prompt."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
"from langchain.prompts import PromptTemplate\n",
"\n",
"prompt_template = \"\"\"\n",
"You are an expert in state of the union topics. You are provided multiple context items that are related to the prompt you have to answer.\n",
"Use the following pieces of context to answer the question at the end.\n",
"\n",
"```\n",
"{context}\n",
"```\n",
"\n",
"Question: {question}\n",
"\"\"\"\n",
"\n",
"PROMPT = PromptTemplate(\n",
" template=prompt_template, input_variables=[\"context\", \"question\"]\n",
")\n",
"chain_type_kwargs = {\"prompt\": PROMPT}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create the ConversationalRetrievalChain, which handles the chat history and the retrieval of similar document chunks to be added to the prompt."
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains import ConversationalRetrievalChain\n",
"\n",
"llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\")\n",
"memory = ConversationBufferMemory(\n",
" memory_key=\"chat_history\", output_key=\"answer\", return_messages=True\n",
")\n",
"qa_chain = ConversationalRetrievalChain.from_llm(\n",
" llm,\n",
" db.as_retriever(search_kwargs={\"k\": 5}),\n",
" return_source_documents=True,\n",
" memory=memory,\n",
" verbose=False,\n",
" combine_docs_chain_kwargs={\"prompt\": PROMPT},\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ask the first question (and verify how many text chunks have been used)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"question = \"What about Mexico and Guatemala?\"\n",
"\n",
"result = qa_chain.invoke({\"question\": question})\n",
"print(\"Answer from LLM:\")\n",
"print(\"================\")\n",
"print(result[\"answer\"])\n",
"\n",
"source_docs = result[\"source_documents\"]\n",
"print(\"================\")\n",
"print(f\"Number of used source document chunks: {len(source_docs)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Examine the used chunks of the chain in detail. Check if the best ranked chunk contains info about \"Mexico and Guatemala\" as mentioned in the question."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for doc in source_docs:\n",
" print(\"-\" * 80)\n",
" print(doc.page_content)\n",
" print(doc.metadata)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ask another question on the same conversational chain. The answer should relate to the previous answer given."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"question = \"What about other countries?\"\n",
"\n",
"result = qa_chain.invoke({\"question\": question})\n",
"print(\"Answer from LLM:\")\n",
"print(\"================\")\n",
"print(result[\"answer\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Standard tables vs. \"custom\" tables with vector data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As default behaviour, the table for the embeddings is created with 3 columns\n",
"* A column \"VEC_TEXT\", which contains the text of the Document\n",
"* A column \"VEC_METADATA\", which contains the metadata of the Document\n",
"* A column \"VEC_VECTOR\", which contains the embeddings-vector of the document's text"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Access the vector DB with a new table\n",
"db = HanaDB(\n",
" connection=connection, embedding=embeddings, table_name=\"LANGCHAIN_DEMO_NEW_TABLE\"\n",
")\n",
"\n",
"# Delete already existing entries from the table\n",
"db.delete(filter={})\n",
"\n",
"# Add a simple document with some metadata\n",
"docs = [\n",
" Document(\n",
" page_content=\"A simple document\",\n",
" metadata={\"start\": 100, \"end\": 150, \"doc_name\": \"simple.txt\"},\n",
" )\n",
"]\n",
"db.add_documents(docs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show the columns in table \"LANGCHAIN_DEMO_NEW_TABLE\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cur = connection.cursor()\n",
"cur.execute(\n",
" \"SELECT COLUMN_NAME, DATA_TYPE_NAME FROM SYS.TABLE_COLUMNS WHERE SCHEMA_NAME = CURRENT_SCHEMA AND TABLE_NAME = 'LANGCHAIN_DEMO_NEW_TABLE'\"\n",
")\n",
"rows = cur.fetchall()\n",
"for row in rows:\n",
" print(row)\n",
"cur.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show the value of the inserted document in the three columns "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cur = connection.cursor()\n",
"cur.execute(\n",
" \"SELECT VEC_TEXT, VEC_META, TO_NVARCHAR(VEC_VECTOR) FROM LANGCHAIN_DEMO_NEW_TABLE LIMIT 1\"\n",
")\n",
"rows = cur.fetchall()\n",
"print(rows[0][0]) # The text\n",
"print(rows[0][1]) # The metadata\n",
"print(rows[0][2]) # The vector\n",
"cur.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Custom tables must have at least three columns that match the semantics of a standard table\n",
"* A column with type \"NCLOB\" or \"NVARCHAR\" for the text/context of the embeddings\n",
"* A column with type \"NCLOB\" or \"NVARCHAR\" for the metadata \n",
"* A column with type REAL_VECTOR for the embedding vector\n",
"\n",
"The table can contain additional columns. When new Documents are inserted to the table, these addtional columns must allow NULL values."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create a new table \"MY_OWN_TABLE\" with three \"standard\" columns and one additional column\n",
"my_own_table_name = \"MY_OWN_TABLE\"\n",
"cur = connection.cursor()\n",
"cur.execute(\n",
" (\n",
" f\"CREATE TABLE {my_own_table_name} (\"\n",
" \"SOME_OTHER_COLUMN NVARCHAR(42), \"\n",
" \"MY_TEXT NVARCHAR(2048), \"\n",
" \"MY_METADATA NVARCHAR(1024), \"\n",
" \"MY_VECTOR REAL_VECTOR )\"\n",
" )\n",
")\n",
"\n",
"# Create a HanaDB instance with the own table\n",
"db = HanaDB(\n",
" connection=connection,\n",
" embedding=embeddings,\n",
" table_name=my_own_table_name,\n",
" content_column=\"MY_TEXT\",\n",
" metadata_column=\"MY_METADATA\",\n",
" vector_column=\"MY_VECTOR\",\n",
")\n",
"\n",
"# Add a simple document with some metadata\n",
"docs = [\n",
" Document(\n",
" page_content=\"Some other text\",\n",
" metadata={\"start\": 400, \"end\": 450, \"doc_name\": \"other.txt\"},\n",
" )\n",
"]\n",
"db.add_documents(docs)\n",
"\n",
"# Check if data has been inserted into our own table\n",
"cur.execute(f\"SELECT * FROM {my_own_table_name} LIMIT 1\")\n",
"rows = cur.fetchall()\n",
"print(rows[0][0]) # Value of column \"SOME_OTHER_DATA\". Should be NULL/None\n",
"print(rows[0][1]) # The text\n",
"print(rows[0][2]) # The metadata\n",
"print(rows[0][3]) # The vector\n",
"\n",
"cur.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add another document and perform a similarity search on the custom table"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"docs = [\n",
" Document(\n",
" page_content=\"Some more text\",\n",
" metadata={\"start\": 800, \"end\": 950, \"doc_name\": \"more.txt\"},\n",
" )\n",
"]\n",
"db.add_documents(docs)\n",
"\n",
"query = \"What's up?\"\n",
"docs = db.similarity_search(query, k=2)\n",
"for doc in docs:\n",
" print(\"-\" * 80)\n",
" print(doc.page_content)"
]
}
],
"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.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@@ -0,0 +1,514 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "08b3f3a3-7542-4d39-a9a1-f66e50ec3c0f",
"metadata": {},
"source": [
"# KDB.AI\n",
"\n",
"> [KDB.AI](https://kdb.ai/) is a powerful knowledge-based vector database and search engine that allows you to build scalable, reliable AI applications, using real-time data, by providing advanced search, recommendation and personalization.\n",
"\n",
"[This example](https://github.com/KxSystems/kdbai-samples/blob/main/document_search/document_search.ipynb) demonstrates how to use KDB.AI to run semantic search on unstructured text documents.\n",
"\n",
"To access your end point and API keys, [sign up to KDB.AI here](https://kdb.ai/get-started/).\n",
"\n",
"To set up your development environment, follow the instructions on the [KDB.AI pre-requisites page](https://code.kx.com/kdbai/pre-requisites.html).\n",
"\n",
"The following examples demonstrate some of the ways you can interact with KDB.AI through LangChain.\n",
"\n",
"## Import required packages"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "2704194d-c42d-463d-b162-fb95262e052c",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import time\n",
"from getpass import getpass\n",
"\n",
"import kdbai_client as kdbai\n",
"import pandas as pd\n",
"import requests\n",
"from langchain.chains import RetrievalQA\n",
"from langchain.document_loaders import PyPDFLoader\n",
"from langchain_community.vectorstores import KDBAI\n",
"from langchain_openai import ChatOpenAI, OpenAIEmbeddings"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "04848fcf-e128-4d63-af6c-b3991531d62e",
"metadata": {},
"outputs": [
{
"name": "stdin",
"output_type": "stream",
"text": [
"KDB.AI endpoint: https://ui.qa.cld.kx.com/instance/pcnvlmi860\n",
"KDB.AI API key: ········\n",
"OpenAI API Key: ········\n"
]
}
],
"source": [
"KDBAI_ENDPOINT = input(\"KDB.AI endpoint: \")\n",
"KDBAI_API_KEY = getpass(\"KDB.AI API key: \")\n",
"os.environ[\"OPENAI_API_KEY\"] = getpass(\"OpenAI API Key: \")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "d08a1468-6bff-4a65-8b4a-9835cfa997ad",
"metadata": {},
"outputs": [],
"source": [
"TEMP = 0.0\n",
"K = 3"
]
},
{
"cell_type": "markdown",
"id": "63a111d8-2422-4d33-85c0-bc95d25e330a",
"metadata": {},
"source": [
"## Create a KBD.AI Session"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9ffe4fee-2dc3-4943-917b-28adc3a69472",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Create a KDB.AI session...\n"
]
}
],
"source": [
"print(\"Create a KDB.AI session...\")\n",
"session = kdbai.Session(endpoint=KDBAI_ENDPOINT, api_key=KDBAI_API_KEY)"
]
},
{
"cell_type": "markdown",
"id": "a2ea7e87-f65c-43d9-bc67-be7bda86def2",
"metadata": {},
"source": [
"## Create a table"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "da27f31c-890e-46c0-8e01-1b8474ee3a70",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Create table \"documents\"...\n"
]
}
],
"source": [
"print('Create table \"documents\"...')\n",
"schema = {\n",
" \"columns\": [\n",
" {\"name\": \"id\", \"pytype\": \"str\"},\n",
" {\"name\": \"text\", \"pytype\": \"bytes\"},\n",
" {\n",
" \"name\": \"embeddings\",\n",
" \"pytype\": \"float32\",\n",
" \"vectorIndex\": {\"dims\": 1536, \"metric\": \"L2\", \"type\": \"hnsw\"},\n",
" },\n",
" {\"name\": \"tag\", \"pytype\": \"str\"},\n",
" {\"name\": \"title\", \"pytype\": \"bytes\"},\n",
" ]\n",
"}\n",
"table = session.create_table(\"documents\", schema)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "930ba64a-1cf9-4892-9335-8745c830497c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 44.1 ms, sys: 6.04 ms, total: 50.2 ms\n",
"Wall time: 213 ms\n"
]
},
{
"data": {
"text/plain": [
"562978"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"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)"
]
},
{
"cell_type": "markdown",
"id": "0f7da153-e7d4-4a4c-b044-ad7b4d893c7f",
"metadata": {},
"source": [
"## Read a PDF"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "00873e6b-f204-4dca-b82b-1c45d0b83ee5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Read a PDF...\n",
"CPU times: user 156 ms, sys: 12.5 ms, total: 169 ms\n",
"Wall time: 183 ms\n"
]
},
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"print(\"Read a PDF...\")\n",
"loader = PyPDFLoader(PDF)\n",
"pages = loader.load_and_split()\n",
"len(pages)"
]
},
{
"cell_type": "markdown",
"id": "3536c7db-0db7-446a-b61e-149fd3c2d1d8",
"metadata": {},
"source": [
"## Create a Vector Database from PDF Text"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b06d4a96-c3d5-426b-9e22-12925b14e5e6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Create a Vector Database from PDF text...\n",
"CPU times: user 211 ms, sys: 18.4 ms, total: 229 ms\n",
"Wall time: 2.23 s\n"
]
},
{
"data": {
"text/plain": [
"['3ef27d23-47cf-419b-8fe9-5dfae9e8e895',\n",
" 'd3a9a69d-28f5-434b-b95b-135db46695c8',\n",
" 'd2069bda-c0b8-4791-b84d-0c6f84f4be34']"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\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(\n",
" \"utf-8\"\n",
")\n",
"vectordb = KDBAI(table, embeddings)\n",
"vectordb.add_texts(texts=texts, metadatas=metadata)"
]
},
{
"cell_type": "markdown",
"id": "3b658f9a-61dd-4a88-9bcb-4651992f610d",
"metadata": {},
"source": [
"## Create LangChain Pipeline"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "6d848577-1192-4bb0-b721-37f52be5d9d0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Create LangChain Pipeline...\n",
"CPU times: user 40.8 ms, sys: 4.69 ms, total: 45.5 ms\n",
"Wall time: 44.7 ms\n"
]
}
],
"source": [
"%%time\n",
"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",
")"
]
},
{
"cell_type": "markdown",
"id": "21113a5e-d72d-4a44-9714-6b23ec95b755",
"metadata": {},
"source": [
"## Summarize the document in English"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "81668f8f-a416-4b58-93d2-8e0924ceca23",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"Summarize the document in English:\n",
"\n",
"The document is the Declaration of the Rights of Man and of the Citizen of 1789. It was written by the representatives of the French people and aims to declare the natural, inalienable, and sacred rights of every individual. These rights include freedom, property, security, and resistance to oppression. The document emphasizes the importance of equality and the principle that sovereignty resides in the nation. It also highlights the role of law in protecting individual rights and ensuring the common good. The document asserts the right to freedom of thought, expression, and religion, as long as it does not disturb public order. It emphasizes the need for a public force to guarantee the rights of all citizens and the importance of a fair and equal distribution of public contributions. The document also recognizes the right of citizens to hold public officials accountable and states that any society without the guarantee of rights and separation of powers does not have a constitution. Finally, it affirms the inviolable and sacred nature of property, stating that it can only be taken away for public necessity and with just compensation.\n",
"CPU times: user 144 ms, sys: 50.2 ms, total: 194 ms\n",
"Wall time: 4.96 s\n"
]
}
],
"source": [
"%%time\n",
"Q = \"Summarize the document in English:\"\n",
"print(f\"\\n\\n{Q}\\n\")\n",
"print(qabot.invoke(dict(query=Q))[\"result\"])"
]
},
{
"cell_type": "markdown",
"id": "9ce7667e-8c89-466c-8040-9ba62f3e57ec",
"metadata": {},
"source": [
"## Query the Data"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "e02a7acb-99ac-48f8-b93c-d95a8f9e87d4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"Is it a fair law and why ?\n",
"\n",
"As an AI language model, I don't have personal opinions. However, I can provide some analysis based on the given context. The text provided is an excerpt from the Declaration of the Rights of Man and of the Citizen of 1789, which is considered a foundational document in the history of human rights. It outlines the natural and inalienable rights of individuals, such as freedom, property, security, and resistance to oppression. It also emphasizes the principles of equality, the rule of law, and the separation of powers. \n",
"\n",
"Whether or not this law is considered fair is subjective and can vary depending on individual perspectives and societal norms. However, many consider the principles and rights outlined in this declaration to be fundamental and just. It is important to note that this declaration was a significant step towards establishing principles of equality and individual rights in France and has influenced subsequent human rights documents worldwide.\n",
"CPU times: user 85.1 ms, sys: 5.93 ms, total: 91.1 ms\n",
"Wall time: 5.11 s\n"
]
}
],
"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\"])"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "24dc85bd-cd35-4fb3-9d01-e00a896fd9a1",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"What are the rights and duties of the man, the citizen and the society ?\n",
"\n",
"According to the Declaration of the Rights of Man and of the Citizen of 1789, the rights and duties of man, citizen, and society are as follows:\n",
"\n",
"Rights of Man:\n",
"1. Men are born and remain free and equal in rights. Social distinctions can only be based on common utility.\n",
"2. The purpose of political association is the preservation of the natural and imprescriptible rights of man, which are liberty, property, security, and resistance to oppression.\n",
"3. The principle of sovereignty resides essentially in the nation. No body or individual can exercise any authority that does not emanate expressly from it.\n",
"4. Liberty consists of being able to do anything that does not harm others. The exercise of natural rights of each man has no limits other than those that ensure the enjoyment of these same rights by other members of society. These limits can only be determined by law.\n",
"5. The law has the right to prohibit only actions harmful to society. Anything not prohibited by law cannot be prevented, and no one can be compelled to do what it does not command.\n",
"6. The law is the expression of the general will. All citizens have the right to participate personally, or through their representatives, in its formation. It must be the same for all, whether it protects or punishes. All citizens, being equal in its eyes, are equally eligible to all public dignities, places, and employments, according to their abilities, and without other distinction than that of their virtues and talents.\n",
"7. No man can be accused, arrested, or detained except in cases determined by law and according to the forms it has prescribed. Those who solicit, expedite, execute, or cause to be executed arbitrary orders must be punished. But any citizen called or seized in virtue of the law must obey instantly; he renders himself culpable by resistance.\n",
"8. The law should establish only strictly and evidently necessary penalties, and no one can be punished except in virtue of a law established and promulgated prior to the offense, and legally applied.\n",
"9. Every man being presumed innocent until he has been declared guilty, if it is judged indispensable to arrest him, any rigor that is not necessary to secure his person must be severely repressed by the law.\n",
"10. No one should be disturbed for his opinions, even religious ones, as long as their manifestation does not disturb the established public order by law.\n",
"11. The free communication of ideas and opinions is one of the most precious rights of man. Every citizen may therefore speak, write, and print freely, except to respond to the abuse of this liberty in cases determined by law.\n",
"12. The guarantee of the rights of man and of the citizen requires a public force. This force is therefore instituted for the advantage of all and not for the particular utility of those to whom it is entrusted.\n",
"13. For the maintenance of the public force and for the expenses of administration, a common contribution is necessary. It must be equally distributed among all citizens, in proportion to their abilities.\n",
"14. All citizens have the right to ascertain, by themselves or through their representatives, the necessity of the public contribution, to consent to it freely, to follow its use, and to determine its amount, basis, collection, and duration.\n",
"15. Society has the right to ask any public agent for an account of his administration.\n",
"16. Any society in which the guarantee of rights is not assured, nor the separation of powers determined, has no constitution.\n",
"17. Property being an inviolable and sacred right, no one can be deprived of it, except when public necessity, legally determined, obviously requires it, and under the condition of a just and prior indemnity.\n",
"\n",
"Duties of the Citizen:\n",
"The Declaration does not explicitly mention the duties of the citizen, but it emphasizes the importance of the law and the need for citizens to obey it. It also highlights the responsibility of citizens to participate in the formation of the law and to hold public agents accountable for their administration.\n",
"\n",
"Duties of Society:\n",
"The Declaration does not explicitly mention the duties of society, but it emphasizes the importance of guaranteeing the rights of man and of the citizen. Society is responsible for ensuring the preservation of these rights and the separation of powers, as well as providing a public force for the advantage of all.\n",
"CPU times: user 86.5 ms, sys: 5.45 ms, total: 92 ms\n",
"Wall time: 14.9 s\n"
]
}
],
"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\"])"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d55b7980-a3d3-45d7-a310-99492edb098b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"Is this law practical ?\n",
"\n",
"As an AI language model, I cannot provide personal opinions or subjective judgments on whether a law is practical or not. The texts provided are excerpts from the French Constitution and the Declaration of the Rights of Man and of the Citizen of 1789. These texts outline fundamental rights and principles that form the basis of the French legal system. The practicality of a law is often a matter of interpretation and can vary depending on the context and specific circumstances. It is ultimately up to legal experts, lawmakers, and the judiciary to determine the practicality and application of these laws in specific cases.\n",
"CPU times: user 91.4 ms, sys: 5.89 ms, total: 97.3 ms\n",
"Wall time: 2.78 s\n"
]
}
],
"source": [
"%%time\n",
"Q = \"Is this law practical ?\"\n",
"print(f\"\\n\\n{Q}\\n\")\n",
"print(qabot.invoke(dict(query=Q))[\"result\"])"
]
},
{
"cell_type": "markdown",
"id": "5f9d0a3c-4941-4f65-b6b8-aefe4f6abd14",
"metadata": {},
"source": [
"## Clean up the Documents table"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "cdddda29-e28d-423f-b1c6-f77d39acc3dd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Clean up KDB.AI \"documents\" table and index for similarity search\n",
"# so this notebook could be played again and again\n",
"session.table(\"documents\").drop()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "23cb1359-f32c-4b47-a885-cbf3cbae5b14",
"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.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

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

@@ -129,7 +129,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 1,
"id": "a0fbfbba-3c82-4298-a312-9cec016d9d2e",
"metadata": {},
"outputs": [],
@@ -138,8 +138,7 @@
"from langchain.agents import AgentExecutor\n",
"from langchain.agents.format_scratchpad import format_to_openai_function_messages\n",
"from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser\n",
"from langchain.tools import DuckDuckGoSearchResults\n",
"from langchain_community.tools.convert_to_openai import format_tool_to_openai_function\n",
"from langchain_community.tools import DuckDuckGoSearchResults\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"# Fetches the latest version of this prompt\n",
@@ -156,7 +155,7 @@
" ), # General internet search using DuckDuckGo\n",
"]\n",
"\n",
"llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])\n",
"llm_with_tools = llm.bind_functions(tools)\n",
"\n",
"runnable_agent = (\n",
" {\n",
@@ -334,7 +333,6 @@
"from langchain.agents import AgentExecutor, AgentType, initialize_agent, load_tools\n",
"from langchain.agents.format_scratchpad import format_to_openai_function_messages\n",
"from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser\n",
"from langchain_community.tools.convert_to_openai import format_tool_to_openai_function\n",
"from langchain_openai import ChatOpenAI\n",
"\n",
"\n",
@@ -1345,9 +1343,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "poetry-venv",
"language": "python",
"name": "python3"
"name": "poetry-venv"
},
"language_info": {
"codemirror_mode": {
@@ -1359,7 +1357,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.2"
"version": "3.9.1"
}
},
"nbformat": 4,

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

@@ -43,7 +43,7 @@
"metadata": {},
"outputs": [],
"source": [
"# pip install chromadb"
"%pip install -qU chromadb langchain langchain-community langchain-openai"
]
},
{
@@ -61,7 +61,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 2,
"id": "e3002ed7",
"metadata": {},
"outputs": [],
@@ -96,14 +96,12 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"id": "204ef7ca",
"metadata": {},
"outputs": [],
"source": [
"from langchain.agents.agent_toolkits.conversational_retrieval.tool import (\n",
" create_retriever_tool,\n",
")\n",
"from langchain.tools.retriever import create_retriever_tool\n",
"\n",
"retriever_tool = create_retriever_tool(\n",
" retriever,\n",
@@ -124,15 +122,14 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 4,
"id": "2df91723",
"metadata": {},
"outputs": [],
"source": [
"from typing import List\n",
"\n",
"from langchain.utils.openai_functions import convert_pydantic_to_openai_function\n",
"from pydantic import BaseModel, Field\n",
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
"\n",
"\n",
"class Response(BaseModel):\n",
@@ -169,7 +166,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 5,
"id": "dfb73fe3",
"metadata": {},
"outputs": [],
@@ -181,7 +178,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 6,
"id": "5b46cdb2",
"metadata": {},
"outputs": [],
@@ -224,14 +221,13 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"id": "73c785f9",
"metadata": {},
"outputs": [],
"source": [
"from langchain.agents import AgentExecutor\n",
"from langchain.agents.format_scratchpad import format_to_openai_function_messages\n",
"from langchain_community.tools.convert_to_openai import format_tool_to_openai_function\n",
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"from langchain_openai import ChatOpenAI"
]
@@ -269,14 +265,7 @@
"metadata": {},
"outputs": [],
"source": [
"llm_with_tools = llm.bind(\n",
" functions=[\n",
" # The retriever tool\n",
" format_tool_to_openai_function(retriever_tool),\n",
" # Response schema\n",
" convert_pydantic_to_openai_function(Response),\n",
" ]\n",
")"
"llm_with_tools = llm.bind_functions([retriever_tool, Response])"
]
},
{
@@ -302,7 +291,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 12,
"id": "2cfd783e",
"metadata": {},
"outputs": [],
@@ -322,7 +311,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 20,
"id": "2667c9a4",
"metadata": {},
"outputs": [
@@ -333,7 +322,55 @@
"\n",
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3m\u001b[0m\u001b[36;1m\u001b[1;3m[Document(page_content='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\\nTonight, 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\\nOne of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \\n\\nAnd 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.', metadata={'page_chunk': 31, 'source': '../../state_of_the_union.txt'}), Document(page_content='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\\nWhen they came home, many of the worlds fittest and best trained warriors were never the same. \\n\\nHeadaches. Numbness. Dizziness. \\n\\nA cancer that would put them in a flag-draped coffin. \\n\\nI know. \\n\\nOne of those soldiers was my son Major Beau Biden. \\n\\nWe 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\\nBut Im committed to finding out everything we can. \\n\\nCommitted to military families like Danielle Robinson from Ohio. \\n\\nThe widow of Sergeant First Class Heath Robinson. \\n\\nHe was born a soldier. Army National Guard. Combat medic in Kosovo and Iraq. \\n\\nStationed near Baghdad, just yards from burn pits the size of football fields. \\n\\nHeaths widow Danielle is here with us tonight. They loved going to Ohio State football games. He loved building Legos with their daughter.', metadata={'page_chunk': 37, 'source': '../../state_of_the_union.txt'}), Document(page_content='A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since shes been nominated, shes received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. \\n\\nAnd if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. \\n\\nWe can do both. At our border, weve installed new technology like cutting-edge scanners to better detect drug smuggling. \\n\\nWeve set up joint patrols with Mexico and Guatemala to catch more human traffickers. \\n\\nWere putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. \\n\\nWere securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders.', metadata={'page_chunk': 32, 'source': '../../state_of_the_union.txt'}), Document(page_content='But cancer from prolonged exposure to burn pits ravaged Heaths lungs and body. \\n\\nDanielle says Heath was a fighter to the very end. \\n\\nHe didnt know how to stop fighting, and neither did she. \\n\\nThrough her pain she found purpose to demand we do better. \\n\\nTonight, Danielle—we are. \\n\\nThe VA is pioneering new ways of linking toxic exposures to diseases, already helping more veterans get benefits. \\n\\nAnd tonight, Im announcing were expanding eligibility to veterans suffering from nine respiratory cancers. \\n\\nIm also calling on Congress: pass a law to make sure veterans devastated by toxic exposures in Iraq and Afghanistan finally get the benefits and comprehensive health care they deserve. \\n\\nAnd fourth, lets end cancer as we know it. \\n\\nThis is personal to me and Jill, to Kamala, and to so many of you. \\n\\nCancer is the #2 cause of death in Americasecond only to heart disease.', metadata={'page_chunk': 38, 'source': '../../state_of_the_union.txt'})]\u001b[0m\u001b[32;1m\u001b[1;3m{'name': 'Response', 'arguments': '{\\n \"answer\": \"President mentioned Ketanji Brown Jackson as a nominee for the United States Supreme Court and praised her as one of the nation\\'s top legal minds.\",\\n \"sources\": [31]\\n}'}\u001b[0m\n",
"\u001b[32;1m\u001b[1;3m\u001b[0m\u001b[36;1m\u001b[1;3mTonight. 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",
"And for our LGBTQ+ Americans, lets finally get the bipartisan Equality Act to my desk. The onslaught of state laws targeting transgender Americans and their families is wrong. \n",
"\n",
"As I said last year, especially to our younger transgender Americans, I will always have your back as your President, so you can be yourself and reach your God-given potential. \n",
"\n",
"While it often appears that we never agree, that isnt true. I signed 80 bipartisan bills into law last year. From preventing government shutdowns to protecting Asian-Americans from still-too-common hate crimes to reforming military justice. \n",
"\n",
"And soon, well strengthen the Violence Against Women Act that I first wrote three decades ago. It is important for us to show the nation that we can come together and do big things. \n",
"\n",
"So tonight Im offering a Unity Agenda for the Nation. Four big things we can do together. \n",
"\n",
"First, beat the opioid epidemic.\n",
"\n",
"Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \n",
"\n",
"Last year COVID-19 kept us apart. This year we are finally together again. \n",
"\n",
"Tonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \n",
"\n",
"With a duty to one another to the American people to the Constitution. \n",
"\n",
"And with an unwavering resolve that freedom will always triumph over tyranny. \n",
"\n",
"Six days ago, Russias Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways. But he badly miscalculated. \n",
"\n",
"He thought he could roll into Ukraine and the world would roll over. Instead he met a wall of strength he never imagined. \n",
"\n",
"He met the Ukrainian people. \n",
"\n",
"From President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.\n",
"\n",
"A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since shes been nominated, shes received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. \n",
"\n",
"And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. \n",
"\n",
"We can do both. At our border, weve installed new technology like cutting-edge scanners to better detect drug smuggling. \n",
"\n",
"Weve set up joint patrols with Mexico and Guatemala to catch more human traffickers. \n",
"\n",
"Were putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. \n",
"\n",
"Were securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders.\u001b[0m\u001b[32;1m\u001b[1;3m{'arguments': '{\\n\"answer\": \"President Biden nominated Ketanji Brown Jackson for the United States Supreme Court and described her as one of our nation\\'s top legal minds who will continue Justice Breyer\\'s legacy of excellence.\",\\n\"sources\": [6]\\n}', 'name': 'Response'}\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
@@ -341,18 +378,18 @@
{
"data": {
"text/plain": [
"{'answer': \"President mentioned Ketanji Brown Jackson as a nominee for the United States Supreme Court and praised her as one of the nation's top legal minds.\",\n",
" 'sources': [31]}"
"{'answer': \"President Biden nominated Ketanji Brown Jackson for the United States Supreme Court and described her as one of our nation's top legal minds who will continue Justice Breyer's legacy of excellence.\",\n",
" 'sources': [6]}"
]
},
"execution_count": 18,
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agent_executor.invoke(\n",
" {\"input\": \"what did the president say about kentaji brown jackson\"},\n",
" {\"input\": \"what did the president say about ketanji brown jackson\"},\n",
" return_only_outputs=True,\n",
")"
]
@@ -368,9 +405,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "poetry-venv",
"language": "python",
"name": "python3"
"name": "poetry-venv"
},
"language_info": {
"codemirror_mode": {
@@ -382,7 +419,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -152,9 +152,7 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.tools.convert_to_openai import format_tool_to_openai_tool\n",
"\n",
"llm_with_tools = llm.bind(tools=[format_tool_to_openai_tool(tool) for tool in tools])"
"llm_with_tools = llm.bind_tools(tools)"
]
},
{
@@ -229,9 +227,9 @@
{
"data": {
"text/plain": [
"[{'actions': [OpenAIToolAgentAction(tool='get_word_length', tool_input={'word': 'eudca'}, log=\"\\nInvoking: `get_word_length` with `{'word': 'eudca'}`\\n\\n\\n\", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_U9SR78eT398r9UbzID2N9LXh', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})], tool_call_id='call_U9SR78eT398r9UbzID2N9LXh')],\n",
" 'messages': [AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_U9SR78eT398r9UbzID2N9LXh', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})]},\n",
" {'steps': [AgentStep(action=OpenAIToolAgentAction(tool='get_word_length', tool_input={'word': 'eudca'}, log=\"\\nInvoking: `get_word_length` with `{'word': 'eudca'}`\\n\\n\\n\", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_U9SR78eT398r9UbzID2N9LXh', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})], tool_call_id='call_U9SR78eT398r9UbzID2N9LXh'), observation=5)],\n",
"[{'actions': [OpenAIToolAgentAction(tool='get_word_length', tool_input={'word': 'eudca'}, log=\"\\nInvoking: `get_word_length` with `{'word': 'eudca'}`\\n\\n\\n\", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_A07D5TuyqcNIL0DIEVRPpZkg', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})], tool_call_id='call_A07D5TuyqcNIL0DIEVRPpZkg')],\n",
" 'messages': [AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_A07D5TuyqcNIL0DIEVRPpZkg', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})]},\n",
" {'steps': [AgentStep(action=OpenAIToolAgentAction(tool='get_word_length', tool_input={'word': 'eudca'}, log=\"\\nInvoking: `get_word_length` with `{'word': 'eudca'}`\\n\\n\\n\", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_A07D5TuyqcNIL0DIEVRPpZkg', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})], tool_call_id='call_A07D5TuyqcNIL0DIEVRPpZkg'), observation=5)],\n",
" 'messages': [FunctionMessage(content='5', name='get_word_length')]},\n",
" {'output': 'There are 5 letters in the word \"eudca\".',\n",
" 'messages': [AIMessage(content='There are 5 letters in the word \"eudca\".')]}]"
@@ -449,7 +447,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.9.1"
},
"vscode": {
"interpreter": {

View File

@@ -12,71 +12,101 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "bb220019-4012-4da4-bfee-01fb8189aa49",
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-community langchain-openai"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "d65d8a60",
"metadata": {},
"outputs": [],
"source": [
"from langchain.schema import HumanMessage\n",
"from langchain_community.tools import MoveFileTool\n",
"from langchain_core.messages import HumanMessage\n",
"from langchain_core.utils.function_calling import convert_to_openai_function\n",
"from langchain_openai import ChatOpenAI"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 20,
"id": "abd8dc72",
"metadata": {},
"outputs": [],
"source": [
"model = ChatOpenAI(model=\"gpt-3.5-turbo-0613\")"
"model = ChatOpenAI(model=\"gpt-3.5-turbo\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "dce2cdb7",
"metadata": {},
"outputs": [],
"source": [
"from langchain.tools import MoveFileTool, format_tool_to_openai_function"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 21,
"id": "3b3dc766",
"metadata": {},
"outputs": [],
"source": [
"tools = [MoveFileTool()]\n",
"functions = [format_tool_to_openai_function(t) for t in tools]"
"functions = [convert_to_openai_function(t) for t in tools]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 12,
"id": "d38c4a22-2e9e-4d15-a9e1-bf8103c6303b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'name': 'move_file',\n",
" 'description': 'Move or rename a file from one location to another',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'source_path': {'description': 'Path of the file to move',\n",
" 'type': 'string'},\n",
" 'destination_path': {'description': 'New path for the moved file',\n",
" 'type': 'string'}},\n",
" 'required': ['source_path', 'destination_path']}}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"functions[0]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "230a7939",
"metadata": {},
"outputs": [],
"source": [
"message = model.predict_messages(\n",
"message = model.invoke(\n",
" [HumanMessage(content=\"move file foo to bar\")], functions=functions\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 16,
"id": "c118c940",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'function_call': {'name': 'move_file', 'arguments': '{\\n \"source_path\": \"foo\",\\n \"destination_path\": \"bar\"\\n}'}}, example=False)"
"AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\\n \"source_path\": \"foo\",\\n \"destination_path\": \"bar\"\\n}', 'name': 'move_file'}})"
]
},
"execution_count": 6,
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
@@ -108,12 +138,64 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "751da79f",
"cell_type": "markdown",
"id": "77dd0d9f-2f24-4535-a658-a061f91e009a",
"metadata": {},
"outputs": [],
"source": []
"source": [
"With OpenAI chat models we can also automatically bind and convert function-like objects with `bind_functions`"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "24bb1518-8100-4ac3-acea-04acfac963d1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\\n \"source_path\": \"foo\",\\n \"destination_path\": \"bar\"\\n}', 'name': 'move_file'}})"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model_with_functions = model.bind_functions(tools)\n",
"model_with_functions.invoke([HumanMessage(content=\"move file foo to bar\")])"
]
},
{
"cell_type": "markdown",
"id": "000ec6ff-ca67-4206-ba56-cc2a91b85ce6",
"metadata": {},
"source": [
"Or we can use the update OpenAI API that uses `tools` and `tool_choice` instead of `functions` and `function_call` by using `ChatOpenAI.bind_tools`:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "1a333e4e-df55-4e15-9d2e-4fd142d969f3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_btkY3xV71cEVAOHnNa5qwo44', 'function': {'arguments': '{\\n \"source_path\": \"foo\",\\n \"destination_path\": \"bar\"\\n}', 'name': 'move_file'}, 'type': 'function'}]})"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model_with_tools = model.bind_tools(tools)\n",
"model_with_tools.invoke([HumanMessage(content=\"move file foo to bar\")])"
]
}
],
"metadata": {

View File

@@ -6,7 +6,7 @@
"metadata": {},
"source": [
"# Logging to file\n",
"This example shows how to print logs to file. It shows how to use the `FileCallbackHandler`, which does the same thing as [`StdOutCallbackHandler`](https://python.langchain.com/en/latest/modules/callbacks/getting_started.html#using-an-existing-handler), but instead writes the output to file. It also uses the `loguru` library to log other outputs that are not captured by the handler."
"This example shows how to print logs to file. It shows how to use the `FileCallbackHandler`, which does the same thing as [`StdOutCallbackHandler`](https://python.langchain.com/docs/modules/callbacks/#get-started), but instead writes the output to file. It also uses the `loguru` library to log other outputs that are not captured by the handler."
]
},
{
@@ -166,7 +166,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
"version": "3.11.6"
}
},
"nbformat": 4,

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`, `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

@@ -0,0 +1,492 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "dae8d4ed-9150-45da-b494-7717ab0a2960",
"metadata": {},
"source": [
"# Function calling\n",
"\n",
"Certain chat models, like [OpenAI's](https://platform.openai.com/docs/guides/function-calling), have a function-calling API that lets you describe functions and their arguments, and have the model return a JSON object with a function to invoke and the inputs to that function. Function-calling is extremely useful for building [tool-using chains and agents](/docs/use_cases/tool_use/), and for getting structured outputs from models more generally.\n",
"\n",
"LangChain comes with a number of utilities to make function-calling easy. Namely, it comes with\n",
"\n",
"* simple syntax for binding functions to models\n",
"* converters for formatting various types of objects to the expected function schemas\n",
"* output parsers for extracting the function invocations from API responses\n",
"\n",
"We'll focus here on the first two bullets. To see how output parsing works as well check out the [OpenAI Tools output parsers](/docs/modules/model_io/output_parsers/types/openai_tools)."
]
},
{
"cell_type": "markdown",
"id": "a177c64b-7c99-495c-b362-5ed3b40aa26a",
"metadata": {},
"source": [
"## Defining functions\n",
"\n",
"We'll focus on the [OpenAI function format](https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools) here since as of this writing that is the main model provider that supports function calling. LangChain has a built-in converter that can turn Python functions, Pydantic classes, and LangChain Tools into the OpenAI function format:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "f6d1dc0c-6170-4977-809f-365099f628ea",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;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 -qU langchain-core langchain-openai"
]
},
{
"cell_type": "markdown",
"id": "6bd290bd-7621-466b-a73e-fc8480f879ec",
"metadata": {},
"source": [
"### Python function"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "41ebab5c-0e9f-4b49-86ee-9290ced2fe96",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"multiply\",\n",
" \"description\": \"Multiply two integers together.\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"a\": {\n",
" \"type\": \"integer\",\n",
" \"description\": \"First integer\"\n",
" },\n",
" \"b\": {\n",
" \"type\": \"integer\",\n",
" \"description\": \"Second integer\"\n",
" }\n",
" },\n",
" \"required\": [\n",
" \"a\",\n",
" \"b\"\n",
" ]\n",
" }\n",
" }\n",
"}\n"
]
}
],
"source": [
"import json\n",
"\n",
"from langchain_core.utils.function_calling import convert_to_openai_tool\n",
"\n",
"\n",
"def multiply(a: int, b: int) -> int:\n",
" \"\"\"Multiply two integers together.\n",
"\n",
" Args:\n",
" a: First integer\n",
" b: Second integer\n",
" \"\"\"\n",
" return a * b\n",
"\n",
"\n",
"print(json.dumps(convert_to_openai_tool(multiply), indent=2))"
]
},
{
"cell_type": "markdown",
"id": "ecf22577-38ab-48f1-ba0b-371aaba1bacc",
"metadata": {},
"source": [
"### Pydantic class"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ecc8ffd4-aed3-4f47-892d-1896cc1ca4dc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"multiply\",\n",
" \"description\": \"Multiply two integers together.\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"a\": {\n",
" \"description\": \"First integer\",\n",
" \"type\": \"integer\"\n",
" },\n",
" \"b\": {\n",
" \"description\": \"Second integer\",\n",
" \"type\": \"integer\"\n",
" }\n",
" },\n",
" \"required\": [\n",
" \"a\",\n",
" \"b\"\n",
" ]\n",
" }\n",
" }\n",
"}\n"
]
}
],
"source": [
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
"\n",
"\n",
"class multiply(BaseModel):\n",
" \"\"\"Multiply two integers together.\"\"\"\n",
"\n",
" a: int = Field(..., description=\"First integer\")\n",
" b: int = Field(..., description=\"Second integer\")\n",
"\n",
"\n",
"print(json.dumps(convert_to_openai_tool(multiply), indent=2))"
]
},
{
"cell_type": "markdown",
"id": "b83d5a88-50ed-4ae4-85cf-8b895617496f",
"metadata": {},
"source": [
"### LangChain Tool"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "696c7dd6-660c-4797-909f-bf878b3acf93",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"multiply\",\n",
" \"description\": \"Multiply two integers together.\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"a\": {\n",
" \"description\": \"First integer\",\n",
" \"type\": \"integer\"\n",
" },\n",
" \"b\": {\n",
" \"description\": \"Second integer\",\n",
" \"type\": \"integer\"\n",
" }\n",
" },\n",
" \"required\": [\n",
" \"a\",\n",
" \"b\"\n",
" ]\n",
" }\n",
" }\n",
"}\n"
]
}
],
"source": [
"from typing import Any, Type\n",
"\n",
"from langchain_core.tools import BaseTool\n",
"\n",
"\n",
"class MultiplySchema(BaseModel):\n",
" \"\"\"Multiply tool schema.\"\"\"\n",
"\n",
" a: int = Field(..., description=\"First integer\")\n",
" b: int = Field(..., description=\"Second integer\")\n",
"\n",
"\n",
"class Multiply(BaseTool):\n",
" args_schema: Type[BaseModel] = MultiplySchema\n",
" name: str = \"multiply\"\n",
" description: str = \"Multiply two integers together.\"\n",
"\n",
" def _run(self, a: int, b: int, **kwargs: Any) -> Any:\n",
" return a * b\n",
"\n",
"\n",
"# Note: we're passing in a Multiply object not the class itself.\n",
"print(json.dumps(convert_to_openai_tool(Multiply()), indent=2))"
]
},
{
"cell_type": "markdown",
"id": "04bda177-202f-4811-bb74-f3fa7094a15b",
"metadata": {},
"source": [
"## Binding functions\n",
"\n",
"Now that we've defined a function, we'll want to pass it in to our model."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "a5aa93a7-6859-43e8-be85-619d975b908c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_JvOu9oUwMrQHiDekZTbpNCHY', 'function': {'arguments': '{\\n \"a\": 5,\\n \"b\": 3\\n}', 'name': 'multiply'}, 'type': 'function'}]})"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_openai import ChatOpenAI\n",
"\n",
"llm = ChatOpenAI(model=\"gpt-3.5-turbo\")\n",
"llm.invoke(\"what's 5 times three\", tools=[convert_to_openai_tool(multiply)])"
]
},
{
"cell_type": "markdown",
"id": "dd0e7365-32d0-46a3-b8f2-caf27d5d9262",
"metadata": {},
"source": [
"And if we wanted this function to be passed in every time we call the tool, we could bind it to the tool:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "87165d64-31a7-4332-965e-18fa939fda50",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_cwRoTnD1ux1SnWXLrTj2KlWH', 'function': {'arguments': '{\\n \"a\": 5,\\n \"b\": 3\\n}', 'name': 'multiply'}, 'type': 'function'}]})"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_with_tool = llm.bind(tools=[convert_to_openai_tool(multiply)])\n",
"llm_with_tool.invoke(\"what's 5 times three\")"
]
},
{
"cell_type": "markdown",
"id": "21b4d000-3828-4e32-9226-55119f47ee67",
"metadata": {},
"source": [
"We can also enforce that a tool is called using the [tool_choice](https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools) parameter."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2daa354c-cc85-4a60-a9b2-b681ec22ca33",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_sWjLyioSZAtYMQRLMTzncz1v', 'function': {'arguments': '{\\n \"a\": 5,\\n \"b\": 4\\n}', 'name': 'multiply'}, 'type': 'function'}]})"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_with_tool = llm.bind(\n",
" tools=[convert_to_openai_tool(multiply)],\n",
" tool_choice={\"type\": \"function\", \"function\": {\"name\": \"multiply\"}},\n",
")\n",
"llm_with_tool.invoke(\n",
" \"don't answer my question. no do answer my question. no don't. what's five times four\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "ce013d11-49ea-4de9-8bbc-bc9ae203002c",
"metadata": {},
"source": [
"The [ChatOpenAI](https://api.python.langchain.com/en/latest/chat_models/langchain_openai.chat_models.base.ChatOpenAI.html#langchain_openai.chat_models.base.ChatOpenAI) class even comes with a `bind_tools` helper function that handles converting function-like objects to the OpenAI format and binding them for you:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "842c9914-ac28-428f-9fcc-556177e8e715",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_LCdBa4cbhMJPRdtkhDzpRh7x', 'function': {'arguments': '{\\n \"a\": 5,\\n \"b\": 3\\n}', 'name': 'multiply'}, 'type': 'function'}]})"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_with_tool = llm.bind_tools([multiply], tool_choice=\"multiply\")\n",
"llm_with_tool.invoke(\"what's 5 times three\")"
]
},
{
"cell_type": "markdown",
"id": "7d6e22d8-9f33-4845-9364-0d276df35ff5",
"metadata": {},
"source": [
"## Legacy args `functions` and `function_call`\n",
"\n",
"Until Fall of 2023 the OpenAI API expected arguments `functions` and `funtion_call` instead of `tools` and `tool_choice`, and they had a slightly different format than `tools` and `tool_choice`. LangChain maintains utilities for using the old API if you need to use that as well:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "a317f71e-177e-404b-b09c-8fb365a4d8a2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'name': 'multiply',\n",
" 'description': 'Multiply two integers together.',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'a': {'description': 'First integer', 'type': 'integer'},\n",
" 'b': {'description': 'Second integer', 'type': 'integer'}},\n",
" 'required': ['a', 'b']}}"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.utils.function_calling import convert_to_openai_function\n",
"\n",
"convert_to_openai_function(multiply)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "dd124259-75e2-4704-9f57-824d3e463bfa",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\\n \"a\": 3,\\n \"b\": 1000000\\n}', 'name': 'multiply'}})"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_with_functions = llm.bind(\n",
" functions=[convert_to_openai_function(multiply)], function_call={\"name\": \"multiply\"}\n",
")\n",
"llm_with_functions.invoke(\"what's 3 times a million\")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "d9a90af9-1c81-4ace-b155-1589f7308a1c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\\n \"a\": 3,\\n \"b\": 1000000\\n}', 'name': 'multiply'}})"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm_with_functions = llm.bind_functions([multiply], function_call=\"multiply\")\n",
"llm_with_functions.invoke(\"what's 3 times a million\")"
]
},
{
"cell_type": "markdown",
"id": "7779808d-d75c-4d76-890d-ba8c6c571514",
"metadata": {},
"source": [
"## Next steps\n",
"\n",
"* **Output parsing**: See [OpenAI Tools output parsers](/docs/modules/model_io/output_parsers/types/openai_tools) and [OpenAI Functions output parsers](/docs/modules/model_io/output_parsers/types/openai_functions) to learn about extracting the function calling API responses into various formats.\n",
"* **Tool use**: See how to construct chains and agents that actually call the invoked tools in [these guides](/docs/use_cases/tool_use/)."
]
}
],
"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

@@ -24,5 +24,6 @@ We have several how-to guides for more advanced usage of LLMs.
This includes:
- [How to cache ChatModel responses](./chat_model_caching)
- [How to use ChatModels that support function calling](./function_calling)
- [How to stream responses from a ChatModel](./streaming)
- [How to track token usage in a ChatModel call](./token_usage_tracking)

View File

@@ -32,7 +32,8 @@ LangChain has lots of different types of output parsers. This is a list of outpu
| Name | Supports Streaming | Has Format Instructions | Calls LLM | Input Type | Output Type | Description |
|-----------------|--------------------|-------------------------------|-----------|----------------------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [OpenAIFunctions](./types/openai_functions) | | (Passes `functions` to model) | | `Message` (with `function_call`) | JSON object | Uses OpenAI function calling to structure the return output. If you are using a model that supports function calling, this is generally the most reliable method. |
| [OpenAITools](./types/openai_tools) | | (Passes `tools` to model) | | `Message` (with `tool_choice`) | JSON object | Uses latest OpenAI function calling args `tools` and `tool_choice` to structure the return output. If you are using a model that supports function calling, this is generally the most reliable method. |
| [OpenAIFunctions](./types/openai_functions) | ✅ | (Passes `functions` to model) | | `Message` (with `function_call`) | JSON object | Uses legacy OpenAI function calling args `functions` and `function_call` to structure the return output. |
| [JSON](./types/json) | ✅ | ✅ | | `str \| Message` | JSON object | Returns a JSON object as specified. You can specify a Pydantic model and it will return JSON for that model. Probably the most reliable output parser for getting structured data that does NOT use function calling. |
| [XML](./types/xml) | ✅ | ✅ | | `str \| Message` | `dict` | Returns a dictionary of tags. Use when XML output is needed. Use with models that are good at writing XML (like Anthropic's). |
| [CSV](./types/csv) | ✅ | ✅ | | `str \| Message` | `List[str]` | Returns a list of comma separated values. |

View File

@@ -0,0 +1,385 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "bcbe5c87",
"metadata": {},
"source": [
"# OpenAI Tools\n",
"\n",
"These output parsers extract tool calls from OpenAI's function calling API responses. This means they are only usable with models that support function calling, and specifically the latest `tools` and `tool_choice` parameters. We recommend familiarizing yourself with [function calling](/docs/modules/model_io/chat/function_calling) before reading this guide.\n",
"\n",
"There are a few different variants of output parsers:\n",
"\n",
"- [JsonOutputToolsParser](https://api.python.langchain.com/en/latest/output_parsers/langchain.output_parsers.openai_tools.JsonOutputToolsParser.html#langchain.output_parsers.openai_tools.JsonOutputToolsParser): Returns the arguments of the function call as JSON\n",
"- [JsonOutputKeyToolsParser](https://api.python.langchain.com/en/latest/output_parsers/langchain.output_parsers.openai_tools.JsonOutputKeyToolsParser.html#langchain.output_parsers.openai_tools.JsonOutputKeyToolsParser): Returns the value of specific key in the function call as JSON\n",
"- [PydanticToolsParser](https://api.python.langchain.com/en/latest/output_parsers/langchain.output_parsers.openai_tools.PydanticToolsParser.html#langchain.output_parsers.openai_tools.PydanticToolsParser): Returns the arguments of the function call as a Pydantic Model"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "aac4262b",
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.prompts import ChatPromptTemplate\n",
"from langchain_core.pydantic_v1 import BaseModel, Field, validator\n",
"from langchain_openai import ChatOpenAI"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "52cb351d",
"metadata": {},
"outputs": [],
"source": [
"class Joke(BaseModel):\n",
" \"\"\"Joke to tell user.\"\"\"\n",
"\n",
" setup: str = Field(description=\"question to set up a joke\")\n",
" punchline: str = Field(description=\"answer to resolve the joke\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2c3259c4",
"metadata": {},
"outputs": [],
"source": [
"model = ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0).bind_tools([Joke])"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "75c33a76-ead8-43aa-ba18-c1822c38cfa9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'type': 'function',\n",
" 'function': {'name': 'Joke',\n",
" 'description': 'Joke to tell user.',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'setup': {'description': 'question to set up a joke',\n",
" 'type': 'string'},\n",
" 'punchline': {'description': 'answer to resolve the joke',\n",
" 'type': 'string'}},\n",
" 'required': ['setup', 'punchline']}}}]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.kwargs[\"tools\"]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d3e9007c",
"metadata": {},
"outputs": [],
"source": [
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", \"You are helpful assistant\"), (\"user\", \"{input}\")]\n",
")"
]
},
{
"cell_type": "markdown",
"id": "87680951",
"metadata": {},
"source": [
"## JsonOutputToolsParser"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "cb065bdd",
"metadata": {},
"outputs": [],
"source": [
"from langchain.output_parsers.openai_tools import JsonOutputToolsParser"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "6ff758c8",
"metadata": {},
"outputs": [],
"source": [
"parser = JsonOutputToolsParser()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "27a3acd1",
"metadata": {},
"outputs": [],
"source": [
"chain = prompt | model | parser"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "59b59179",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'type': 'Joke',\n",
" 'args': {'setup': \"Why don't scientists trust atoms?\",\n",
" 'punchline': 'Because they make up everything!'}}]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"input\": \"tell me a joke\"})"
]
},
{
"cell_type": "markdown",
"id": "0f093b2b-ffd1-47b7-9221-b4265ae52701",
"metadata": {},
"source": [
"To include the tool call id we can specify `return_id=True`:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d43fd620-dcdc-4ad0-a3a9-e7d2d71d6e68",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'type': 'Joke',\n",
" 'args': {'setup': \"Why don't scientists trust atoms?\",\n",
" 'punchline': 'Because they make up everything!'},\n",
" 'id': 'call_Isuoh0RTeQzzOKGg5QlQ7UqI'}]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parser = JsonOutputToolsParser(return_id=True)\n",
"chain = prompt | model | parser\n",
"chain.invoke({\"input\": \"tell me a joke\"})"
]
},
{
"cell_type": "markdown",
"id": "7ca55ac9",
"metadata": {},
"source": [
"## JsonOutputKeyToolsParser\n",
"\n",
"This merely extracts a single key from the returned response. This is useful for when you are passing in a single tool and just want it's arguments."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "f8bc404e",
"metadata": {},
"outputs": [],
"source": [
"from typing import List\n",
"\n",
"from langchain.output_parsers.openai_tools import JsonOutputKeyToolsParser"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "c91c5949",
"metadata": {},
"outputs": [],
"source": [
"parser = JsonOutputKeyToolsParser(key_name=\"Joke\")"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "b4583baf",
"metadata": {},
"outputs": [],
"source": [
"chain = prompt | model | parser"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "e8b766ff",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'setup': \"Why don't scientists trust atoms?\",\n",
" 'punchline': 'Because they make up everything!'}]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"input\": \"tell me a joke\"})"
]
},
{
"cell_type": "markdown",
"id": "fc5695c5-451f-482f-bde6-462d85f1a93e",
"metadata": {},
"source": [
"Certain models can return multiple tool invocations each call, so by default the output is a list. If we just want to return the first tool invocation, we can specify `return_single=True`"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "b1f3097a-5040-435e-9e26-bbdf9506aead",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'setup': \"Why don't scientists trust atoms?\",\n",
" 'punchline': 'Because they make up everything!'}"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parser = JsonOutputKeyToolsParser(key_name=\"Joke\", return_single=True)\n",
"chain = prompt | model | parser\n",
"chain.invoke({\"input\": \"tell me a joke\"})"
]
},
{
"cell_type": "markdown",
"id": "941a3d4e",
"metadata": {},
"source": [
"## PydanticToolsParser\n",
"\n",
"This builds on top of `JsonOutputToolsParser` but passes the results to a Pydantic Model. This allows for further validation should you choose."
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "f51823fe",
"metadata": {},
"outputs": [],
"source": [
"from langchain.output_parsers.openai_tools import PydanticToolsParser"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "3c6a5e4d",
"metadata": {},
"outputs": [],
"source": [
"class Joke(BaseModel):\n",
" \"\"\"Joke to tell user.\"\"\"\n",
"\n",
" setup: str = Field(description=\"question to set up a joke\")\n",
" punchline: str = Field(description=\"answer to resolve the joke\")\n",
"\n",
" # You can add custom validation logic easily with Pydantic.\n",
" @validator(\"setup\")\n",
" def question_ends_with_question_mark(cls, field):\n",
" if field[-1] != \"?\":\n",
" raise ValueError(\"Badly formed question!\")\n",
" return field\n",
"\n",
"\n",
"parser = PydanticToolsParser(tools=[Joke])"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "d2bbd54f",
"metadata": {},
"outputs": [],
"source": [
"model = ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0).bind_tools([Joke])\n",
"chain = prompt | model | parser"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "db1a06e8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Joke(setup=\"Why don't scientists trust atoms?\", punchline='Because they make up everything!')]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"input\": \"tell me a joke\"})"
]
}
],
"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

@@ -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

@@ -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/use_cases/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
}

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