Compare commits

..

349 Commits

Author SHA1 Message Date
Lance Martin
04fa5bd65f Merge branch 'master' into rlm/sql-pgvector-template 2023-11-13 15:31:16 -08:00
Lance Martin
e549397001 fmt 2023-11-13 15:30:48 -08:00
wemysschen
a591cdb67d add cookbook for RAG with baidu QIANFAN and elasticsearch (#13287)
**Description:** 
Add cookbook for RAG with baidu QIANFAN and elasticsearch.

Co-authored-by: wemysschen <root@icoding-cwx.bcc-szzj.baidu.com>
2023-11-13 14:45:24 -08:00
mertkayhan
9b4974871d IMPROVEMENT Increase flexibility of ElasticVectorSearch (#6863)
Hey @rlancemartin, @eyurtsev ,

I did some minimal changes to the `ElasticVectorSearch` client so that
it plays better with existing ES indices.

Main changes are as follows:

1. You can pass the dense vector field name into `_default_script_query`
2. You can pass a custom script query implementation and the respective
parameters to `similarity_search_with_score`
3. You can pass functions for building page content and metadata for the
resulting `Document`

<!-- Thank you for contributing to LangChain!

Replace this comment with:
  - Description: a description of the change, 
  - Issue: the issue # it fixes (if applicable),
  - Dependencies: any dependencies required for this change,
- Tag maintainer: for a quicker response, tag the relevant maintainer
(see below),
- 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!

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,
  4. an example notebook showing its use.

Maintainer responsibilities:
  - General / Misc / if you don't know who to tag: @dev2049
  - DataLoaders / VectorStores / Retrievers: @rlancemartin, @eyurtsev
  - Models / Prompts: @hwchase17, @dev2049
  - Memory: @hwchase17
  - Agents / Tools / Toolkits: @vowelparrot
  - Tracing / Callbacks: @agola11
  - Async: @agola11

If no one reviews your PR within a few days, feel free to @-mention the
same people again.

See contribution guidelines for more information on how to write/run
tests, lint, etc:
https://github.com/hwchase17/langchain/blob/master/.github/CONTRIBUTING.md
 -->
2023-11-13 14:36:03 -08:00
Lance Martin
39852dffd2 Cookbook for multi-modal RAG eval (#13272) 2023-11-13 14:26:02 -08:00
Erick Friis
50a5c919f0 IMPROVEMENT self-query template (#13305)
- [ ]
https://github.com/langchain-ai/langchain/pull/12694#discussion_r1391334719
-> keep date
- [x]
https://github.com/langchain-ai/langchain/pull/12694#discussion_r1391336586
2023-11-13 14:03:15 -08:00
Lance Martin
0686096728 fmt 2023-11-13 13:47:05 -08:00
Lance Martin
adfe14001a fmt 2023-11-13 13:28:09 -08:00
Yasin
b46f88d364 IMPROVEMENT add license file to subproject (#8403)
<!-- Thank you for contributing to LangChain!

Replace this comment with:
  - Description: a description of the change, 
  - Issue: the issue # it fixes (if applicable),
  - Dependencies: any dependencies required for this change,
- Tag maintainer: for a quicker response, tag the relevant maintainer
(see below),
- 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 you're PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` to check this
locally.

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.

Maintainer responsibilities:
  - General / Misc / if you don't know who to tag: @baskaryan
  - DataLoaders / VectorStores / Retrievers: @rlancemartin, @eyurtsev
  - Models / Prompts: @hwchase17, @baskaryan
  - Memory: @hwchase17
  - Agents / Tools / Toolkits: @hinthornw
  - Tracing / Callbacks: @agola11
  - Async: @agola11

If no one reviews your PR within a few days, feel free to @-mention the
same people again.

See contribution guidelines for more information on how to write/run
tests, lint, etc:
https://github.com/hwchase17/langchain/blob/master/.github/CONTRIBUTING.md
 -->

hi!
This is pretty straight-forward: The sdist package does not contain the
license file (which is needed by e.g. conda) because the package is
built from the subdir and can't see the license.
I _copied_ the license but since I'm unfamiliar with the projects
direction, I'm not sure that's correct.
thanks!

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-13 11:48:21 -08:00
Rui Ramos
ff19a62afc Fix Pinecone cosine relevance score (#8920)
Fixes: #8207

Description:
Pinecone returns scores (not distances) with cosine similarity. The
values according to the docs are [-1, 1], although I could never
reproduce negative values.

This PR ensures that the score returned from Pinecone is preserved,
rather than inverted, so the most relevant documents can be filtered (eg
when using similarity thresholds)

I'll leave this as a draft PR as I couldn't run the tests (my pinecone
account might not be enough - some errors were being thrown around
namespaces) so hopefully someone who _can_ will pick this up.

Maintainers:
@rlancemartin, @eyurtsev

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-13 11:47:38 -08:00
Bagatur
2e42ed5de6 Self-query template (#12694)
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-13 11:44:19 -08:00
Konstantin Spieß
1e43025bf5 Fix serialization issue in Matching Engine Vector Store (#13266)
- **Description:** Fixed a serialization issue in the add_texts method
of the Matching Engine Vector Store caused by a typo, leading to an
attempt to serialize the json module itself.
  - **Issue:** #12154 
  - **Dependencies:** ./.
  - **Tag maintainer:**
2023-11-13 11:04:11 -08:00
William FH
9169d77cf6 Update error message in evaluation runner (#13296) 2023-11-13 11:03:20 -08:00
Leonie
32c493e3df Refine Weaviate docs and add RAG example (#13057)
- **Description:** Refine Weaviate tutorial and add an example for
Retrieval-Augmented Generation (RAG)
  - **Issue:** (not applicable),
  - **Dependencies:** none
  - **Tag maintainer:** @baskaryan <!--
If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
  - **Twitter handle:** @helloiamleonie

Co-authored-by: Leonie <leonie@Leonies-MBP-2.fritz.box>
2023-11-13 10:59:19 -08:00
takatost
f22f273f93 FIX: 'from_texts' method in Weaviate with non-existent kwargs param (#11604)
Due to the possibility of external inputs including UUIDs, there may be
additional values in **kwargs, while Weaviate's `__init__` method does
not support passing extra **kwarg parameters.

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-13 10:32:20 -08:00
Frank995
971d2b2e34 Add missing filter to max_marginal_relevance_search inner call to max_marginal_relevance_search_by_vector (#13260)
When calling max_marginal_relevance_search from PGVector the filter
param is not carried over to max_marginal_relevance_search_by_vector

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-13 10:31:34 -08:00
chevalmuscle
3ad78e48e2 Use endpoint_url if provided with boto3 session for dynamodb (#11622)
- **Description:** Uses `endpoint_url` if provided with a boto3 session.
When running dynamodb locally, credentials are required even if invalid.
With this change, it will be possible to pass a boto3 session with
credentials and specify an endpoint_url

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-13 10:31:16 -08:00
Erick Friis
18acc22f29 Ollama pass kwargs as options instead of top (#13280)
Noticed params are really in `options` instead while reviewing #12895
2023-11-13 10:28:47 -08:00
刘 方瑞
46af56dc4f Add MyScaleWithoutJSON which allows user to wrap columns into Document's Metadata (#13164)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
Replace this entire comment with:
- **Description:** Add MyScaleWithoutJSON which allows user to wrap
columns into Document's Metadata
  - **Tag maintainer:** @baskaryan
2023-11-13 10:10:36 -08:00
Michael Landis
2aa13f1e10 chore: bump momento dependency version and refactor search hit usage (#13111)
**Description**

Bumps the Momento dependency to the latest version and refactors the
usage of `SearchHit` in the Momento Vector Index (MVI) vector store
integration. This change is a one liner where we use the preferred
attribute `score` to read the query-document similarity instead of
`distance`. The latest versions of Momento clients will use this
attribute going forward.

**Dependencies**

Updated the Momento dependency to latest version.

**Tests**

💚 I re-ran the existing MVI integration tests
(`tests/integration_tests/vectorstores/test_momento_vector_index.py`)
and they pass.

**Review**
cc @baskaryan @eyurtsev
2023-11-13 09:12:21 -08:00
Junlin Zhou
4da2faba41 docs: align custom_tool document headers (#13252)
On the [Defining Custom
Tools](https://python.langchain.com/docs/modules/agents/tools/custom_tools)
page, there's a 'Subclassing the BaseTool class' paragraph under the
'Completely New Tools - String Input and Output' header. Also there's
another 'Subclassing the BaseTool' paragraph under no header, which I
think may belong to the 'Custom Structured Tools' header.

Another thing is, there's a 'Using the tool decorator' and a 'Using the
decorator' paragraph, I think should belong to 'Completely New Tools -
String Input and Output' and 'Custom Structured Tools' separately.

This PR moves those paragraphs to corresponding headers.
2023-11-13 09:03:56 -08:00
Ikko Eltociear Ashimine
700293cae9 Fix typo in timescalevector.ipynb (#13239)
enviornment -> environment
2023-11-13 09:03:07 -08:00
kYLe
cc55d2fcee Add OpenAI API v1 support for ChatAnyscale and fixed a bug with openai_api_key (#13237)
1. Add OpenAI API v1 support
2. Fixed a bug to call `get_secret_value` on a str value
(values["openai_api_key"])
2023-11-13 09:01:54 -08:00
juan-calvo-datatonic
545b76b0fd Add rag google vertex ai search template (#13294)
- **Description:** This is a template demonstrating how to utilize
Google Vertex AI Search in conjunction with ChatVertexAI()
2023-11-13 08:45:36 -08:00
Govind.S.B
9024593468 added system prompt and template fields to ollama (#13022)
**Description**
the ollama api now supports passing system prompt and template directly
instead of modifying the model file , but the ollama integration in
langchain did not have this change updated . The update just adds these
two parameters to it ( there are 2 more parameters that are pending to
be updated, I was not sure about their utility wrt to langchain )
Refer :
8713ac23a8

**Issue** : None Applicable

**Dependencies** : None Changed

**Twitter handle** : https://twitter.com/violetto96

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-11-13 08:45:11 -08:00
langchain-infra
f55f67055f Add dockerfile template (#13240) 2023-11-13 10:33:01 -05:00
Shaurya Rohatgi
f70aa82c84 Update README.md - Added notebook for extraction_openai_tools (#13205)
added Parallel Function Calling for Structured Data Extraction notebook

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

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

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-13 00:12:46 -08:00
Guillem Orellana Trullols
0f31cd8b49 Remove _get_kwarg_value function (#13184)
`_get_kwarg_value` function is useless, one can rely on python builtin
functionalities to do the exact same thing.

- **Description:** Removed `_get_kwarg_value`. Helps with code
readability.
  - **Issue:** the issue # it fixes (if applicable),
  - **Twitter handle:** @Guillem_96
2023-11-13 00:09:54 -08:00
SuperDa Fu
e1c020dfe1 dalle add model parameter (#13201)
- **Description:** dalle_image_generator adding a new model parameter,
  - **Issue:** N/A,
  - **Dependencies:** 
  - **Tag maintainer: @hwchase17
  - **Twitter handle:**

---------

Co-authored-by: dafu <xiangbingze@wenru.wang>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Erick Friis <erickfriis@gmail.com>
2023-11-13 00:09:20 -08:00
Mario Angst
96b56a4d4f Typo fix to quickstart.mdx (#13178)
- **Description:** I fixed a very small typo in the quickstart docs
(BaeMessage -> BaseMessage)
2023-11-13 00:02:18 -08:00
Dennis de Greef
64e11592bb Improve CSV reader which can't call .strip() on NoneType (#13079)
Improve CSV reader which can't call .strip() on NoneType if there are
less cells in the row compared to the header

<!-- Thank you for contributing to LangChain!

Replace this entire comment with:
  - **Description:** 
I have a CSV file as followed

```
headerA,headerB,headerC
v1A,v1B,v1C,
v2A,v2B
v3A,v3B,v3C
```
In this case, row 2 is missing a value, which results in reading a None
type. The strip() method can not be called on None, hence raising. In
this PR I am making the change to only call strip if the value if not
None.

  - **Issue:** the issue # it fixes (if applicable),
  - **Dependencies:** any dependencies required for this change,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-12 23:51:39 -08:00
glad4enkonm
339973db47 Update ollama.py (#12895)
duplicate option removed
**Description:**  An issue fix, http stop option duplicate removed.
**Issue:** the issue #12892 fix
**Dependencies:** no
**Tag maintainer:** @eyurtsev

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-12 23:43:59 -08:00
刘 方瑞
e89e830c55 Free knowledge base pod information update (#12813)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

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

We updated MyScale free knowledge base, where you can try your RAG with
36 million paragraphs from wikipedia and 2 million paragraphs from
ArXiv.

The pod has two tables
```sql
CREATE TABLE default.ChatArXiv (
    `abstract` String, 
    `id` String, 
    `vector` Array(Float32), 
    `metadata` Object('JSON'), 
    `pubdate` DateTime,
    `title` String,
    `categories` Array(String),
    `authors` Array(String), 
    `comment` String,
    `primary_category` String,
    VECTOR INDEX vec_idx vector TYPE MSTG('metric_type=Cosine'), 
    CONSTRAINT vec_len CHECK length(vector) = 768) 
ENGINE = ReplacingMergeTree ORDER BY id;

CREATE TABLE wiki.Wikipedia (
    `id` String, 
    `title` String, 
    `text` String,
    `url` String,
    `wiki_id` UInt64,
    `views` Float32,
    `paragraph_id` UInt64,
    `langs` UInt32, 
    `emb` Array(Float32), 
    VECTOR INDEX emb_idx emb TYPE MSTG('metric_type=Cosine'), 
    CONSTRAINT emb_len CHECK length(emb) = 768) 
ENGINE = ReplacingMergeTree ORDER BY id;
```

You can connect those two tables using credentials below (just the same
to the old one)
URL: `msc-4a9e710a.us-east-1.aws.staging.myscale.cloud`
Port: `443`
Username: `chatdata`
Password: `myscale_rocks`

It's FREE and you can also use it with 
ChatData: https://github.com/myscale/ChatData
Retrieval-QA-Benchmark:
https://github.com/myscale/Retrieval-QA-Benchmark
... and also LangChain!

Request for review @baskaryan
2023-11-12 23:22:42 -08:00
Luis Valencia
c40973814d Update README.md (#8570)
- Description: updated readme.
  - Tag maintainer: @baskaryan
  - Twitter handle: @Levalencia

---------

Co-authored-by: Bagatur <22008038+baskaryan@users.noreply.github.com>
2023-11-12 22:07:49 -08:00
Manuel Soria
f7f6aebc8d add code to generate embeddings 2023-11-12 18:41:41 -03:00
Manuel Soria
362e1c5233 x 2023-11-12 18:27:46 -03:00
Manuel Soria
e65b73157e adapting readme file 2023-11-12 18:27:36 -03:00
Manuel Soria
ee7c68e8b9 seprating prompts as they are too long 2023-11-12 18:15:42 -03:00
Manuel Soria
597a8c084d replacing chain 2023-11-12 17:54:19 -03:00
Manuel Soria
97d4e028f4 creating template folder 2023-11-12 17:43:41 -03:00
Isak Nyberg
8f81703d76 Add new models to openai callback (#13244)
**Description:** Adding the new models to the openai callback function,
info taken from [model
announcement](https://platform.openai.com/docs/models) and
[pricing](https://openai.com/pricing)

A short description for a short PR :)
2023-11-12 12:01:19 -08:00
Bagatur
ea6dd3a550 bump 335 (#13261) 2023-11-12 11:30:25 -08:00
William FH
a837b03e55 Update langsmith version 0.63 (#13208) 2023-11-12 11:29:25 -08:00
Harrison Chase
7f1d26160d update tools (#13243) 2023-11-12 10:22:54 -08:00
Nuno Campos
8d6faf5665 Make it easier to subclass runnable binding with custom init args (#13189) 2023-11-11 09:01:17 +00:00
Peter Vandenabeele
7f1964b264 Fix BeautifulSoupTransformer: no more duplicates and correct order of tags + tests (#12596) 2023-11-11 08:56:37 +00:00
Bagatur
937d7c41f3 update stack diagram (#13213) 2023-11-10 16:50:20 -08:00
Erick Friis
9c7afa8adb Upgrade cohere embedding model to v3 (#13219)
Just updates API docs, doesn't change default param from 2.0 (could be
breaking change)
2023-11-10 16:25:58 -08:00
Matvey Arye
180657ca7a Add template for conversational rag with timescale vector (#13041)
**Description:** This is like the rag-conversation template in many
ways. What's different is:
- support for a timescale vector store.
- support for time-based filters.
- support for metadata filters.

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

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

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-10 16:12:32 -08:00
Andrew Zhou
1a1a1a883f fleet_context docs update (#13221)
- **Description:** Changed the fleet_context documentation to use
`context.download_embeddings()` from the latest release from our
package. More details here:
https://github.com/fleet-ai/context/tree/main#api
  - **Issue:** n/a
  - **Dependencies:** n/a
  - **Tag maintainer:** @baskaryan 
  - **Twitter handle:** @andrewthezhou
2023-11-10 14:53:57 -08:00
Erick Friis
8fdf15c023 Fix Document Loader Unit Test - Docusaurus (#13228) 2023-11-10 14:52:01 -08:00
Lee
72ad448daa feat: Docusaurus Loader (#9138)
Added a Docusaurus Loader

Issue: #6353

I had to implement this for working with the Ionic documentation, and
wanted to open this up as a draft to get some guidance on building this
out further. I wasn't sure if having it be a light extension of the
SitemapLoader was in the spirit of a proper feature for the library --
but I'm grateful for the opportunities Langchain has given me and I'd
love to build this out properly for the sake of the community.

Any feedback welcome!
2023-11-10 14:21:55 -08:00
VAS
8fa960641a Update Documentation: Corrected Typos and Improved Clarity (#11725)
Docs updates

---------

Co-authored-by: Advaya <126754021+bluevayes@users.noreply.github.com>
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-10 14:14:44 -08:00
Leonid Ganeline
e165daa0ae new course on DeepLearning.ai (#12755)
Added a new course on
[DeepLearning.ai](https://learn.deeplearning.ai/functions-tools-agents-langchain)
Added the LangChain `Wikipedia` link. Probably, it can be placed in the
"More" menu.
2023-11-10 13:55:27 -08:00
Erick Friis
93ae589f1b Add mongo parent template to index (#13222) 2023-11-10 11:56:44 -08:00
Tomaz Bratanic
0dc4ab0be1 Neo4j chat message history (#13008) 2023-11-10 11:53:34 -08:00
Bagatur
bf8cf7e042 Bagatur/langserve blurb (#13217) 2023-11-10 14:05:43 -05:00
fyasla
d266b3ea4a issue #12165 mask API key in chat_models/azureml_endpoint module (#12836)
- **Description:** `AzureMLChatOnlineEndpoint` object from
langchain/chat_models/azureml_endpoint.py safe to print
without having any secrets included in raw format in the string
representation.
  - **Issue:** #12165,
  - **Tag maintainer:** @eyurtsev

---------

Co-authored-by: Faysal Bougamale <faysal.bougamale@horiba.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-10 14:05:19 -05:00
Anush
52f34de9b7 feat: FastEmbed embedding provider (#13109)
## Description:
This PR intends to add
[Qdrant/FastEmbed](https://qdrant.github.io/fastembed/) as a local
embeddings provider, associated tests and documentation.

**Documentation preview:**
https://langchain-git-fork-anush008-master-langchain.vercel.app/docs/integrations/text_embedding/fastembed

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-11-10 13:51:52 -05:00
Eugene Yurtsev
b0e8cbe0b3 Add RunnableSequence documentation (#13094)
Add RunnableSequence documentation
2023-11-10 13:44:43 -05:00
Eugene Yurtsev
869df62736 Document RunnableWithFallbacks (#13088)
Add documentation to RunnableWithFallbacks
2023-11-10 13:16:21 -05:00
Eugene Yurtsev
8313c218da Add more runnable documentation (#13083)
- Adding documentation to the runnable.
- Documentation is not organized in the best way for the runnable; i.e.,
in
terms of LCEL vs. other standard methods, will follow up with more
edits.
2023-11-10 13:14:57 -05:00
Erick Friis
a26105de8e vectara rag mq (#13214)
Description: another Vectara template for MultiQuery RAG flow
Twitter handle: @ofermend

Fixes to #13106

---------

Co-authored-by: Ofer Mendelevitch <ofer@vectara.com>
Co-authored-by: Ofer Mendelevitch <ofermend@gmail.com>
2023-11-10 10:08:45 -08:00
Bagatur
24386e0860 bump 334, exp 40 (#13211) 2023-11-10 09:43:29 -08:00
Lance Martin
d2e50b3108 Add Chroma multimodal cookbook (#12952)
Pending:
* https://github.com/chroma-core/chroma/pull/1294
* https://github.com/chroma-core/chroma/pull/1293

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-10 09:43:10 -08:00
The1Bill
55912868da Update toolkit.py to remove single quotes around table names (#12445)
**Description:** Removing the single quote wrapper around the table
names in the SQL agent toolkit.py file as it misleads the LLM into
querying against tables with single quotes around their names.
**Issue:** #7457 
**Dependencies:** None
**Tag maintainer:** @hwchase17 
**Twitter handle:** None
2023-11-10 06:39:15 -08:00
Nuno Campos
362a446999 Changes to root listener (#12174)
- Implement config_specs to include session_id
- Remove Runnable method and update notebook
- Add more details to notebook, eg. show input schema and config schema
before and after adding message history

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-11-10 09:53:48 +00:00
Nuno Campos
b2b94424db Update return type for Runnable.__or__ (#12880)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-10 09:52:38 +00:00
Bagatur
dd7959f4ac template readme's in docs (#13152) 2023-11-09 23:36:21 -08:00
Bagatur
86b93b5810 Add serve to quickstart (#13174) 2023-11-09 23:10:26 -08:00
Bagatur
fbf7047468 Bagatur/update agent docs (#13167) 2023-11-09 21:14:30 -08:00
Harrison Chase
0a2b1c7471 improve duck duck go tool (#13165) 2023-11-09 20:49:39 -08:00
Bagatur
850336bcf1 Update model i/o docs (#13160) 2023-11-09 20:35:55 -08:00
Jacob Lee
cf271784fa Add basic critique revise template (#12688)
@baskaryan @hwchase17

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-09 17:33:29 -08:00
Cweili
ee3ceb0fb8 Document: Fix "Biadu" typo (#12985)
Fix document "Baidu Cloud ElasticSearch VectorSearch" `Biadu` typo.
2023-11-09 17:32:38 -08:00
Chenyu Zhao
defd4b4f11 Clean up Fireworks provider documentation (#13157) 2023-11-09 16:35:05 -08:00
Bagatur
d9e493e96c fix module sidebar (#13158) 2023-11-09 16:31:45 -08:00
wemysschen
e76ff63125 fix baiducloud_vector_search document typo (#12976)
**Issue:**
fix baiducloud_vector_search document typo

---------

Co-authored-by: wemysschen <root@icoding-cwx.bcc-szzj.baidu.com>
2023-11-09 16:27:04 -08:00
Holt Skinner
fceae456b9 fix: Updates to formatting in Google Drive Retriever docs (#13015)
- Minor updates to formatting to make easier to read
2023-11-09 16:15:55 -08:00
Bagatur
c63eb9d797 LCEL nits (#13155) 2023-11-09 16:09:33 -08:00
Shinya Maeda
28cc60b347 Fix langchain.llms OpenAI completion doesn't work due to v1 client update (#13099)
This commit fixes the issue that langchain.llms OpenAI completion
stopped working since the V1 openai client update.

Replace this entire comment with:
- **Description:** This PR fixes the issue [AttributeError: module
'openai' has no attribute
'Completion'](https://github.com/langchain-ai/langchain/issues/12967)
similar to
8e0cb2eb84
and https://github.com/langchain-ai/langchain/pull/12969,
  - **Issue:** https://github.com/langchain-ai/langchain/issues/12967,
  - **Dependencies:** `openai` v1.x.x client,
  - **Tag maintainer:** @baskaryan,
  - **Twitter handle:** @dosuken123 

Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

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

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-09 15:12:19 -08:00
Bagatur
555ce600ef Bagatur/docs serve context (#13150) 2023-11-09 15:05:18 -08:00
Bagatur
ff43cd6701 OpenAI remove httpx typing (#13154)
Addresses #13124
2023-11-09 14:32:09 -08:00
Erick Friis
8ad3b255dc Pirate Speak Configurable Template (#13153) 2023-11-09 22:13:45 +00:00
Bagatur
eb51150557 update oai tool agent doc (#13147) 2023-11-09 12:37:30 -08:00
Bagatur
b298f550fe update modules sidebar (#13141) 2023-11-09 11:57:09 -08:00
Bagatur
84e65533e9 Docs: combine LCEL index and why (#13142) 2023-11-09 11:16:45 -08:00
Bagatur
1311450646 fix langsmith links (#13144) 2023-11-09 11:12:50 -08:00
Bagatur
8b2a82b5ce Bagatur/docs smith context (#13139) 2023-11-09 10:22:49 -08:00
Erick Friis
58da6e0d47 Multimodal rag traces (#13140) 2023-11-09 09:54:00 -08:00
Bagatur
150d58304d update oai cookbooks (#13135) 2023-11-09 08:04:51 -08:00
Bagatur
f04cc4b7e1 bump 333 (#13131) 2023-11-09 07:33:15 -08:00
billytrend-cohere
b346d4a455 Add message to documents (#12552)
This adds the response message as a document to the rag retriever so
users can choose to use this. Also drops document limit.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-09 07:30:48 -08:00
Harrison Chase
5f38770161 Support oai tool call (#13110)
Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Nuno Campos <nuno@boringbits.io>
2023-11-09 07:29:29 -08:00
Stefano Lottini
c52725bdc5 (Astra DB/Cassandra) Minor clarification about dependencies in the demo notebook (#13118)
This PR helps developers trying the Astra DB / Cassandra vector store
quickstart notebook by making it clear what other dependencies are
required.
2023-11-09 09:19:15 -05:00
Holt Skinner
0fc8fd12bd feat: Vertex AI Search - Add Snippet Retrieval for Non-Advanced Website Data Stores (#13020)
https://cloud.google.com/generative-ai-app-builder/docs/snippets#snippets

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-11-08 21:52:50 -05:00
Erick Friis
3dbaaf59b2 Tool Retrieval Template (#13104)
Adds a template like
https://python.langchain.com/docs/modules/agents/how_to/custom_agent_with_tool_retrieval

Uses OpenAI functions, LCEL, and FAISS
2023-11-08 18:33:31 -08:00
Jacob Lee
76283e9625 Adds embeddings filter option to return scores in state (#12489)
CC @baskaryan @assafelovic
2023-11-08 17:50:06 -08:00
jakerachleff
18601bd4c8 Get project from langchain sdk (#13100)
## Description
We need to centralize the API we use to get the project name for our
tracers. This PR makes it so we always get this from a shared function
in the langsmith sdk.

## Dependencies
Upgraded langsmith from 0.52 to 0.62 to include the new API
`get_tracer_project`
2023-11-08 17:10:12 -08:00
Bagatur
72e12f6bcf update more azure docs (#13093) 2023-11-08 14:11:16 -08:00
Bagatur
1703f132c6 update azure embedding docs (#13091) 2023-11-08 13:39:31 -08:00
Bagatur
9fdfac22c2 bump 332 (#13089) 2023-11-08 13:23:16 -08:00
Bagatur
1f85ec34d5 bump 331rc3 exp 39 (#13086) 2023-11-08 13:00:13 -08:00
Anton Troynikov
9f077270c8 Don't pass EF to chroma (#13085)
- **Description:** 

Recently Chroma rolled out a breaking change on the way we handle
embedding functions, in order to support multi-modal collections.

This broke the way LangChain's `Chroma` objects get created, because we
were passing the EF down into the Chroma collection:
https://docs.trychroma.com/migration#migration-to-0416---november-7-2023

However, internally, we are never actually using embeddings on the
chroma collection - LangChain's `Chroma` object calls it instead. Thus
we just don't pass an `embedding_function` to Chroma itself, which fixes
the issue.
2023-11-08 12:55:35 -08:00
Erick Friis
f15f8e01cf Azure OpenAI Embeddings (#13039)
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-08 12:37:17 -08:00
David Peterson
37561d8986 Add Proper Import Error (#13042)
- **Description:** The issue was not listing the proper import error for
amazon textract loader.
- **Issue:** Time wasted trying to figure out what to install...
(langchain docs don't list the dependency either)
  - **Dependencies:** N/A
  - **Tag maintainer:** @sbusso 
  - **Twitter handle:** @h9ste

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-11-08 10:29:08 -08:00
Eugene Yurtsev
06c503f672 Add RunnableRetry Documentation (#13074) 2023-11-08 18:20:18 +00:00
Bagatur
55aeff6777 oai assistant multiple actions (#13068) 2023-11-08 08:25:37 -08:00
Erick Friis
a9b70baef9 cli updates, 0.0.16 (#13034)
- confirm flags, serve detection
- 0.0.16
- always gen code
- pip bool
2023-11-08 07:47:30 -08:00
Bagatur
1f27104626 Fleet context (#13038)
cc @adrwz
2023-11-07 18:57:09 -08:00
Bagatur
d26fd6f0d1 redirect langsmith walkthrough (#13040) 2023-11-07 18:24:13 -08:00
Erick Friis
6f45532620 Upgrade docs postcss (#13031) 2023-11-07 15:50:25 -08:00
Erick Friis
54ad3cc2b8 template versions again (#13030)
- scipy was locked due to py version
- same guardrails-output-parser
- rag-redis
2023-11-07 15:15:18 -08:00
Erick Friis
506f81563f Update Deps in Experimental (#13029) 2023-11-07 15:15:09 -08:00
Erick Friis
db4b97d590 Relock Templates (#13028) 2023-11-07 15:01:49 -08:00
Stefano Lottini
4f4b020582 Add "Astra DB" vector store integration (#12966)
# Astra DB Vector store integration

- **Description:** This PR adds a `VectorStore` implementation for
DataStax Astra DB using its HTTP API
  - **Issue:** (no related issue)
- **Dependencies:** A new required dependency is `astrapy` (`>=0.5.3`)
which was added to pyptoject.toml, optional, as per guidelines
- **Tag maintainer:** I recently mentioned to @baskaryan this
integration was coming
  - **Twitter handle:** `@rsprrs` if you want to mention me

This PR introduces the `AstraDB` vector store class, extensive
integration test coverage, a reworking of the documentation which
conflates Cassandra and Astra DB on a single "provider" page and a new,
completely reworked vector-store example notebook (common to the
Cassandra store, since parts of the flow is shared by the two APIs). I
also took care in ensuring docs (and redirects therein) are behaving
correctly.

All style, linting, typechecks and tests pass as far as the `AstraDB`
integration is concerned.

I could build the documentation and check it all right (but ran into
trouble with the `api_docs_build` makefile target which I could not
verify: `Error: Unable to import module
'plan_and_execute.agent_executor' with error: No module named
'langchain_experimental'` was the first of many similar errors)

Thank you for a review!
Stefano

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-07 14:45:33 -08:00
Tomaz Bratanic
13bd83bd61 Add neo4j vector memory template (#12993) 2023-11-07 13:00:49 -08:00
Bagatur
5ac2fc5bb2 update stack diagram (#13021) 2023-11-07 12:59:24 -08:00
Yang, Bo
600caff03c Add Memorize tool (#11722)
- **Description:** Add `Memorize` tool
  - **Tag maintainer:** @hwchase17

This PR added a new tool `Memorize` so that an agent can use it to
fine-tune itself. This tool requires `TrainableLLM` introduced in #11721

DEMO:
6a9003d5db

![image](https://github.com/langchain-ai/langchain/assets/601530/d6f0cb45-54df-4dcf-b143-f8aefb1e76e3)
2023-11-07 12:42:10 -08:00
Bagatur
cf481c9418 bump exp 38 (#13016) 2023-11-07 11:49:23 -08:00
Bagatur
57e19989f6 Bagatur/oai assistant (#13010) 2023-11-07 11:44:53 -08:00
Erick Friis
74134dd7e1 cli pyproject updating (#12945)
`langchain app add` and `langchain app remove` will now keep the
dependencies list updated.

---------

Co-authored-by: Nuno Campos <nuno@boringbits.io>
2023-11-07 11:06:08 -08:00
Tomaz Bratanic
d9abcf1aae Neo4j conversation cypher template (#12927)
Adding custom graph memory to Cypher chain

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-07 11:05:28 -08:00
Lance Martin
2287a311cf Multi modal RAG + QA Cookbooks (#12946)
Co-authored-by: Erick Friis <erick@langchain.dev>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
Co-authored-by: Vinzenz Klass <76391770+VinzenzKlass@users.noreply.github.com>
Co-authored-by: Praveen Venkateswaran <praveenv@uci.edu>
Co-authored-by: Praveen Venkateswaran <praveen.venkateswaran@ibm.com>
Co-authored-by: Kacper Łukawski <kacperlukawski@users.noreply.github.com>
Co-authored-by: Bagatur <22008038+baskaryan@users.noreply.github.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Ofer Mendelevitch <ofermend@gmail.com>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-11-07 09:10:24 -08:00
Bagatur
6175dc30aa bump 331rc2 (#13006) 2023-11-07 08:52:17 -08:00
Jasan
ff87f4b4f9 Fix for rag-supabase readme (#12869)
- **Description:** Correct naming for package in README
- **Issue:** README wasn't aligned with pyproject.toml, resulting in not
being able to install the rag-supabase package.
  - **Tag maintainer:** @gregnr
2023-11-06 19:38:22 -08:00
Harrison Chase
99ffeb239f add ingest for mongo (#12897) 2023-11-06 19:28:22 -08:00
Ofer Mendelevitch
ce21308f29 Vectara RAG template (#12975)
- **Description:** RAG template using Vectara
  - **Twitter handle:** @ofermend
2023-11-06 19:24:00 -08:00
Erick Friis
0c81cd923e oai v1 embeddings (#12969)
Initial PR to get OpenAIEmbeddings working with the new sdk

fyi @rlancemartin 

Fixes #12943

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-06 18:52:33 -08:00
Bagatur
fdbb45d79e bump 331rc1 (#12965) 2023-11-06 15:36:43 -08:00
Bagatur
3bb8030a6e fix max_tokens (#12964) 2023-11-06 15:36:05 -08:00
Bagatur
a9002a82b8 bump 331rc0 (#12963) 2023-11-06 15:19:33 -08:00
Harrison Chase
c27400efeb Support multimodal messages (#11320)
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-06 15:14:18 -08:00
Bagatur
388f248391 add oai v1 cookbook (#12961) 2023-11-06 14:28:32 -08:00
Bagatur
4f7dff9d66 Record system fingerprint chat openai (#12960) 2023-11-06 14:25:53 -08:00
Bagatur
8e0cb2eb84 ChatOpenAI and AzureChatOpenAI openai>=1 compatible (#12948) 2023-11-06 13:24:18 -08:00
Kacper Łukawski
52d0055a91 Add support of Cohere Embed v3 (#12940)
Cohere released the new embedding API (Embed v3:
https://txt.cohere.com/introducing-embed-v3/) that treats document and
query embeddings differently. This PR updated the `CohereEmbeddings` to
use them appropriately. It also works with the old models.
2023-11-06 15:06:58 -05:00
Praveen Venkateswaran
8e0dcb37d2 Add SecretStr for Symbl.ai Nebula API (#12896)
Description: This PR masks API key secrets for the Nebula model from
Symbl.ai
Issue: #12165 
Maintainer: @eyurtsev

---------

Co-authored-by: Praveen Venkateswaran <praveen.venkateswaran@ibm.com>
2023-11-06 14:13:59 -05:00
Vinzenz Klass
59d0bd2150 feat: acquire advisory lock before creating extension in pgvector (#12935)
- **Description:** Acquire advisory lock before attempting to create
extension on postgres server, preventing errors in concurrent
executions.
  - **Issue:** #12933
  - **Dependencies:** None

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-11-06 14:00:39 -05:00
Eugene Yurtsev
b376854b26 Fix for anyscale chat model api key (#12938)
* ChatAnyscale was missing coercion to SecretStr for anyscale api key
* The model inherits from ChatOpenAI so it should not force the openai
api key to be secret str until openai model has the same changes

https://github.com/langchain-ai/langchain/issues/12841
2023-11-06 13:28:02 -05:00
Bagatur
58889149c2 fix guides link (#12941) 2023-11-06 08:13:02 -08:00
matthieudelaro
52503a367f Remove useless line of code from sql.ipynb (#12906)
This PR remove a single line of code from a notebook of the
documentation. This line used to define a variable, which is never used
in the code.
For further context, for reviewers, here is the online documentation:
https://python.langchain.com/docs/use_cases/qa_structured/sql#case-3-sql-agents
2023-11-06 07:59:12 -08:00
hmasdev
622bf12c2e fix regex pattern of structured output parser (#12929)
- **Description:** fix the regex pattern of
[StructuredChatOutputParser](https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain/agents/structured_chat/output_parser.py#L18)
and add unit tests for the code change.
- **Issue:** #12158 #12922
- **Dependencies:** None
- **Tag maintainer:** 
- **Twitter handle:** @hmdev3
- **NOTE:** This PR conflicts #7495 . After #7495 is merged, I am going
to update PR.
2023-11-06 07:53:14 -08:00
wemysschen
8c02f4fbd8 add baidu cloud vectorsearch document (#12928)
**Description:** 
Add BaiduCloud VectorSearch document with implement of BESVectorSearch
in langchain vectorstores

---------

Co-authored-by: wemysschen <root@icoding-cwx.bcc-szzj.baidu.com>
2023-11-06 07:52:50 -08:00
wemysschen
8d7144e6a6 fix baiducloud directory loader import file loader (#12924)
**Issue:** 
fix baiducloud BOS directory loader imports its file loader

---------

Co-authored-by: wemysschen <root@icoding-cwx.bcc-szzj.baidu.com>
2023-11-06 07:52:31 -08:00
Alex Howard
5bb2ea51a5 docs: clean up vestigial markdown (#12907)
- **Description:** Remove text "LangChain currently does not support"
which appears to be vestigial leftovers from a previous change.
  - **Issue:** N/A
  - **Dependencies:** N/A
  - **Tag maintainer:** @baskaryan, @eyurtsev
  - **Twitter handle:** thezanke
2023-11-06 07:51:56 -08:00
Praveen Venkateswaran
1eb7d3a862 docs: update hf pipeline docs (#12908)
- **Description:** Noticed that the Hugging Face Pipeline documentation
was a bit out of date.
Updated with information about passing in a pipeline directly
(consistent with docstring) and a recent contribution of mine on adding
support for multi-gpu specifications with Accelerate in
21eeba075c
2023-11-06 07:51:31 -08:00
Christoffer Bo Petersen
37da6e546b Fix typo in e2b_data_analysis.ipynb (#12930)
Just a small typo fix
2023-11-06 07:37:30 -08:00
Kacper Łukawski
621419f71e Fix normalizing the cosine distance in Qdrant (#12934)
Qdrant was incorrectly calculating the cosine similarity and returning
`0.0` for the best match, instead of `1.0`. Internally Qdrant returns a
cosine score from `-1.0` (worst match) to `1.0` (best match), and the
current formula reflects it.
2023-11-06 07:36:59 -08:00
Hech
8fe6bcc662 Fix return metadata when searching for DingoDB (#12937) 2023-11-06 07:35:36 -08:00
Jakub Novák
ada3d2cbd1 Add possibility to pass on_artifacts for a specific conversation (#12687)
Possibility to pass on_artifacts to a conversation. It can be then
achieved by adding this way:

```python
result = agent.run(
    input=message.text,
    metadata={
        "on_artifact": CALLBACK_FUNCTION
    },
)
```
2023-11-06 07:29:47 -08:00
Bagatur
0378662e1d fix langsmith link (#12939) 2023-11-06 07:17:05 -08:00
Harrison Chase
1a92d2245d Harrison/docs smith serve (#12898)
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-06 07:07:25 -08:00
Bagatur
53f453f01a bump 331 (#12932) 2023-11-06 05:58:12 -08:00
Priyadutt
a4d9e986fb Update csv.ipynb description (#12878)
The line removed is not required as there are no other alternative
solutions above than that.

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-06 03:32:04 -08:00
Erick Friis
5000c7308e cli template gitignores (#12914)
- ap gitignore
- package
2023-11-05 22:34:45 -08:00
Harrison Chase
aba407f774 use keys not items (#12918) 2023-11-05 22:08:29 -08:00
Harrison Chase
60d025b83b mongo parent document retrieval (#12887) 2023-11-04 10:16:02 -07:00
Michael Hunger
e43b4079c8 template: use dashes instead of underscores for neo4j-cypher package and path in readme (#12827)
Minimal readme template update

underscores didn't work, dashes do
2023-11-03 15:54:48 -07:00
wemysschen
e14aa37d59 fix bes vector store search (#12828)
**Issue:** 
fix search body in baidu cloud vectorsearch

---------

Co-authored-by: wemysschen <root@icoding-cwx.bcc-szzj.baidu.com>
2023-11-03 15:39:19 -07:00
standby24x7
f04e4df7f9 coockbook: Fix typo in wikibase_agent.ipynb (#12839)
This patch fixes a spelling typo in message
within wikibase_agent.ipynb.

Signed-off-by: Masanari Iida <standby24x7@gmail.com>

Signed-off-by: Masanari Iida <standby24x7@gmail.com>
2023-11-03 14:57:37 -07:00
Kacper Łukawski
66c41c0dbf Add template for self-query-qdrant (#12795)
This PR adds a self-querying template using Qdrant as a vector store.
The template uses an artificial dataset and was implemented in a way
that simplifies passing different components and choosing LLM and
embedding providers.

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-03 13:37:29 -07:00
Daniel Chalef
f41f4c5e37 zep/rag conversation zep template (#12762)
LangServe template for a RAG Conversation App using Zep.

 @baskaryan, @eyurtsev

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-03 13:34:44 -07:00
Lance Martin
ea1ab391d4 Open Clip multimodal embeddings (#12754) 2023-11-03 13:33:36 -07:00
Bagatur
ebee616822 bump 330 (#12853) 2023-11-03 13:26:41 -07:00
Tomaz Bratanic
0dbdb8498a Neo4j Advanced RAG template (#12794)
Todo:

- [x] Docs
2023-11-03 13:22:55 -07:00
Harrison Chase
83cee2cec4 Template Readmes and Standardization (#12819)
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-03 13:15:29 -07:00
Erick Friis
6c237716c4 Update readmes with new cli install (#12847)
Old command still works. Just simplifying.

Merge after releasing CLI 0.0.15
2023-11-03 12:10:32 -07:00
Erick Friis
7db49d3842 Confirm sys.path includes current dir for app serve (#12851)
- Make sure sys.path is set properly for langchain app serve
- bump
2023-11-03 11:37:20 -07:00
Erick Friis
1bc35f61cb CLI 0.0.14, Uvicorn update and no more [serve] (#12845)
Calls uvicorn directly from cli:
Reload works if you define app by import string instead of object.
(was doing subprocess in order to get reloading)

Version bump to 0.0.14

Remove the need for [serve] for simplicity.

Readmes are updated in #12847 to avoid cluttering this PR
2023-11-03 11:05:52 -07:00
Brace Sproul
76bcac5bb3 Remove admin prefix/suffix from docs for anthropic (#12849) 2023-11-03 10:54:16 -07:00
Harrison Chase
523e5803bb update mongo template (#12838) 2023-11-03 10:31:53 -07:00
William FH
18005c6384 Disable trace_on_chain_group auto-tracing (#12807)
Previously we treated trace_on_chain_group as a command to always start
tracing. This is unintuitive (makes the function do 2 things), and makes
it harder to toggle tracing
2023-11-03 10:05:09 -07:00
Erick Friis
0da75b9ebd Autopopulate module name in cli init (#12814) 2023-11-02 23:45:38 -07:00
William FH
98aff29fbd Add Dataset Page to printout (#12816) 2023-11-02 20:36:56 -07:00
Joseph Martinez
f573a4d0b3 Update quickstart.mdx (#12386)
**Description**
Removed confusing sentence. 
Not clear what "both" was referring to. The two required components
mentioned previously? The two methods listed below?

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-02 18:38:21 -07:00
Leonid Ganeline
e112b2f2e6 updated integrations/providers/google (#12226)
Added missed integrations. Updated formats.

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-02 18:35:31 -07:00
Manuel Rech
2e2b9c76d9 Keep also original query - multi_query.py (#12696)
When you use a MultiQuery it might be useful to use the original query
as well as the newly generated ones to maximise the changes to retriever
the correct document. I haven't created an issue, it seems a very small
and easy thing.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-02 18:15:02 -07:00
Michael Landis
4fe9bf70b6 feat: add a rag template for momento vector index (#12757)
# Description
Add a RAG template showcasing Momento Vector Index as a vector store.
Includes a project directory and README.

# **Twitter handle** 

Tag the company @momentohq for a mention and @mlonml for the
contribution.
2023-11-02 17:59:15 -07:00
刘 方瑞
26c4ec1eaf myscale notebook url change (#12810)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-02 17:56:26 -07:00
Lance Martin
2683c2fc53 Update template index (#12809) 2023-11-02 17:51:40 -07:00
apeng-singlestore
5c0e9ac578 Add template for rag-singlestoredb (#12805)
This change adds a new template for simple RAG using the SingleStoreDB
vectorstore.

Twitter: @alexjpeng

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-02 17:51:00 -07:00
Bagatur
658a3a8607 FEAT: Merge TileDB vecstore (#12811) 2023-11-02 17:40:32 -07:00
Akio Nishimura
c04647bb4e Correct number of elements in config list in batch() and abatch() of BaseLLM (#12713)
- **Description:** Correct number of elements in config list in
`batch()` and `abatch()` of `BaseLLM` in case `max_concurrency` is not
None.
- **Issue:** #12643
- **Twitter handle:** @akionux

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-02 17:28:48 -07:00
James Braza
88b506b321 Adds missing urllib.parse for IDE warning of PubMedAPIWrapper (#12808)
Resolves an IDE (PyCharm 2023.2.3 PE) warning around
`urllib.parse.quote`, also enabling CTRL-click
2023-11-02 17:27:25 -07:00
Bagatur
a2bb0dd445 TileDB update import unit tests 2023-11-02 17:24:22 -07:00
Nikos Papailiou
2fdaa1e5fd Add TileDB vectorstore implementation (#12624)
- **Description:** Add [TileDB](https://tiledb.com) vectorstore
implementation. TileDB offers ANN search capabilities using the
[TileDB-Vector-Search](https://github.com/TileDB-Inc/TileDB-Vector-Search)
module. It provides serverless execution of ANN queries and storage of
vector indexes both on local disk and cloud object stores (i.e. AWS S3).
More details in:
- [Why TileDB as a Vector
Database](https://tiledb.com/blog/why-tiledb-as-a-vector-database)
- [TileDB 101: Vector
Search](https://tiledb.com/blog/tiledb-101-vector-search)
- **Twitter handle:** @tiledb
2023-11-02 17:21:03 -07:00
盐粒 Yanli
1b233798a0 feat: Supprt pgvecto.rs as a VectorStore (#12718)
Supprt [pgvecto.rs](https://github.com/tensorchord/pgvecto.rs) as a new
VectorStore type.

This introduces a new dependency
[pgvecto_rs](https://pypi.org/project/pgvecto_rs/) and upgrade
SQLAlchemy to ^2.

Relate to https://github.com/tensorchord/pgvecto.rs/issues/11

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-02 17:16:04 -07:00
Daniel Chalef
0cbdba6a9b zep: VectorStore: Use Native MMR (#12690)
- refactor to use Zep's native MMR; update example
- 
@baskaryan @eyurtsev
2023-11-02 16:45:42 -07:00
Daniel Chalef
cc3d3920e3 Zep: Summary Search and Example (#12686)
Zep now has the ability to search over chat history summaries. This PR
adds support for doing so. More here: https://blog.getzep.com/zep-v0-17/

@baskaryan @eyurtsev
2023-11-02 16:31:11 -07:00
Bagatur
526313002c add import tests to all modules (#12806) 2023-11-02 15:32:55 -07:00
Harrison Chase
6609a6033f fix vectorstore imports (#12804)
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-11-02 15:32:31 -07:00
Nuno Campos
f66a9d2adf Automatically add configurable key to config_schema if config_specs i… (#12798)
…s present

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-02 21:46:15 +00:00
Praveen Venkateswaran
21eeba075c enable the device_map parameter in huggingface pipeline (#12731)
### Enabling `device_map` in HuggingFacePipeline 

For multi-gpu settings with large models, the
[accelerate](https://huggingface.co/docs/accelerate/usage_guides/big_modeling#using--accelerate)
library provides the `device_map` parameter to automatically distribute
the model across GPUs / disk.

The [Transformers
pipeline](3520e37e86/src/transformers/pipelines/__init__.py (L543))
enables users to specify `device` (or) `device_map`, and handles cases
(with warnings) when both are specified.

However, Langchain's HuggingFacePipeline only supports specifying
`device` when calling transformers which limits large models and
multi-gpu use-cases.
Additionally, the [default
value](8bd3ce59cd/libs/langchain/langchain/llms/huggingface_pipeline.py (L72))
of `device` is initialized to `-1` , which is incompatible with the
transformers pipeline when `device_map` is specified.

This PR addresses the addition of `device_map` as a parameter , and
solves the incompatibility of `device = -1` when `device_map` is also
specified.
An additional test has been added for this feature. 

Additionally, some existing tests no longer work since 
1. `max_new_tokens` has to be specified under `pipeline_kwargs` and not
`model_kwargs`
2. The GPT2 tokenizer raises a `ValueError: Pipeline with tokenizer
without pad_token cannot do batching`, since the `tokenizer.pad_token`
is `None` ([related
issue](https://github.com/huggingface/transformers/issues/19853) on the
transformers repo).

This PR handles fixing these tests as well.

Co-authored-by: Praveen Venkateswaran <praveen.venkateswaran@ibm.com>
2023-11-02 14:29:06 -07:00
Mark Bell
3276aa3e17 __getattr__ should rase AttributeError not ImportError on missing attributes (#12801)
[The python
spec](https://docs.python.org/3/reference/datamodel.html#object.__getattr__)
requires that `__getattr__` throw `AttributeError` for missing
attributes but there are several places throwing `ImportError` in the
current code base. This causes a specific problem with `hasattr` since
it calls `__getattr__` then looks only for `AttributeError` exceptions.
At present, calling `hasattr` on any of these modules will raise an
unexpected exception that most code will not handle as `hasattr`
throwing exceptions is not expected.

In our case this is triggered by an exception tracker (Airbrake) that
attempts to collect the version of all installed modules with code that
looks like: `if hasattr(mod, "__version__"):`. With `HEAD` this is
causing our exception tracker to fail on all exceptions.

I only changed instances of unknown attributes raising `ImportError` and
left instances of known attributes raising `ImportError`. It feels a
little weird but doesn't seem to break anything.
2023-11-02 17:08:54 -04:00
Daniel Chalef
d966e4d13a zep: Update Zep docs and messaging (#12764)
Update Zep documentation with messaging, more details.

 @baskaryan, @eyurtsev
2023-11-02 13:39:17 -07:00
Illia
71d1a48b66 Use data from all Google search results in SerpApi.com wrapper (#12770)
- **Description:** Use all Google search results data in SerpApi.com
wrapper instead of the first one only
  - **Tag maintainer:** @hwchase17 

_P.S. `libs/langchain/tests/integration_tests/utilities/test_serpapi.py`
are not executed during the `make test`._
2023-11-02 13:31:27 -07:00
ba230t
9214d8e6ed Fixed a typo in templates/docs/CONTRIBUTING.md (delimeters =>delimiters) (#12774)
- **Description:** Just fixed a minor typo in
templates/docs/CONTRIBUTING.md.
  - **Issue:** No linked issues.

Very small contribution!
2023-11-02 13:31:04 -07:00
Armin Stepanjan
185ddc573e Fix broken links to use cases (#12777)
This PR replaces broken links to end to end usecases
([/docs/use_cases](https://python.langchain.com/docs/use_cases)) with a
non-broken version
([/docs/use_cases/qa_structured/sql](https://python.langchain.com/docs/use_cases/qa_structured/sql)),
consistently with the "Use cases" navigation button at the top of the
page.

---------

Co-authored-by: Matvey Arye <mat@timescale.com>
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-02 13:20:54 -07:00
니콜라스
25ee10ed4f Docs: 'memory' -> 'history' typo. (#12779)
The 'MessagesPlaceholder' expects 'history' but 'RunnablePassthrough' is
assigning 'memory'.
2023-11-02 13:09:39 -07:00
yudai yamamoto
1f7e811156 Fixed broken link in Quickstart page (#12516)
- **Description:** 
Corrected a specific link within the documentation.
  
  - **Issue:**
  #12490 

  - **Dependencies:**
  - **Tag maintainer:**
  - **Twitter handle:**

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-02 13:00:53 -07:00
Ikko Eltociear Ashimine
9b02f7d59c Update llamacpp.ipynb (#12791)
HuggingFace -> Hugging Face
2023-11-02 12:52:12 -07:00
Tomaz Bratanic
2a9f40ed28 Add input types to cypher templates (#12800) 2023-11-02 12:46:02 -07:00
Nuno Campos
c4fdf78d03 Fix AddableDict raising exception when used with non-addable values (#12785)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-02 18:56:29 +00:00
Erick Friis
49e283a0cd CLI 0.0.13, Configurable Template Demo (#12796) 2023-11-02 11:42:57 -07:00
Nuno Campos
d1c6ad7769 Fix on_llm_new_token(chunk=) for some chat models (#12784)
It was passing in message instead of generation

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-02 16:33:44 +00:00
Erick Friis
070823f294 CLI 0.0.12 (#12787) 2023-11-02 08:29:27 -07:00
Bagatur
979501c0ca bump 329 (#12778) 2023-11-02 06:02:43 -07:00
Matvey Arye
9369d6aca0 Fixes to the docs for timescale vector template (#12756) 2023-11-01 18:48:23 -07:00
Lance Martin
33810126bd Update chat prompt structure in LLaMA SQL cookbook (#12364)
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-01 16:37:03 -07:00
ElliotKetchup
58b90f30b0 Update llama.cpp integration (#11864)
<!-- 
- **Description:** removed redondant link, replaced it with Meta's LLaMA
repo, add resources for models' hardware requirements,
  - **Issue:** None,
  - **Dependencies:** None,
  - **Tag maintainer:** None,
  - **Twitter handle:** @ElliotAlladaye
 -->
2023-11-01 16:32:02 -07:00
Manuel Soria
a228f340f1 Semantic search within postgreSQL using pgvector (#12365)
Cookbook showing how to incoporate RAG search within a postgreSQL
database using pgvector.

---------

Co-authored-by: Lance Martin <lance@langchain.dev>
Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-01 16:21:34 -07:00
Erick Friis
da821320d3 Fixes 'Nonetype' not iterable for ObsidianLoader (#12751)
Implements #12726 from @Di3mex
2023-11-01 16:07:09 -07:00
Juan Bustos
67b6f4dc71 Update google_vertex_ai_palm.ipynb (#12715)
Fixed a typo

<!-- Thank you for contributing to LangChain!

Replace this entire comment with:
  - **Description:** Fixed a typo on the code
  - **Issue:** the issue # it fixes (if applicable),


Please make sure your PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-01 16:05:44 -07:00
Eugene Yurtsev
b1caae62fd APIChain add restrictions to domains (CVE-2023-32786) (#12747)
* Restrict the chain to specific domains by default
* This is a breaking change, but it will fail loudly upon object
instantiation -- so there should be no silent errors for users
* Resolves CVE-2023-32786
2023-11-01 18:50:34 -04:00
Erick Friis
4421ba46d7 Demo Server, Fix Timescale (#12746)
- improve demo server
- missing deps
2023-11-01 15:29:34 -07:00
Eugene Yurtsev
0e1aedb9f4 Use jinja2 sandboxing by default (#12733)
* This is an opt-in feature, so users should be aware of risks if using
jinja2.
* Regardless we'll add sandboxing by default to jinja2 templates -- this
  sandboxing is a best effort basis.
* Best strategy is still to make sure that jinja2 templates are only
loaded from trusted sources.
2023-11-01 14:54:01 -07:00
Erick Friis
ab5309f6f2 template updates (#12736)
- langchain license
- add timescale vector dep to that template
2023-11-01 13:53:26 -07:00
Lance Martin
6406c53089 Update template index w/ Timescale (#12729) 2023-11-01 12:04:54 -07:00
Erick Friis
14340ee7cd use http.client instead of urllib3 (#12660)
dep problems with requests

cloudflare debugging not worth it with urllib
2023-11-01 11:15:05 -07:00
Bagatur
eee5181b7a bump 328, exp 37 (#12722) 2023-11-01 10:27:39 -07:00
Erick Friis
3405dbbc64 dash not underscore (#12716)
template names are auto-populating with the wrong convention (with
underscores)
2023-11-01 09:48:37 -07:00
123-fake-st
8bd3ce59cd PyPDFLoader use url in metadata source if file is a web path (#12092)
**Description:** Update `langchain.document_loaders.pdf.PyPDFLoader` to
store url in metadata (instead of a temporary file path) if user
provides a web path to a pdf

- **Issue:** Related to #7034; the reporter on that issue submitted a PR
updating `PyMuPDFParser` for this behavior, but it has unresolved merge
issues as of 20 Oct 2023 #7077
- In addition to `PyPDFLoader` and `PyMuPDFParser`, these other classes
in `langchain.document_loaders.pdf` exhibit similar behavior and could
benefit from an update: `PyPDFium2Loader`, `PDFMinerLoader`,
`PDFMinerPDFasHTMLLoader`, `PDFPlumberLoader` (I'm happy to contribute
to some/all of that, including assisting with `PyMuPDFParser`, if my
work is agreeable)
- The root cause is that the underlying pdf parser classes, e.g.
`langchain.document_loaders.parsers.pdf.PyPDFParser`, never receive
information about the url; the parsers receive a
`langchain.document_loaders.blob_loaders.blob`, which contains the pdf
contents and local file path, but not the url
- This update passes the web path directly to the parser since it's
minimally invasive and doesn't require further changes to maintain
existing behavior for local files... bigger picture, I'd consider
extending `blob` so that extra information like this can be
communicated, but that has much bigger implications on the codebase
which I think warrants maintainer input

  - **Dependencies:** None

```python
# old behavior
>>> from langchain.document_loaders import PyPDFLoader
>>> loader = PyPDFLoader('https://arxiv.org/pdf/1706.03762.pdf')
>>> docs = loader.load()
>>> docs[0].metadata
{'source': '/var/folders/w2/zx77z1cs01s1thx5dhshkd58h3jtrv/T/tmpfgrorsi5/tmp.pdf', 'page': 0}

# new behavior
>>> from langchain.document_loaders import PyPDFLoader
>>> loader = PyPDFLoader('https://arxiv.org/pdf/1706.03762.pdf')
>>> docs = loader.load()
>>> docs[0].metadata
{'source': 'https://arxiv.org/pdf/1706.03762.pdf', 'page': 0}
```
2023-11-01 11:27:00 -04:00
Dave Kwon
b1954aab13 feat: Add page metadata on PDFMinerLoader (#12277)
- **Description:** #12273 's suggestion PR
Like other PDFLoader, loading pdf per each page and giving page
metadata.
  - **Issue:** #12273 
  - **Twitter handle:** @blue0_0hope

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-11-01 11:25:37 -04:00
Duda Nogueira
7148f3e1fe Weaviate - Fix schema existence check (#12711)
This will allow you create the schema beforehand. The check was failing
and preventing importing into existing classes.

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-11-01 08:22:15 -07:00
Sayandip
8dbbcf0b6c Adding a template for Solo Performance Prompting Agent (#12627)
**Description:** This template creates an agent that transforms a single
LLM into a cognitive synergist by engaging in multi-turn
self-collaboration with multiple personas.
**Tag maintainer:** @hwchase17

---------

Co-authored-by: Sayandip Sarkar <sayandip.sarkar@skypointcloud.com>
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-11-01 08:10:07 -07:00
Aidos Kanapyanov
ae63c186af Mask API key for Anyscale LLM (#12406)
Description: Add masking of API Key for Anyscale LLM when printed.
Issue: #12165 
Dependencies: None
Tag maintainer: @eyurtsev

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-11-01 10:22:26 -04:00
Predrag Gruevski
5ae51a8a85 Fix typo highlighted by ruff autoformatter. (#12691)
H/t @MichaReiser for spotting it:
https://github.com/langchain-ai/langchain/pull/12585/files#r1378253045
2023-10-31 22:16:06 -04:00
Predrag Gruevski
724b92231d Remove black caching config from CI lint workflow. (#12594)
To merge after #12585 is merged.
2023-10-31 21:39:05 -04:00
Predrag Gruevski
0ea837404a Only publish to test PyPI from the _test_release.yml workflow. (#12668)
PyPI trusted publishing wants to know which workflow is expected to do
the publish. We always want to publish from the same workflow, so we're
making `_test_release.yml` the only workflow that publishes to Test
PyPI.
2023-10-31 21:36:38 -04:00
Predrag Gruevski
321cd44f13 Use separate jobs for building and publishing test releases. (#12671)
This follows the principle of least privilege. Our `poetry build` step
doesn't need, and shouldn't get, access to our GitHub OIDC capability.

This is the same structure as I used in the already-merged PR for
refactoring the regular PyPI release workflow: #12578.
2023-10-31 21:36:26 -04:00
Erick Friis
44c8b159b9 properly increment version in cli (#12685)
Went from 0.0.9 -> 0.0.11 without releasing. Back to 10, then release.
2023-10-31 17:27:43 -07:00
Erick Friis
b825dddf95 fix elastic rag template in playground (#12682)
- a few instructions in the readme (load_documents -> ingest.py)
- added docker run command for local elastic
- adds input type definition to render playground properly
2023-10-31 17:18:35 -07:00
Lance Martin
f0eba1ac63 Add RAG input types (#12684)
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-10-31 17:13:44 -07:00
Erick Friis
392cfbee24 link to templates (#12680) 2023-10-31 16:19:22 -07:00
Leonid Ganeline
ddcec005bc fix for YahooFinanceNewsTool (#12665)
Added YahooFinanceNewsTool to the __init__.py 
It was missed here.
2023-10-31 14:58:09 -07:00
Predrag Gruevski
09711ad5a1 Both lint and format templates with ruff v0.1.3. (#12676)
- Both lint and format code in `templates`.
- Upgrade to ruff v0.1.3.
2023-10-31 14:52:00 -07:00
Predrag Gruevski
01a3c9b94e Use an in-project virtualenv in the CLI package. (#12678)
Keeping it in sync with how our other packages are configured.
2023-10-31 14:51:24 -07:00
Predrag Gruevski
f7f35a9102 Use black to lint notebooks and docs for now. (#12679)
Due to #12677 having lots of errors for the time being.
2023-10-31 14:51:05 -07:00
Jacob Lee
bd668fcea1 Adds version CLI command (#12619)
Will be automatically bumped with `poetry version patch`.

@efriis @hwchase17

---------

Co-authored-by: Erick Friis <erick@langchain.dev>
2023-10-31 14:50:04 -07:00
Frank
bf5805bb32 Add quip loader (#12259)
- **Description:** implement [quip](https://quip.com) loader
  - **Issue:** https://github.com/langchain-ai/langchain/issues/10352
  - **Dependencies:** No
  -  pass make format, make lint, make test

---------

Co-authored-by: Hao Fan <h_fan@apple.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-31 14:11:24 -07:00
Roman Vasilyev
c9a6940d58 PGVector fix (#12592)
latest release broken, this fixes it

---------

Co-authored-by: Roman Vasilyev <rvasilyev@mozilla.com>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-10-31 17:01:15 -04:00
Lance Martin
9e17d1a225 Update Vertex template (#12644)
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-10-31 14:00:22 -07:00
Predrag Gruevski
aa3f4a9bc8 Remove the CLI package's pydantic compatibility tests. (#12675)
They aren't necessary, since the CLI package doesn't have a direct
dependency on pydantic.
2023-10-31 16:57:38 -04:00
Predrag Gruevski
e8b99364b3 Use ruff for both linting and formatting in langchain-cli. (#12672)
Prior to this PR, `ruff` was used only for linting and not for
formatting, despite the names of the commands. This PR makes it be used
for both linting code and autoformatting it.
2023-10-31 13:52:25 -07:00
Harrison Chase
9a10b2b047 fix plate chain (#12673) 2023-10-31 13:45:09 -07:00
Margaret Qian
acfc485808 Update MosaicML Embedding Input Key (#12657)
This input key was missed in the last update PR:
https://github.com/langchain-ai/langchain/pull/7391

The input/output formats are intended to be like this:

```
{"inputs": [<prompt>]} 

{"outputs": [<output_text>]}
```
2023-10-31 14:43:30 -04:00
Erika Cardenas
d26ac5f999 Update README for Hybrid Search Weaviate (#12661)
- **Description:** Updated the README for Hybrid Search Weaviate
2023-10-31 11:02:34 -07:00
Predrag Gruevski
c871cc5055 Remove print() statements which seemed leftover from debugging. (#12648)
Added in #12159 presumably during debugging. Right now they cause a bit of visual noise.
2023-10-31 13:45:48 -04:00
Erick Friis
2a7e0a27cb update lc version (#12655)
also updated py version in `csv-agent` and `rag-codellama-fireworks`
because they have stricter python requirements
2023-10-31 10:19:15 -07:00
Predrag Gruevski
360cff81a3 Overwrite existing distributions when uploading to test PyPI. (#12658) 2023-10-31 10:02:50 -07:00
Lance Martin
da94c750c5 Add RAG template for Timescale Vector (#12651)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

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

---------

Co-authored-by: Matvey Arye <mat@timescale.com>
2023-10-31 09:56:29 -07:00
Noam Gat
14e8c74736 LM Format Enforcer Integration + Sample Notebook (#12625)
## Description

This PR adds support for
[lm-format-enforcer](https://github.com/noamgat/lm-format-enforcer) to
LangChain.

![image](https://raw.githubusercontent.com/noamgat/lm-format-enforcer/main/docs/Intro.webp)

The library is similar to jsonformer / RELLM which are supported in
Langchain, but has several advantages such as
- Batching and Beam search support
- More complete JSON Schema support
- LLM has control over whitespace, improving quality
- Better runtime performance due to only calling the LLM's generate()
function once per generate() call.

The integration is loosely based on the jsonformer integration in terms
of project structure.

## Dependencies

No compile-time dependency was added, but if `lm-format-enforcer` is not
installed, a runtime error will occur if it is trying to be used.

## Tests

Due to the integration modifying the internal parameters of the
underlying huggingface transformer LLM, it is not possible to test
without building a real LM, which requires internet access. So, similar
to the jsonformer and RELLM integrations, the testing is via the
notebook.

## Twitter Handle

[@noamgat](https://twitter.com/noamgat)


Looking forward to hearing feedback!

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-31 09:49:01 -07:00
Stefano Lottini
a4e4b5a86f Relax python version and remove need for explicit setup step (#12637)
This PR addresses what seems like a unnecessary Python version
restriction in the pyroject.toml specs within both Cassandra (/Astra DB)
templates. With "^3.11" I got some version incompatibilities with the
latest "langchain add [...]" commands, so these are now relaxed in line
with the other templates I could inspect.

Incidentally, in the "entomology" template, the need for an explicit
"setup" step for the user to carry on has been removed, replaced by a
check-and-execute-if-necessary instruction on app startup.

Thank you for your attention!
2023-10-31 09:42:27 -07:00
Predrag Gruevski
5308b836c7 Upgrade to actions/checkout@v4 in the docs lint job. (#12581) 2023-10-31 12:41:18 -04:00
Predrag Gruevski
94f018f1ba Support release-testing packages with dashes in their names. (#12654) 2023-10-31 12:40:34 -04:00
Erick Friis
912ace18e9 fix template py verisons (#12650) 2023-10-31 09:20:29 -07:00
Brian McBrayer
b74468f399 Fix small typo on Founcational -> Router notebook (#12634)
- **Description:** Fix small typo on Founcational -> Router notebook
2023-10-31 09:16:29 -07:00
Predrag Gruevski
72fa5a463d Show ruff output inline in GitHub PRs. (#12647) 2023-10-31 12:16:01 -04:00
William FH
17c2e3b87e Rename Template (#12649)
To chatbot feedback. Update import
2023-10-31 09:15:30 -07:00
Erick Friis
7f6e751a3d template updates (#12646) 2023-10-31 09:13:58 -07:00
Leonid Kuligin
a53cac4508 added template to use Vertex Vector Search for q&a (#12622)
added template to use Vertex Vector Search for q&a
2023-10-31 08:49:24 -07:00
Lance Martin
944cb552bb Minor updates to READMEs (#12642) 2023-10-31 08:34:46 -07:00
William FH
88f0f1e73b Conversational Feedback (#12590)
Context in the README.

Show how score chat responses based on a followup from the user and then
log that as feedback in LangSmith
2023-10-31 08:34:17 -07:00
Predrag Gruevski
f94e24dfd7 Install and use ruff format instead of black for code formatting. (#12585)
Best to review one commit at a time, since two of the commits are 100%
autogenerated changes from running `ruff format`:
- Install and use `ruff format` instead of black for code formatting.
- Output of `ruff format .` in the `langchain` package.
- Use `ruff format` in experimental package.
- Format changes in experimental package by `ruff format`.
- Manual formatting fixes to make `ruff .` pass.
2023-10-31 10:53:12 -04:00
William FH
bfd719f9d8 bind_functions convenience method (#12518)
I always take 20-30 seconds to re-discover where the
`convert_to_openai_function` wrapper lives in our codebase. Chat
langchain [has no
clue](https://smith.langchain.com/public/3989d687-18c7-4108-958e-96e88803da86/r)
what to do either. There's the older `create_openai_fn_chain` , but we
haven't been recommending it in LCEL. The example we show in the
[cookbook](https://python.langchain.com/docs/expression_language/how_to/binding#attaching-openai-functions)
is really verbose.


General function calling should be as simple as possible to do, so this
seems a bit more ergonomic to me (feel free to disagree). Another option
would be to directly coerce directly in the class's init (or when
calling invoke), if provided. I'm not 100% set against that. That
approach may be too easy but not simple. This PR feels like a decent
compromise between simple and easy.

```
from enum import Enum
from typing import Optional

from pydantic import BaseModel, Field


class Category(str, Enum):
    """The category of the issue."""

    bug = "bug"
    nit = "nit"
    improvement = "improvement"
    other = "other"


class IssueClassification(BaseModel):
    """Classify an issue."""

    category: Category
    other_description: Optional[str] = Field(
        description="If classified as 'other', the suggested other category"
    )
    

from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI().bind_functions([IssueClassification])
llm.invoke("This PR adds a convenience wrapper to the bind argument")

# AIMessage(content='', additional_kwargs={'function_call': {'name': 'IssueClassification', 'arguments': '{\n  "category": "improvement"\n}'}})
```
2023-10-31 07:15:37 -07:00
Nuno Campos
3143324984 Improve Runnable type inference for input_schemas (#12630)
- Prefer lambda type annotations over inferred dict schema
- For sequences that start with RunnableAssign infer seq input type as
"input type of 2nd item in sequence - output type of runnable assign"
2023-10-31 13:22:54 +00:00
Nuno Campos
2f563cee20 Add Runnable.with_listeners() (#12549)
- This binds start/end/error listeners to a runnable, which will be
called with the Run object
2023-10-31 11:04:51 +00:00
Bagatur
bcc62d63be bump 327 (#12623) 2023-10-31 02:18:08 -07:00
Erick Friis
a1fae1fddd Readme rewrite (#12615)
Co-authored-by: Lance Martin <lance@langchain.dev>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-10-31 00:06:02 -07:00
Ankur Singh
00766c9f31 Improves the description of the installation command (#12354)
- **Description:**

 Before: 
`
To install modules needed for the common LLM providers, run:
`

After:
`
To install modules needed for the common LLM providers, run the
following command. Please bear in mind that this command is exclusively
compatible with the `bash` shell:
`


> This is required for the user so that the user will know if this
command is compatible with `zsh` or not.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 18:56:48 -07:00
Yujie Qian
1dbb77d7db VoyageEmbeddings (#12608)
- **Description:** Integrate VoyageEmbeddings into LangChain, with tests
and docs
  - **Issue:** N/A
  - **Dependencies:** N/A
  - **Tag maintainer:** N/A
  - **Twitter handle:** @Voyage_AI_

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 18:37:43 -07:00
chocolate4
92bf40a921 Add a new vector store hippo for langchain #11763 (#12412)
#11763

---------

Co-authored-by: TranswarpHippo <hippo.0.assistant@gmail.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 18:35:23 -07:00
Karthik Raja A
342d6c7ab6 Multi on client toolkit (#12392)
Replace this entire comment with:
-Add MultiOn close function and update key value and add async
functionality
- solved the key value TabId not found.. (updated to use latest key
value)
  
@hwchase17
2023-10-30 18:34:56 -07:00
Prabin Nepal
b109cb031b SecretStr for fireworks api (#12475)
- **Description:** This pull request removes secrets present in raw
format,
- **Issue:** Fireworks api key was exposed when printing out the
langchain object
[#12165](https://github.com/langchain-ai/langchain/issues/12165)
 - **Maintainer:** @eyurtsev

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 18:17:53 -07:00
Harrison Chase
f35a65124a improve agent templates (#12528)
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-10-30 18:15:13 -07:00
Harrison Chase
75bb28afd8 Harrison/pii chatbot (#12523)
the pii detection in the template is pretty basic, will need to be
customized per use case

the chain it "protects" can be swapped out for any chain
2023-10-30 18:13:12 -07:00
Harrison Chase
a32c236c64 bump cli to 009 (#12611) 2023-10-30 18:12:08 -07:00
Erika Cardenas
b97b9eda21 Hybrid Search Weaviate Template (#12606)
- **Description:** This template covers hybrid search in Weaviate
  - **Dependencies:** No
  - **Twitter handle:** @ecardenas300

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-10-30 18:10:48 -07:00
Martin Schade
0c7f1d8b21 Textract linearizer (#12446)
**Description:** Textract PDF Loader generating linearized output,
meaning it will replicate the structure of the source document as close
as possible based on the features passed into the call (e. g. LAYOUT,
FORMS, TABLES). With LAYOUT reading order for multi-column documents or
identification of lists and figures is supported and with TABLES it will
generate the table structure as well. FORMS will indicate "key: value"
with columms.
  - **Issue:** the issue fixes #12068 
- **Dependencies:** amazon-textract-textractor is added, which provides
the linearization
  - **Tag maintainer:** @3coins 

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 18:02:10 -07:00
Harrison Chase
a7d5e0ce8a add guardrails profanity (#12609) 2023-10-30 17:01:23 -07:00
Erick Friis
e933212a3d run poetry build in working dir (#12610)
Was failing because was trying to build from root:
https://github.com/langchain-ai/langchain/actions/runs/6700033981/job/18205251365
2023-10-30 16:58:34 -07:00
Erick Friis
f39246bd7e cli should pull instead of delete+clone (#12607)
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-10-30 16:44:09 -07:00
Harrison Chase
8b5e879171 add a template for the package readme (#12499)
Co-authored-by: Erick Friis <erick@langchain.dev>
2023-10-30 16:39:39 -07:00
Bagatur
9bedda50f2 Bagatur/lakefs loader2 (#12524)
Co-authored-by: Jonathan Rosenberg <96974219+Jonathan-Rosenberg@users.noreply.github.com>
2023-10-30 16:30:27 -07:00
Brian McBrayer
3243dcc83e Fix very small typo (#12603)
- **Description:** this is the world's smallest typo change of a typo I
saw while reading the docs
2023-10-30 16:30:18 -07:00
Ackermann Yuriy
99b69fe607 Fixed missing optional tags. Added default key value for Ollama (#12599)
Added missing Optional typings. Added default values for Ollama optional
keys.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 16:30:10 -07:00
Lance Martin
f6f3ca12e7 Codebase RAG fireworks (#12597) 2023-10-30 16:21:56 -07:00
Harrison Chase
481bf6fae6 hosting note (#12589) 2023-10-30 15:31:31 -07:00
David Duong
b5c17ff188 Force List[Tuple[str,str]] to chat history widget (#12530)
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 15:19:32 -07:00
David Duong
d39b4b61b6 Batch apply poetry lock --no-update for all templates (#12531)
Ran the following bash script for all templates

```bash
#!/bin/bash

set -e
current_dir="$(pwd)"
for directory in */; do
    if [ -d "$directory" ]; then
        (cd "$directory" && poetry lock --no-update)
    fi
done

cd "$current_dir"
```

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 15:18:53 -07:00
Kenzie Mihardja
e914283cf9 add docs to min_chunk_size (#12537)
Minor addition to documentation to elaborate on min_chunk_size.

Co-authored-by: Kenzie Mihardja <kenzie@docugami.com>
2023-10-30 15:13:52 -07:00
Bagatur
016813d189 factor out to_secret (#12593) 2023-10-30 15:10:25 -07:00
hsuyuming
630ae24b28 implement get_num_tokens to use google's count_tokens function (#10565)
can get the correct token count instead of using gpt-2 model

**Description:** 
Implement get_num_tokens within VertexLLM to use google's count_tokens
function.
(https://cloud.google.com/vertex-ai/docs/generative-ai/get-token-count).
So we don't need to download gpt-2 model from huggingface, also when we
do the mapreduce chain we can get correct token count.

**Tag maintainer:** 
@lkuligin 
**Twitter handle:** 
My twitter: @abehsu1992626

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 15:10:05 -07:00
Pham Vu Thai Minh
33e77a1007 Async support for FAISS (#11333)
Following this tutoral about using OpenAI Embeddings with FAISS

https://python.langchain.com/docs/integrations/vectorstores/faiss

```python
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.document_loaders import TextLoader
from langchain.document_loaders import TextLoader

loader = TextLoader("../../../extras/modules/state_of_the_union.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings()
```

This works fine

```python
db = FAISS.from_documents(docs, embeddings)
query = "What did the president say about Ketanji Brown Jackson"
docs = db.similarity_search(query)
```

But the async version is not

```python
db = await FAISS.afrom_documents(docs, embeddings)  # NotImplementedError
query = "What did the president say about Ketanji Brown Jackson"

docs = await db.asimilarity_search(query) # this will use await asyncio.get_event_loop().run_in_executor under the hood and will not call OpenAIEmbeddings.aembed_query but call OpenAIEmbeddings.embed_query
```

So this PR add async/await supports for FAISS

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-10-30 15:08:53 -07:00
Lance Martin
26f0ca222d RAG template for MongoDB Atlas Vector Search (#12526) 2023-10-30 14:31:34 -07:00
Jeff Zhuo
13b89815a3 Issue: fix the issue #11648 init minimax llm (#12554)
e https://github.com/langchain-ai/langchain/issues/11648 Minimax
llm failed to initialize

The idea of this fix is
https://github.com/langchain-ai/langchain/issues/10917#issuecomment-1765606725

do not use  underscore in python model class

---------

Co-authored-by: zhuojianming@cmcm.com <zhuojianming@cmcm.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 14:30:17 -07:00
Florian Valeye
bfb27324cb [Matching Engine] Update the Matching Engine to include the distance and filters (#12555)
Hello 👋,

This Pull Request adds more capability to the
[MatchingEngine](https://api.python.langchain.com/en/latest/vectorstores/langchain.vectorstores.matching_engine.MatchingEngine.html)
vectorstore of GCP. It includes the
`similarity_search_by_vector_with_relevance_scores` function and also
[filters](https://cloud.google.com/vertex-ai/docs/vector-search/filtering)
to `filter` the namespaces when retrieving the results.

- **Description:** Add
[filter](https://cloud.google.com/python/docs/reference/aiplatform/latest/google.cloud.aiplatform.MatchingEngineIndexEndpoint#google_cloud_aiplatform_MatchingEngineIndexEndpoint_find_neighbors)
in `similarity_search` and add
`similarity_search_by_vector_with_relevance_scores` method
  - **Dependencies:** None
  - **Tag maintainer:** Unknown

Thank you!

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 14:12:59 -07:00
Predrag Gruevski
3c5c384f1a Test-publish to test PyPI and separate jobs to limit permissions. (#12578)
Before making a new `langchain` release, we want to test that everything
works as expected. This PR lets us publish `langchain` to test PyPI,
then install it from there and run checks to ensure everything works
normally before publishing it "for real".

It also takes the opportunity to refactor the build process, splitting
up the build, release-creation, and PyPI upload steps into separate jobs
that do not share their elevated permissions with each other.
2023-10-30 17:10:14 -04:00
Harrison Chase
1d51363e49 change project template (#12493) 2023-10-30 14:06:30 -07:00
Holt Skinner
e53b9ccd70 feat: Add Google Cloud Text-to-Speech Tool (#12572)
- Add Tool for [Google Cloud
Text-to-Speech](https://cloud.google.com/text-to-speech)
- Follows similar structure to [Eleven Labs
Text2Speech](https://python.langchain.com/docs/integrations/tools/eleven_labs_tts)

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 14:05:39 -07:00
Bagatur
1f2c672d4a add routing by embedding doc (#12580) 2023-10-30 13:03:16 -07:00
William FH
199630ff93 Replace You with DDG in xml agent (#12504)
You requires an email to get an API key which IMO is too much friction.
Duckduck go is free and easy to install.
2023-10-30 12:51:00 -07:00
Adilkhan Sarsen
6e702b9c36 Deep memory support in LangChain (#12268)
- Description: adding support to Activeloop's DeepMemory feature that
boosts recall up to 25%. Added Jupyter notebook showcasing the feature
and also made index params explicit.
- Twitter handle: will really appreciate if we could announce this on
twitter.

---------

Co-authored-by: adolkhan <adilkhan.sarsen@alumni.nu.edu.kz>
2023-10-30 12:16:14 -07:00
Lance Martin
c57945e0a8 Formatting on ntbks (#12576) 2023-10-30 11:32:31 -07:00
Lance Martin
08103e6d48 Minor template cleaning (#12573) 2023-10-30 11:27:44 -07:00
billytrend-cohere
b1e3843931 Add client_name="langchain" to Cohere usage (#11328)
Hey, we're looking to invest more in adding cohere integrations to
langchain so would love to get more of an idea for how it's used.
Hopefully this pr is acceptable. This week I'm also going to be looking
into adding our new [retrieval augmented generation
product](https://txt.cohere.com/chat-with-rag/) to langchain.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-30 11:20:55 -07:00
Bagatur
37aec1e050 bump 326 (#12569) 2023-10-30 10:11:17 -07:00
Eugene Yurtsev
1b1a2d5740 Image Caption accepts bytes for images (#12561)
Accept bytes for images in image caption

---------

Co-authored-by: webcoderz <19884161+webcoderz@users.noreply.github.com>
2023-10-30 12:29:54 -04:00
Nuno Campos
7897483819 Allow astream_log to be used inside atrace_as_chain_group (#12558)
<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-10-30 15:55:16 +00:00
Tomaz Bratanic
8e88ba16a8 Update neo4j template readmes (#12540) 2023-10-30 07:57:53 -07:00
Bagatur
b2138508cb google translate nb formatting (#12534) 2023-10-29 21:27:04 -07:00
Holt Skinner
e05bb938de Merge pull request #12433
* feat: Add Google Cloud Translation document transformer

* Merge branch 'langchain-ai:master' into google-translate

* Add documentation for Google Translate Document Transformer

* Fix line length error

* Merge branch 'master' into google-translate

* Merge branch 'google-translate' of https://github.com/holtskinner/lan…

* Addressed code review comments

* Merge branch 'master' into google-translate

* Merge branch 'google-translate' of https://github.com/holtskinner/lan…

* Removed extra variable

* Merge branch 'google-translate' of https://github.com/holtskinner/lan…

* Merge branch 'master' into google-translate

* Merge branch 'google-translate' of https://github.com/holtskinner/lan…

* Removed extra import
2023-10-29 21:22:36 -04:00
Samad Koita
d1fdcd4fcb Masking of API Key for GooseAI LLM (#12496)
Description: Add masking of API Key for GooseAI LLM when printed.
Issue: https://github.com/langchain-ai/langchain/issues/12165
Dependencies: None
Tag maintainer: @eyurtsev

---------

Co-authored-by: Samad Koita <>
2023-10-29 21:21:33 -04:00
Andrew Zhou
64c4a698a8 More comprehensive readthedocs document loader (#12382)
## **Description:**
When building our own readthedocs.io scraper, we noticed a couple
interesting things:

1. Text lines with a lot of nested <span> tags would give unclean text
with a bunch of newlines. For example, for [Langchain's
documentation](https://api.python.langchain.com/en/latest/document_loaders/langchain.document_loaders.readthedocs.ReadTheDocsLoader.html#langchain.document_loaders.readthedocs.ReadTheDocsLoader),
a single line is represented in a complicated nested HTML structure, and
the naive `soup.get_text()` call currently being made will create a
newline for each nested HTML element. Therefore, the document loader
would give a messy, newline-separated blob of text. This would be true
in a lot of cases.

<img width="945" alt="Screenshot 2023-10-26 at 6 15 39 PM"
src="https://github.com/langchain-ai/langchain/assets/44193474/eca85d1f-d2bf-4487-a18a-e1e732fadf19">
<img width="1031" alt="Screenshot 2023-10-26 at 6 16 00 PM"
src="https://github.com/langchain-ai/langchain/assets/44193474/035938a0-9892-4f6a-83cd-0d7b409b00a3">

Additionally, content from iframes, code from scripts, css from styles,
etc. will be gotten if it's a subclass of the selector (which happens
more often than you'd think). For example, [this
page](https://pydeck.gl/gallery/contour_layer.html#) will scrape 1.5
million characters of content that looks like this:

<img width="1372" alt="Screenshot 2023-10-26 at 6 32 55 PM"
src="https://github.com/langchain-ai/langchain/assets/44193474/dbd89e39-9478-4a18-9e84-f0eb91954eac">

Therefore, I wrote a recursive _get_clean_text(soup) class function that
1. skips all irrelevant elements, and 2. only adds newlines when
necessary.

2. Index pages (like [this
one](https://api.python.langchain.com/en/latest/api_reference.html))
would be loaded, chunked, and eventually embedded. This is really bad
not just because the user will be embedding irrelevant information - but
because index pages are very likely to show up in retrieved content,
making retrieval less effective (in our tests). Therefore, I added a
bool parameter `exclude_index_pages` defaulted to False (which is the
current behavior — although I'd petition to default this to True) that
will skip all pages where links take up 50%+ of the page. Through manual
testing, this seems to be the best threshold.



## Other Information:
  - **Issue:** n/a
  - **Dependencies:** n/a
  - **Tag maintainer:** n/a
  - **Twitter handle:** @andrewthezhou

---------

Co-authored-by: Andrew Zhou <andrew@heykona.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-29 16:26:53 -07:00
Peter Vandenabeele
3468c038ba Add unit tests for document_transformers/beautiful_soup_transformer.py (#12520)
- **Description:**
* Add unit tests for document_transformers/beautiful_soup_transformer.py
* Basic functionality is tested (extract tags, remove tags, drop lines)
    * add a FIXME comment about the order of tags that is not preserved
      (and a passing test, but with the expected tags now out-of-order)
  - **Issue:** None
  - **Dependencies:** None
  - **Tag maintainer:** @rlancemartin 
  - **Twitter handle:** `peter_v`

Please make sure your PR is passing linting and testing before
submitting.

=> OK: I ran `make format`, `make test` (passing after install of
beautifulsoup4) and `make lint`.
2023-10-29 16:24:47 -07:00
Bagatur
d31d705407 update contributing (#12532) 2023-10-29 16:22:18 -07:00
Bagatur
0b4b9e61fc Bagatur/fix doc ci (#12529) 2023-10-29 16:15:18 -07:00
Bagatur
2424fff3f1 notebook fmt (#12498) 2023-10-29 15:50:09 -07:00
Harrison Chase
56cc5b847c Harrison/add descriptions (#12522) 2023-10-29 15:11:37 -07:00
Anirudh Gautam
b257e6a4e8 Mask API key for AI21 LLM (#12418)
- **Description:** Added masking of the API Key for AI21 LLM when
printed and improved the docstring for AI21 LLM.
- Updated the AI21 LLM to utilize SecretStr from pydantic to securely
manage API key.
- Made improvements in the docstring of AI21 LLM. It now mentions that
the API key can also be passed as a named parameter to the constructor.
    - Added unit tests.
  - **Issue:** #12165 
  - **Tag maintainer:** @eyurtsev

---------

Co-authored-by: Anirudh Gautam <anirudh@Anirudhs-Mac-mini.local>
2023-10-29 14:53:41 -07:00
Nico Baier
35d726dc15 docs(prompt_templates): fix typo in prompt template (#12497)
- **Description:** Fixes a small typo in the [Prompt template
document](https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/)
  - **Dependencies:** none
2023-10-29 14:52:37 -07:00
silvhua
9dead1034c _dalle_image_url returns list of urls if n>1 (#11800)
- **Description:** Updated the `_dalle_image_url` method to return a
list of URLs if self.n>1,
  - **Issue:** #10691,
  - **Dependencies:** unsure,
  - **Tag maintainer:** @eyurtsev,
  - **Twitter handle:** @silvhua
---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-29 14:23:23 -07:00
Bagatur
1815ea2fdb OpenAI runnable constructor (#12455) 2023-10-29 13:40:30 -07:00
William FH
a830b809f3 Patch forward ref bug (#12508)
Currently this gives a bug:
```
from langchain.schema.runnable import RunnableLambda

bound = RunnableLambda(lambda x: x).with_config({"callbacks": []})

# ConfigError: field "callbacks" not yet prepared so type is still a ForwardRef, you might need to call RunnableConfig.update_forward_refs().
```

Rather than deal with cyclic imports and extra load time, etc., I think
it makes sense to just have a separate Callbacks definition here that is
a relaxed typehint.
2023-10-29 00:53:01 -07:00
William FH
36204c2baf Evaluation Callback Multi Response (#12505)
1. Allow run evaluators to return {"results": [list of evaluation
results]} in the evaluator callback.
2. Allows run evaluators to pick the target run ID to provide feedback
to

(1) means you could do something like a function call that populates a
full rubric in one go (not sure how reliable that is in general though)
rather than splitting off into separate LLM calls - cheaper and less
code to write
(2) means you can provide feedback to runs on subsequent calls.
Immediate use case is if you wanted to add an evaluator to a chat bot
and assign to assign to previous conversation turns


have a corresponding one in the SDK
2023-10-28 23:18:29 -07:00
Harrison Chase
9e0ae56287 various templates improvements (#12500) 2023-10-28 22:13:22 -07:00
Harrison Chase
d85d4d7822 add cookbook for selectins llms based on context length (#12486) 2023-10-28 21:50:14 -07:00
Harrison Chase
0660c06cf1 add gha for cli (#12492) 2023-10-28 21:49:28 -07:00
0xC9
79cf01366e Update tool.py (#12472)
In the GoogleSerperResults class, the name field is defined as
'google_serrper_results_json'. This looks like a typo, and perhaps
should be 'google_serper_results_json'.

<!-- Thank you for contributing to LangChain!

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,
- **Tag maintainer:** for a quicker response, tag the relevant
maintainer (see below),
- **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` to check this
locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc:

https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md

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/extras`
directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
2023-10-28 21:49:01 -07:00
Harrison Chase
61f5ea4b5e Sphinxbio nls/add plate chain template (#12502)
Co-authored-by: Nicholas Larus-Stone <7347808+nlarusstone@users.noreply.github.com>
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-10-28 21:48:17 -07:00
Harrison Chase
221134d239 Harrison/quick start (#12491)
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-10-28 16:26:52 -07:00
Bagatur
e130680d74 Bagatur/self query doc update (#12461) 2023-10-28 14:37:14 -07:00
Piyush Jain
689853902e Added a rag template for Kendra (#12470)
## Description
Adds a rag template for Amazon Kendra with Bedrock.

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-10-28 08:58:28 -07:00
Harrison Chase
eb903e211c bump to 36 (#12487) 2023-10-28 08:51:23 -07:00
Tyler Hutcherson
4209457bdc Redis langserve template (#12443)
Add Redis langserve template! Eventually will add semantic caching to
this too. But I was struggling to get that to work for some reason with
the LCEL implementation here.

- **Description:** Introduces the Redis LangServe template. A simple RAG
based app built on top of Redis that allows you to chat with company's
public financial data (Edgar 10k filings)
  - **Issue:** None
- **Dependencies:** The template contains the poetry project
requirements to run this template
  - **Tag maintainer:** @baskaryan @Spartee 
  - **Twitter handle:** @tchutch94

**Note**: this requires the commit here that deletes the
`_aget_relevant_documents()` method from the Redis retriever class that
wasn't implemented. That was breaking the langserve app.

---------

Co-authored-by: Sam Partee <sam.partee@redis.com>
2023-10-28 08:31:12 -07:00
Erick Friis
9adaa78c65 cli improvements (#12465)
Features
- add multiple repos by their branch/repo
- generate `pip install` commands and `add_route()` code
![Screenshot 2023-10-27 at 4 49 52
PM](https://github.com/langchain-ai/langchain/assets/9557659/3aec4cbb-3f67-4f04-8370-5b54ea983b2a)

Optimizations:
- group installs by repo/branch to avoid duplicate cloning
2023-10-28 08:25:31 -07:00
Piyush Jain
5545de0466 Updated the Bedrock rag template (#12462)
Updates the bedrock rag template.
- Removes pinecone and replaces with FAISS as the vector store
- Fixes the environment variables, setting defaults
- Adds a `main.py` test file quick sanity testing
- Updates README.md with correct instructions
2023-10-27 17:02:28 -07:00
Lance Martin
5c2243ee91 Update llama.cpp and Ollama templates (#12466) 2023-10-27 16:54:54 -07:00
Lance Martin
f10c17c6a4 Update SQL templates (#12464) 2023-10-27 16:34:37 -07:00
Lance Martin
a476147189 Add Weaviate RAG template (#12460) 2023-10-27 15:19:34 -07:00
Adam Law
df4960a6d8 add reranking to azuresearch (#12454)
-**Description** Adds returning the reranking score when using semantic
search
-**Issue:* #12317

---------

Co-authored-by: Adam Law <adamlaw@microsoft.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-27 14:14:09 -07:00
dependabot[bot]
389459af8f Bump @babel/traverse from 7.22.8 to 7.23.2 in /docs (#12453)
Bumps
[@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse)
from 7.22.8 to 7.23.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/babel/babel/releases"><code>@​babel/traverse</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v7.23.2 (2023-10-11)</h2>
<p><strong>NOTE</strong>: This release also re-publishes
<code>@babel/core</code>, even if it does not appear in the linked
release commit.</p>
<p>Thanks <a
href="https://github.com/jimmydief"><code>@​jimmydief</code></a> for
your first PR!</p>
<h4>🐛 Bug Fix</h4>
<ul>
<li><code>babel-traverse</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16033">#16033</a>
Only evaluate own String/Number/Math methods (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-preset-typescript</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16022">#16022</a>
Rewrite <code>.tsx</code> extension when using
<code>rewriteImportExtensions</code> (<a
href="https://github.com/jimmydief"><code>@​jimmydief</code></a>)</li>
</ul>
</li>
<li><code>babel-helpers</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16017">#16017</a>
Fix: fallback to typeof when toString is applied to incompatible object
(<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-helpers</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-runtime-corejs2</code>, <code>babel-runtime-corejs3</code>,
<code>babel-runtime</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16025">#16025</a>
Avoid override mistake in namespace imports (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
</ul>
<h4>Committers: 5</h4>
<ul>
<li>Babel Bot (<a
href="https://github.com/babel-bot"><code>@​babel-bot</code></a>)</li>
<li>Huáng Jùnliàng (<a
href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
<li>James Diefenderfer (<a
href="https://github.com/jimmydief"><code>@​jimmydief</code></a>)</li>
<li>Nicolò Ribaudo (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
<li><a
href="https://github.com/liuxingbaoyu"><code>@​liuxingbaoyu</code></a></li>
</ul>
<h2>v7.23.1 (2023-09-25)</h2>
<p>Re-publishing <code>@babel/helpers</code> due to a publishing error
in 7.23.0.</p>
<h2>v7.23.0 (2023-09-25)</h2>
<p>Thanks <a
href="https://github.com/lorenzoferre"><code>@​lorenzoferre</code></a>
and <a
href="https://github.com/RajShukla1"><code>@​RajShukla1</code></a> for
your first PRs!</p>
<h4>🚀 New Feature</h4>
<ul>
<li><code>babel-plugin-proposal-import-wasm-source</code>,
<code>babel-plugin-syntax-import-source</code>,
<code>babel-plugin-transform-dynamic-import</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15870">#15870</a>
Support transforming <code>import source</code> for wasm (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-helper-module-transforms</code>,
<code>babel-helpers</code>,
<code>babel-plugin-proposal-import-defer</code>,
<code>babel-plugin-syntax-import-defer</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-runtime-corejs2</code>, <code>babel-runtime-corejs3</code>,
<code>babel-runtime</code>, <code>babel-standalone</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15878">#15878</a>
Implement <code>import defer</code> proposal transform support (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-generator</code>, <code>babel-parser</code>,
<code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15845">#15845</a>
Implement <code>import defer</code> parsing support (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
<li><a
href="https://redirect.github.com/babel/babel/pull/15829">#15829</a> Add
parsing support for the &quot;source phase imports&quot; proposal (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-generator</code>,
<code>babel-helper-module-transforms</code>, <code>babel-parser</code>,
<code>babel-plugin-transform-dynamic-import</code>,
<code>babel-plugin-transform-modules-amd</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-plugin-transform-modules-systemjs</code>,
<code>babel-traverse</code>, <code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15682">#15682</a> Add
<code>createImportExpressions</code> parser option (<a
href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-standalone</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15671">#15671</a>
Pass through nonce to the transformed script element (<a
href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-helper-function-name</code>,
<code>babel-helper-member-expression-to-functions</code>,
<code>babel-helpers</code>, <code>babel-parser</code>,
<code>babel-plugin-proposal-destructuring-private</code>,
<code>babel-plugin-proposal-optional-chaining-assign</code>,
<code>babel-plugin-syntax-optional-chaining-assign</code>,
<code>babel-plugin-transform-destructuring</code>,
<code>babel-plugin-transform-optional-chaining</code>,
<code>babel-runtime-corejs2</code>, <code>babel-runtime-corejs3</code>,
<code>babel-runtime</code>, <code>babel-standalone</code>,
<code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15751">#15751</a> Add
support for optional chain in assignments (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-helpers</code>,
<code>babel-plugin-proposal-decorators</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15895">#15895</a>
Implement the &quot;decorator metadata&quot; proposal (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-traverse</code>, <code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15893">#15893</a> Add
<code>t.buildUndefinedNode</code> (<a
href="https://github.com/liuxingbaoyu"><code>@​liuxingbaoyu</code></a>)</li>
</ul>
</li>
<li><code>babel-preset-typescript</code></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/babel/babel/blob/main/CHANGELOG.md"><code>@​babel/traverse</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>v7.23.2 (2023-10-11)</h2>
<h4>🐛 Bug Fix</h4>
<ul>
<li><code>babel-traverse</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16033">#16033</a>
Only evaluate own String/Number/Math methods (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-preset-typescript</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16022">#16022</a>
Rewrite <code>.tsx</code> extension when using
<code>rewriteImportExtensions</code> (<a
href="https://github.com/jimmydief"><code>@​jimmydief</code></a>)</li>
</ul>
</li>
<li><code>babel-helpers</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16017">#16017</a>
Fix: fallback to typeof when toString is applied to incompatible object
(<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-helpers</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-runtime-corejs2</code>, <code>babel-runtime-corejs3</code>,
<code>babel-runtime</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/16025">#16025</a>
Avoid override mistake in namespace imports (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
</ul>
<h2>v7.23.0 (2023-09-25)</h2>
<h4>🚀 New Feature</h4>
<ul>
<li><code>babel-plugin-proposal-import-wasm-source</code>,
<code>babel-plugin-syntax-import-source</code>,
<code>babel-plugin-transform-dynamic-import</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15870">#15870</a>
Support transforming <code>import source</code> for wasm (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-helper-module-transforms</code>,
<code>babel-helpers</code>,
<code>babel-plugin-proposal-import-defer</code>,
<code>babel-plugin-syntax-import-defer</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-runtime-corejs2</code>, <code>babel-runtime-corejs3</code>,
<code>babel-runtime</code>, <code>babel-standalone</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15878">#15878</a>
Implement <code>import defer</code> proposal transform support (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-generator</code>, <code>babel-parser</code>,
<code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15845">#15845</a>
Implement <code>import defer</code> parsing support (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
<li><a
href="https://redirect.github.com/babel/babel/pull/15829">#15829</a> Add
parsing support for the &quot;source phase imports&quot; proposal (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-generator</code>,
<code>babel-helper-module-transforms</code>, <code>babel-parser</code>,
<code>babel-plugin-transform-dynamic-import</code>,
<code>babel-plugin-transform-modules-amd</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-plugin-transform-modules-systemjs</code>,
<code>babel-traverse</code>, <code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15682">#15682</a> Add
<code>createImportExpressions</code> parser option (<a
href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-standalone</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15671">#15671</a>
Pass through nonce to the transformed script element (<a
href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-helper-function-name</code>,
<code>babel-helper-member-expression-to-functions</code>,
<code>babel-helpers</code>, <code>babel-parser</code>,
<code>babel-plugin-proposal-destructuring-private</code>,
<code>babel-plugin-proposal-optional-chaining-assign</code>,
<code>babel-plugin-syntax-optional-chaining-assign</code>,
<code>babel-plugin-transform-destructuring</code>,
<code>babel-plugin-transform-optional-chaining</code>,
<code>babel-runtime-corejs2</code>, <code>babel-runtime-corejs3</code>,
<code>babel-runtime</code>, <code>babel-standalone</code>,
<code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15751">#15751</a> Add
support for optional chain in assignments (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-helpers</code>,
<code>babel-plugin-proposal-decorators</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15895">#15895</a>
Implement the &quot;decorator metadata&quot; proposal (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-traverse</code>, <code>babel-types</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15893">#15893</a> Add
<code>t.buildUndefinedNode</code> (<a
href="https://github.com/liuxingbaoyu"><code>@​liuxingbaoyu</code></a>)</li>
</ul>
</li>
<li><code>babel-preset-typescript</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15913">#15913</a> Add
<code>rewriteImportExtensions</code> option to TS preset (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15896">#15896</a>
Allow TS tuples to have both labeled and unlabeled elements (<a
href="https://github.com/yukukotani"><code>@​yukukotani</code></a>)</li>
</ul>
</li>
</ul>
<h4>🐛 Bug Fix</h4>
<ul>
<li><code>babel-plugin-transform-block-scoping</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15962">#15962</a>
fix: <code>transform-block-scoping</code> captures the variables of the
method in the loop (<a
href="https://github.com/liuxingbaoyu"><code>@​liuxingbaoyu</code></a>)</li>
</ul>
</li>
</ul>
<h4>💅 Polish</h4>
<ul>
<li><code>babel-traverse</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15797">#15797</a>
Expand evaluation of global built-ins in <code>@babel/traverse</code>
(<a
href="https://github.com/lorenzoferre"><code>@​lorenzoferre</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-proposal-explicit-resource-management</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15985">#15985</a>
Improve source maps for blocks with <code>using</code> declarations (<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
</ul>
<h4>🔬 Output optimization</h4>
<ul>
<li><code>babel-core</code>,
<code>babel-helper-module-transforms</code>,
<code>babel-plugin-transform-async-to-generator</code>,
<code>babel-plugin-transform-classes</code>,
<code>babel-plugin-transform-dynamic-import</code>,
<code>babel-plugin-transform-function-name</code>,
<code>babel-plugin-transform-modules-amd</code>,
<code>babel-plugin-transform-modules-commonjs</code>,
<code>babel-plugin-transform-modules-umd</code>,
<code>babel-plugin-transform-parameters</code>,
<code>babel-plugin-transform-react-constant-elements</code>,
<code>babel-plugin-transform-react-inline-elements</code>,
<code>babel-plugin-transform-runtime</code>,
<code>babel-plugin-transform-typescript</code>,
<code>babel-preset-env</code>
<ul>
<li><a
href="https://redirect.github.com/babel/babel/pull/15984">#15984</a>
Inline <code>exports.XXX =</code> update in simple variable declarations
(<a
href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
</ul>
<h2>v7.22.20 (2023-09-16)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b4b9942a6c"><code>b4b9942</code></a>
v7.23.2</li>
<li><a
href="b13376b346"><code>b13376b</code></a>
Only evaluate own String/Number/Math methods (<a
href="https://github.com/babel/babel/tree/HEAD/packages/babel-traverse/issues/16033">#16033</a>)</li>
<li><a
href="ca58ec15cb"><code>ca58ec1</code></a>
v7.23.0</li>
<li><a
href="0f333dafcf"><code>0f333da</code></a>
Add <code>createImportExpressions</code> parser option (<a
href="https://github.com/babel/babel/tree/HEAD/packages/babel-traverse/issues/15682">#15682</a>)</li>
<li><a
href="3744545649"><code>3744545</code></a>
Fix linting</li>
<li><a
href="c7e6806e21"><code>c7e6806</code></a>
Add <code>t.buildUndefinedNode</code> (<a
href="https://github.com/babel/babel/tree/HEAD/packages/babel-traverse/issues/15893">#15893</a>)</li>
<li><a
href="38ee8b4dd6"><code>38ee8b4</code></a>
Expand evaluation of global built-ins in <code>@babel/traverse</code>
(<a
href="https://github.com/babel/babel/tree/HEAD/packages/babel-traverse/issues/15797">#15797</a>)</li>
<li><a
href="9f3dfd9021"><code>9f3dfd9</code></a>
v7.22.20</li>
<li><a
href="3ed28b29c1"><code>3ed28b2</code></a>
Fully support <code>||</code> and <code>&amp;&amp;</code> in
<code>pluginToggleBooleanFlag</code> (<a
href="https://github.com/babel/babel/tree/HEAD/packages/babel-traverse/issues/15961">#15961</a>)</li>
<li><a
href="77b0d73599"><code>77b0d73</code></a>
v7.22.19</li>
<li>Additional commits viewable in <a
href="https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@babel/traverse&package-manager=npm_and_yarn&previous-version=7.22.8&new-version=7.23.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langchain/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-27 14:13:58 -07:00
Eugene Yurtsev
60d009f75a Add security note to API chain (#12452)
Add security note
2023-10-27 17:09:42 -04:00
Matvey Arye
11505f95d3 Improve handling of empty queries for timescale vector (#12393)
**Description:** Improve handling of empty queries in timescale-vector.
For timescale-vector it is more efficient to get a None embedding when
the embedding has no semantic meaning. It allows timescale-vector to
perform more optimizations. Thus, when the query is empty, use a None
embedding.

 Also pass down constructor arguments to the timescale vector client.

---------

Co-authored-by: Bagatur <baskaryan@gmail.com>
2023-10-27 13:55:16 -07:00
Erick Friis
38cee5fae0 cli updates 2 (#12447)
- extras group
- readme
- another readme

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2023-10-27 13:37:03 -07:00
Lance Martin
3afa68e30e Update AWS Bedrock README.md (#12451) 2023-10-27 13:21:54 -07:00
Lance Martin
5c564e62e1 AWS Bedrock RAG template (#12450) 2023-10-27 13:15:54 -07:00
William FH
5d40e36c75 Trace if run tree set (#12444)
This code path is hit in the following case:
- Start in langchain code and manually provide a tracer
- Handoff to the traceable
- Hand back to langchain code.

Which happens for evaluating `@traceable` functions unfortunately
2023-10-27 12:29:18 -07:00
1199 changed files with 134038 additions and 31006 deletions

View File

@@ -17,13 +17,16 @@ For more info, check out the [GitHub documentation](https://docs.github.com/en/f
## VS Code Dev Containers
[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/langchain-ai/langchain)
Note: If you click this link you will open the main repo and not your local cloned repo, you can use this link and replace with your username and cloned repo name:
Note: If you click the link above you will open the main repo (langchain-ai/langchain) and not your local cloned repo. This is fine if you only want to run and test the library, but if you want to contribute you can use the link below and replace with your username and cloned repo name:
```
https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/<yourusername>/<yourclonedreponame>
```
Then you will have a local cloned repo where you can contribute and then create pull requests.
If you already have VS Code and Docker installed, you can use the button above to get started. This will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.
You can also follow these steps to open this repo in a container using the VS Code Dev Containers extension:
Alternatively you can also follow these steps to open this repo in a container using the VS Code Dev Containers extension:
1. If this is your first time using a development container, please ensure your system meets the pre-reqs (i.e. have Docker installed) in the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started).

View File

@@ -134,14 +134,21 @@ Run these locally before submitting a PR; the CI system will check also.
#### Code Formatting
Formatting for this project is done via a combination of [Black](https://black.readthedocs.io/en/stable/) and [ruff](https://docs.astral.sh/ruff/rules/).
Formatting for this project is done via [ruff](https://docs.astral.sh/ruff/rules/).
To run formatting for this project:
To run formatting for docs, cookbook and templates:
```bash
make format
```
To run formatting for a library, run the same command from the relevant library directory:
```bash
cd libs/{LIBRARY}
make format
```
Additionally, you can run the formatter only on the files that have been modified in your current branch as compared to the master branch using the format_diff command:
```bash
@@ -152,14 +159,21 @@ This is especially useful when you have made changes to a subset of the project
#### Linting
Linting for this project is done via a combination of [Black](https://black.readthedocs.io/en/stable/), [ruff](https://docs.astral.sh/ruff/rules/), and [mypy](http://mypy-lang.org/).
Linting for this project is done via a combination of [ruff](https://docs.astral.sh/ruff/rules/) and [mypy](http://mypy-lang.org/).
To run linting for this project:
To run linting for docs, cookbook and templates:
```bash
make lint
```
To run linting for a library, run the same command from the relevant library directory:
```bash
cd libs/{LIBRARY}
make lint
```
In addition, you can run the linter only on the files that have been modified in your current branch as compared to the master branch using the lint_diff command:
```bash
@@ -288,8 +302,8 @@ make api_docs_linkcheck
### Verify Documentation changes
After pushing documentation changes to the repository, you can preview and verify that the changes are
what you wanted by clicking the `View deployment` or `Visit Preview` buttons on the pull request `Conversation` page.
After pushing documentation changes to the repository, you can preview and verify that the changes are
what you wanted by clicking the `View deployment` or `Visit Preview` buttons on the pull request `Conversation` page.
This will take you to a preview of the documentation changes.
This preview is created by [Vercel](https://vercel.com/docs/getting-started-with-vercel).

View File

@@ -16,15 +16,12 @@ env:
POETRY_VERSION: "1.6.1"
WORKDIR: ${{ inputs.working-directory == '' && '.' || inputs.working-directory }}
# This env var allows us to get inline annotations when ruff has complaints.
RUFF_OUTPUT_FORMAT: github
jobs:
build:
runs-on: ubuntu-latest
env:
# This number is set "by eye": we want it to be big enough
# so that it's bigger than the number of commits in any reasonable PR,
# and also as small as possible since increasing the number makes
# the initial `git fetch` slower.
FETCH_DEPTH: 50
strategy:
matrix:
# Only lint on the min and max supported Python versions.
@@ -39,51 +36,6 @@ jobs:
- "3.11"
steps:
- uses: actions/checkout@v4
with:
# Fetch the last FETCH_DEPTH commits, so the mtime-changing script
# can accurately set the mtimes of files modified in the last FETCH_DEPTH commits.
fetch-depth: ${{ env.FETCH_DEPTH }}
- name: Restore workdir file mtimes to last-edited commit date
id: restore-mtimes
# This is needed to make black caching work.
# Black's cache uses file (mtime, size) to check whether a lookup is a cache hit.
# Without this command, files in the repo would have the current time as the modified time,
# since the previous action step just created them.
# This command resets the mtime to the last time the files were modified in git instead,
# which is a high-quality and stable representation of the last modification date.
run: |
# Important considerations:
# - These commands run at base of the repo, since we never `cd` to the `WORKDIR`.
# - We only want to alter mtimes for Python files, since that's all black checks.
# - We don't need to alter mtimes for directories, since black doesn't look at those.
# - We also only alter mtimes inside the `WORKDIR` since that's all we'll lint.
# - This should run before `poetry install`, because poetry's venv also contains
# Python files, and we don't want to alter their mtimes since they aren't linted.
# Ensure we fail on non-zero exits and on undefined variables.
# Also print executed commands, for easier debugging.
set -eux
# Restore the mtimes of Python files in the workdir based on git history.
.github/tools/git-restore-mtime --no-directories "$WORKDIR/**/*.py"
# Since CI only does a partial fetch (to `FETCH_DEPTH`) for efficiency,
# the local git repo doesn't have full history. There are probably files
# that were last modified in a commit *older than* the oldest fetched commit.
# After `git-restore-mtime`, such files have a mtime set to the oldest fetched commit.
#
# As new commits get added, that timestamp will keep moving forward.
# If left unchanged, this will make `black` think that the files were edited
# more recently than its cache suggests. Instead, we can set their mtime
# to a fixed date in the far past that won't change and won't cause cache misses in black.
#
# For all workdir Python files modified in or before the oldest few fetched commits,
# make their mtime be 2000-01-01 00:00:00.
OLDEST_COMMIT="$(git log --reverse '--pretty=format:%H' | head -1)"
OLDEST_COMMIT_TIME="$(git show -s '--format=%ai' "$OLDEST_COMMIT")"
find "$WORKDIR" -name '*.py' -type f -not -newermt "$OLDEST_COMMIT_TIME" -exec touch -c -m -t '200001010000' '{}' '+'
echo "oldest-commit=$OLDEST_COMMIT" >> "$GITHUB_OUTPUT"
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
@@ -120,25 +72,12 @@ jobs:
- name: Install langchain editable
working-directory: ${{ inputs.working-directory }}
if: ${{ inputs.working-directory != 'libs/langchain' }}
if: ${{ inputs.langchain-location }}
env:
LANGCHAIN_LOCATION: ${{ inputs.langchain-location || '../langchain'}}
LANGCHAIN_LOCATION: ${{ inputs.langchain-location }}
run: |
pip install -e "$LANGCHAIN_LOCATION"
- name: Restore black cache
uses: actions/cache@v3
env:
CACHE_BASE: black-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ inputs.working-directory }}-${{ hashFiles(format('{0}/poetry.lock', env.WORKDIR)) }}
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "1"
with:
path: |
${{ env.WORKDIR }}/.black_cache
key: ${{ env.CACHE_BASE }}-${{ steps.restore-mtimes.outputs.oldest-commit }}
restore-keys:
# If we can't find an exact match for our cache key, accept any with this prefix.
${{ env.CACHE_BASE }}-
- name: Get .mypy_cache to speed up mypy
uses: actions/cache@v3
env:
@@ -150,7 +89,5 @@ jobs:
- name: Analysing the code with our lint
working-directory: ${{ inputs.working-directory }}
env:
BLACK_CACHE_DIR: .black_cache
run: |
make lint

View File

@@ -9,13 +9,121 @@ on:
description: "From which folder this pipeline executes"
env:
PYTHON_VERSION: "3.10"
POETRY_VERSION: "1.6.1"
jobs:
if_release:
# Disallow publishing from branches that aren't `master`.
build:
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
outputs:
pkg-name: ${{ steps.check-version.outputs.pkg-name }}
version: ${{ steps.check-version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
# We want to keep this build stage *separate* from the release stage,
# so that there's no sharing of permissions between them.
# The release stage has trusted publishing and GitHub repo contents write access,
# and we want to keep the scope of that access limited just to the release job.
# Otherwise, a malicious `build` step (e.g. via a compromised dependency)
# could get access to our GitHub or PyPI credentials.
#
# Per the trusted publishing GitHub Action:
# > It is strongly advised to separate jobs for building [...]
# > from the publish job.
# https://github.com/pypa/gh-action-pypi-publish#non-goals
- name: Build project for distribution
run: poetry build
working-directory: ${{ inputs.working-directory }}
- name: Upload build
uses: actions/upload-artifact@v3
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Check Version
id: check-version
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
echo version="$(poetry version --short)" >> $GITHUB_OUTPUT
test-pypi-publish:
needs:
- build
uses:
./.github/workflows/_test_release.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
pre-release-checks:
needs:
- build
- test-pypi-publish
runs-on: ubuntu-latest
steps:
# We explicitly *don't* set up caching here. This ensures our tests are
# maximally sensitive to catching breakage.
#
# For example, here's a way that caching can cause a falsely-passing test:
# - Make the langchain package manifest no longer list a dependency package
# as a requirement. This means it won't be installed by `pip install`,
# and attempting to use it would cause a crash.
# - That dependency used to be required, so it may have been cached.
# When restoring the venv packages from cache, that dependency gets included.
# - Tests pass, because the dependency is present even though it wasn't specified.
# - The package is published, and it breaks on the missing dependency when
# used in the real world.
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Test published package
shell: bash
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
# Here we specify:
# - The test PyPI index as the *primary* index, meaning that it takes priority.
# - The regular PyPI index as an extra index, so that any dependencies that
# are not found on test PyPI can be resolved and installed anyway.
#
# Without the former, we might install the wrong langchain release.
# Without the latter, we might not be able to install langchain's dependencies.
#
# TODO: add more in-depth pre-publish tests after testing that importing works
run: |
pip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
"$PKG_NAME==$VERSION"
# Replace all dashes in the package name with underscores,
# since that's how Python imports packages with dashes in the name.
IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/_/g)"
python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))"
publish:
needs:
- build
- test-pypi-publish
- pre-release-checks
runs-on: ubuntu-latest
permissions:
# This permission is used for trusted publishing:
# https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
@@ -24,28 +132,65 @@ jobs:
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
id-token: write
# This permission is needed by `ncipollo/release-action` to create the GitHub release.
contents: write
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: "3.10"
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
- name: Build project for distribution
run: poetry build
- name: Check Version
id: check-version
run: |
echo version=$(poetry version --short) >> $GITHUB_OUTPUT
- uses: actions/download-artifact@v3
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
verbose: true
print-hash: true
mark-release:
needs:
- build
- test-pypi-publish
- pre-release-checks
- publish
runs-on: ubuntu-latest
permissions:
# This permission is needed by `ncipollo/release-action` to
# create the GitHub release.
contents: write
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
- uses: actions/download-artifact@v3
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Create Release
uses: ncipollo/release-action@v1
if: ${{ inputs.working-directory == 'libs/langchain' }}
@@ -54,11 +199,5 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
generateReleaseNotes: true
tag: v${{ steps.check-version.outputs.version }}
tag: v${{ needs.build.outputs.version }}
commit: master
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
verbose: true
print-hash: true

View File

@@ -10,9 +10,60 @@ on:
env:
POETRY_VERSION: "1.6.1"
PYTHON_VERSION: "3.10"
jobs:
publish_to_test_pypi:
build:
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
outputs:
pkg-name: ${{ steps.check-version.outputs.pkg-name }}
version: ${{ steps.check-version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
# We want to keep this build stage *separate* from the release stage,
# so that there's no sharing of permissions between them.
# The release stage has trusted publishing and GitHub repo contents write access,
# and we want to keep the scope of that access limited just to the release job.
# Otherwise, a malicious `build` step (e.g. via a compromised dependency)
# could get access to our GitHub or PyPI credentials.
#
# Per the trusted publishing GitHub Action:
# > It is strongly advised to separate jobs for building [...]
# > from the publish job.
# https://github.com/pypa/gh-action-pypi-publish#non-goals
- name: Build project for distribution
run: poetry build
working-directory: ${{ inputs.working-directory }}
- name: Upload build
uses: actions/upload-artifact@v3
with:
name: test-dist
path: ${{ inputs.working-directory }}/dist/
- name: Check Version
id: check-version
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
echo version="$(poetry version --short)" >> $GITHUB_OUTPUT
publish:
needs:
- build
runs-on: ubuntu-latest
permissions:
# This permission is used for trusted publishing:
@@ -21,30 +72,24 @@ jobs:
# Trusted publishing has to also be configured on PyPI for each package:
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
id-token: write
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
- uses: actions/download-artifact@v3
with:
python-version: "3.10"
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
name: test-dist
path: ${{ inputs.working-directory }}/dist/
- name: Build project for distribution
run: poetry build
- name: Check Version
id: check-version
run: |
echo version=$(poetry version --short) >> $GITHUB_OUTPUT
- name: Publish package to TestPyPI
- name: Publish to test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
packages-dir: ${{ inputs.working-directory }}/dist/
verbose: true
print-hash: true
repository-url: https://test.pypi.org/legacy/
# We overwrite any existing distributions with the same name and version.
# This is *only for CI use* and is *extremely dangerous* otherwise!
# https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates
skip-existing: true

View File

@@ -1,11 +1,17 @@
---
name: Documentation Lint
name: Docs, templates, cookbook lint
on:
push:
branches: [master]
branches: [ master ]
pull_request:
branches: [master]
paths:
- 'docs/**'
- 'templates/**'
- 'cookbook/**'
- '.github/workflows/_lint.yml'
- '.github/workflows/doc_lint.yml'
workflow_dispatch:
jobs:
check:
@@ -13,10 +19,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Run import check
run: |
# We should not encourage imports directly from main init file
# Expect for hub
git grep 'from langchain import' docs/{docs,snippets} | grep -vE 'from langchain import (hub)' && exit 1 || exit 0
git grep 'from langchain import' {docs/docs,templates,cookbook} | grep -vE 'from langchain import (hub)' && exit 1 || exit 0
lint:
uses:
./.github/workflows/_lint.yml
with:
working-directory: "."
secrets: inherit

View File

@@ -36,6 +36,7 @@ jobs:
./.github/workflows/_lint.yml
with:
working-directory: libs/cli
langchain-location: ../langchain
secrets: inherit
test:
@@ -44,10 +45,3 @@ jobs:
with:
working-directory: libs/cli
secrets: inherit
pydantic-compatibility:
uses:
./.github/workflows/_pydantic_compatibility.yml
with:
working-directory: libs/cli
secrets: inherit

View File

@@ -0,0 +1,13 @@
---
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

@@ -35,6 +35,7 @@ jobs:
./.github/workflows/_lint.yml
with:
working-directory: libs/experimental
langchain-location: ../langchain
secrets: inherit
test:

1
.gitignore vendored
View File

@@ -178,3 +178,4 @@ docs/docs/build
docs/docs/node_modules
docs/docs/yarn.lock
_dist
docs/docs/templates

View File

@@ -37,6 +37,18 @@ spell_check:
spell_fix:
poetry run codespell --toml pyproject.toml -w
######################
# LINTING AND FORMATTING
######################
lint:
poetry run ruff docs templates cookbook
poetry run black docs templates cookbook --diff
format format_diff:
poetry run black docs templates cookbook
poetry run ruff --select I --fix docs templates cookbook
######################
# HELP
######################

View File

@@ -47,7 +47,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 1,
"id": "6a75a5c6-34ee-4ab9-a664-d9b432d812ee",
"metadata": {},
"outputs": [
@@ -60,28 +60,27 @@
}
],
"source": [
"# Local \n",
"# Local\n",
"from langchain.chat_models import ChatOllama\n",
"\n",
"llama2_chat = ChatOllama(model=\"llama2:13b-chat\")\n",
"llama2_code = ChatOllama(model=\"codellama:7b-instruct\")\n",
"\n",
"# API\n",
"from getpass import getpass\n",
"from langchain.llms import Replicate\n",
"\n",
"# REPLICATE_API_TOKEN = getpass()\n",
"# os.environ[\"REPLICATE_API_TOKEN\"] = REPLICATE_API_TOKEN\n",
"replicate_id = \"meta/llama-2-13b-chat:f4e2de70d66816a838a89eeeb621910adffb0dd0baba3976c96980970978018d\"\n",
"llama2_chat_replicate = Replicate(\n",
" model=replicate_id,\n",
" input={\"temperature\": 0.01, \n",
" \"max_length\": 500, \n",
" \"top_p\": 1}\n",
" model=replicate_id, input={\"temperature\": 0.01, \"max_length\": 500, \"top_p\": 1}\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 2,
"id": "ce96f7ea-b3d5-44e1-9fa5-a79e04a9e1fb",
"metadata": {},
"outputs": [],
@@ -104,17 +103,20 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 3,
"id": "025bdd82-3bb1-4948-bc7c-c3ccd94fd05c",
"metadata": {},
"outputs": [],
"source": [
"from langchain.utilities import SQLDatabase\n",
"db = SQLDatabase.from_uri(\"sqlite:///nba_roster.db\", sample_rows_in_table_info= 0)\n",
"\n",
"db = SQLDatabase.from_uri(\"sqlite:///nba_roster.db\", sample_rows_in_table_info=0)\n",
"\n",
"\n",
"def get_schema(_):\n",
" return db.get_table_info()\n",
"\n",
"\n",
"def run_query(query):\n",
" return db.run(query)"
]
@@ -131,7 +133,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 4,
"id": "5a4933ea-d9c0-4b0a-8177-ba4490c6532b",
"metadata": {},
"outputs": [
@@ -141,7 +143,7 @@
"' SELECT \"Team\" FROM nba_roster WHERE \"NAME\" = \\'Klay Thompson\\';'"
]
},
"execution_count": 14,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -149,26 +151,29 @@
"source": [
"# Prompt\n",
"from langchain.prompts import ChatPromptTemplate\n",
"\n",
"template = \"\"\"Based on the table schema below, write a SQL query that would answer the user's question:\n",
"{schema}\n",
"\n",
"Question: {question}\n",
"SQL Query:\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"Given an input question, convert it to a SQL query. No pre-amble.\"),\n",
" (\"human\", template)\n",
"])\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"Given an input question, convert it to a SQL query. No pre-amble.\"),\n",
" (\"human\", template),\n",
" ]\n",
")\n",
"\n",
"# Chain to query\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain.schema.runnable import RunnablePassthrough\n",
"\n",
"sql_response = (\n",
" RunnablePassthrough.assign(schema=get_schema)\n",
" | prompt\n",
" | llm.bind(stop=[\"\\nSQLResult:\"])\n",
" | StrOutputParser()\n",
" )\n",
" RunnablePassthrough.assign(schema=get_schema)\n",
" | prompt\n",
" | llm.bind(stop=[\"\\nSQLResult:\"])\n",
" | StrOutputParser()\n",
")\n",
"\n",
"sql_response.invoke({\"question\": \"What team is Klay Thompson on?\"})"
]
@@ -209,18 +214,23 @@
"Question: {question}\n",
"SQL Query: {query}\n",
"SQL Response: {response}\"\"\"\n",
"prompt_response = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"Given an input question and SQL response, convert it to a natural langugae answer. No pre-amble.\"),\n",
" (\"human\", template)\n",
"])\n",
"prompt_response = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"Given an input question and SQL response, convert it to a natural langugae answer. No pre-amble.\",\n",
" ),\n",
" (\"human\", template),\n",
" ]\n",
")\n",
"\n",
"full_chain = (\n",
" RunnablePassthrough.assign(query=sql_response) \n",
" RunnablePassthrough.assign(query=sql_response)\n",
" | RunnablePassthrough.assign(\n",
" schema=get_schema,\n",
" response=lambda x: db.run(x[\"query\"]),\n",
" )\n",
" | prompt_response \n",
" | prompt_response\n",
" | llm\n",
")\n",
"\n",
@@ -250,8 +260,8 @@
},
{
"cell_type": "code",
"execution_count": 19,
"id": "1985aa1c-eb8f-4fb1-a54f-c8aa10744687",
"execution_count": 7,
"id": "022868f2-128e-42f5-8d90-d3bb2f11d994",
"metadata": {},
"outputs": [
{
@@ -260,7 +270,7 @@
"' SELECT \"Team\" FROM nba_roster WHERE \"NAME\" = \\'Klay Thompson\\';'"
]
},
"execution_count": 19,
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
@@ -269,61 +279,44 @@
"# Prompt\n",
"from langchain.memory import ConversationBufferMemory\n",
"from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"template = \"\"\"Based on the table schema below, write a SQL query that would answer the user's question:\n",
"{schema}\n",
"\n",
"Question: {question}\n",
"SQL Query:\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"Given an input question, convert it to a SQL query. No pre-amble.\"),\n",
" MessagesPlaceholder(variable_name=\"history\"),\n",
" (\"human\", template)\n",
"])\n",
"template = \"\"\"Given an input question, convert it to a SQL query. No pre-amble. Based on the table schema below, write a SQL query that would answer the user's question:\n",
"{schema}\n",
"\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", template),\n",
" MessagesPlaceholder(variable_name=\"history\"),\n",
" (\"human\", \"{question}\"),\n",
" ]\n",
")\n",
"\n",
"memory = ConversationBufferMemory(return_messages=True)\n",
"\n",
"# Chain to query with memory \n",
"# Chain to query with memory\n",
"from langchain.schema.runnable import RunnableLambda\n",
"\n",
"sql_chain = (\n",
" RunnablePassthrough.assign(\n",
" schema=get_schema,\n",
" history=RunnableLambda(lambda x: memory.load_memory_variables(x)[\"history\"])\n",
" )| prompt\n",
" schema=get_schema,\n",
" history=RunnableLambda(lambda x: memory.load_memory_variables(x)[\"history\"]),\n",
" )\n",
" | prompt\n",
" | llm.bind(stop=[\"\\nSQLResult:\"])\n",
" | StrOutputParser()\n",
")\n",
"\n",
"\n",
"def save(input_output):\n",
" output = {\"output\": input_output.pop(\"output\")}\n",
" memory.save_context(input_output, output)\n",
" return output['output']\n",
" \n",
" return output[\"output\"]\n",
"\n",
"\n",
"sql_response_memory = RunnablePassthrough.assign(output=sql_chain) | save\n",
"sql_response_memory.invoke({\"question\": \"What team is Klay Thompson on?\"})"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "0b45818a-1498-441d-b82d-23c29428c2bb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' SELECT \"SALARY\" FROM nba_roster WHERE \"NAME\" = \\'Klay Thompson\\';'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sql_response_memory.invoke({\"question\": \"What is his salary?\"})"
]
},
{
"cell_type": "code",
"execution_count": 21,
@@ -349,18 +342,23 @@
"Question: {question}\n",
"SQL Query: {query}\n",
"SQL Response: {response}\"\"\"\n",
"prompt_response = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"Given an input question and SQL response, convert it to a natural langugae answer. No pre-amble.\"),\n",
" (\"human\", template)\n",
"])\n",
"prompt_response = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"Given an input question and SQL response, convert it to a natural langugae answer. No pre-amble.\",\n",
" ),\n",
" (\"human\", template),\n",
" ]\n",
")\n",
"\n",
"full_chain = (\n",
" RunnablePassthrough.assign(query=sql_response_memory) \n",
" RunnablePassthrough.assign(query=sql_response_memory)\n",
" | RunnablePassthrough.assign(\n",
" schema=get_schema,\n",
" response=lambda x: db.run(x[\"query\"]),\n",
" )\n",
" | prompt_response \n",
" | prompt_response\n",
" | llm\n",
")\n",
"\n",

File diff suppressed because one or more lines are too long

View File

@@ -20,6 +20,7 @@ Notebook | Description
[databricks_sql_db.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/databricks_sql_db.ipynb) | Connect to databricks runtimes and databricks sql.
[deeplake_semantic_search_over_...](https://github.com/langchain-ai/langchain/tree/master/cookbook/deeplake_semantic_search_over_chat.ipynb) | Perform semantic search and question-answering over a group chat using activeloop's deep lake with gpt4.
[elasticsearch_db_qa.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/elasticsearch_db_qa.ipynb) | Interact with elasticsearch analytics databases in natural language and build search queries via the elasticsearch dsl API.
[extraction_openai_tools.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/extraction_openai_tools.ipynb) | Structured Data Extraction with OpenAI Tools
[forward_looking_retrieval_augm...](https://github.com/langchain-ai/langchain/tree/master/cookbook/forward_looking_retrieval_augmented_generation.ipynb) | Implement the forward-looking active retrieval augmented generation (flare) method, which generates answers to questions, identifies uncertain tokens, generates hypothetical questions based on these tokens, and retrieves relevant documents to continue generating the answer.
[generative_agents_interactive_...](https://github.com/langchain-ai/langchain/tree/master/cookbook/generative_agents_interactive_simulacra_of_human_behavior.ipynb) | Implement a generative agent that simulates human behavior, based on a research paper, using a time-weighted memory object backed by a langchain retriever.
[gymnasium_agent_simulation.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/gymnasium_agent_simulation.ipynb) | Create a simple agent-environment interaction loop in simulated environments like text-based games with gymnasium.
@@ -38,10 +39,12 @@ Notebook | Description
[multiagent_bidding.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/multiagent_bidding.ipynb) | Implement a multi-agent simulation where agents bid to speak, with the highest bidder speaking next, demonstrated through a fictitious presidential debate example.
[myscale_vector_sql.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/myscale_vector_sql.ipynb) | Access and interact with the myscale integrated vector database, which can enhance the performance of language model (llm) applications.
[openai_functions_retrieval_qa....](https://github.com/langchain-ai/langchain/tree/master/cookbook/openai_functions_retrieval_qa.ipynb) | Structure response output in a question-answering system by incorporating openai functions into a retrieval pipeline.
[openai_v1_cookbook.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/openai_v1_cookbook.ipynb) | Explore new functionality released alongside the V1 release of the OpenAI Python library.
[petting_zoo.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/petting_zoo.ipynb) | Create multi-agent simulations with simulated environments using the petting zoo library.
[plan_and_execute_agent.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/plan_and_execute_agent.ipynb) | Create plan-and-execute agents that accomplish objectives by planning tasks with a language model (llm) and executing them with a separate agent.
[press_releases.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/press_releases.ipynb) | Retrieve and query company press release data powered by [Kay.ai](https://kay.ai).
[program_aided_language_model.i...](https://github.com/langchain-ai/langchain/tree/master/cookbook/program_aided_language_model.ipynb) | Implement program-aided language models as described in the provided research paper.
[retrieval_in_sql.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/retrieval_in_sql.ipynb) | Perform retrieval-augmented-generation (rag) on a PostgreSQL database using pgvector.
[sales_agent_with_context.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/sales_agent_with_context.ipynb) | Implement a context-aware ai sales agent, salesgpt, that can have natural sales conversations, interact with other systems, and use a product knowledge base to discuss a company's offerings.
[self_query_hotel_search.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/self_query_hotel_search.ipynb) | Build a hotel room search feature with self-querying retrieval, using a specific hotel recommendation dataset.
[smart_llm.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/smart_llm.ipynb) | Implement a smartllmchain, a self-critique chain that generates multiple output proposals, critiques them to find the best one, and then improves upon it to produce a final output.

View File

@@ -60,7 +60,7 @@
"metadata": {},
"outputs": [],
"source": [
"! brew install tesseract \n",
"! brew install tesseract\n",
"! brew install poppler"
]
},
@@ -108,21 +108,23 @@
"from unstructured.partition.pdf import partition_pdf\n",
"\n",
"# Get elements\n",
"raw_pdf_elements = partition_pdf(filename=path+\"LLaMA2.pdf\",\n",
" # Unstructured first finds embedded image blocks\n",
" extract_images_in_pdf=False,\n",
" # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles\n",
" # Titles are any sub-section of the document \n",
" infer_table_structure=True, \n",
" # Post processing to aggregate text once we have the title \n",
" chunking_strategy=\"by_title\",\n",
" # Chunking params to aggregate text blocks\n",
" # Attempt to create a new chunk 3800 chars\n",
" # Attempt to keep chunks > 2000 chars \n",
" max_characters=4000, \n",
" new_after_n_chars=3800, \n",
" combine_text_under_n_chars=2000,\n",
" image_output_dir_path=path)"
"raw_pdf_elements = partition_pdf(\n",
" filename=path + \"LLaMA2.pdf\",\n",
" # Unstructured first finds embedded image blocks\n",
" extract_images_in_pdf=False,\n",
" # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles\n",
" # Titles are any sub-section of the document\n",
" infer_table_structure=True,\n",
" # Post processing to aggregate text once we have the title\n",
" chunking_strategy=\"by_title\",\n",
" # Chunking params to aggregate text blocks\n",
" # Attempt to create a new chunk 3800 chars\n",
" # Attempt to keep chunks > 2000 chars\n",
" max_characters=4000,\n",
" new_after_n_chars=3800,\n",
" combine_text_under_n_chars=2000,\n",
" image_output_dir_path=path,\n",
")"
]
},
{
@@ -190,6 +192,7 @@
" type: str\n",
" text: Any\n",
"\n",
"\n",
"# Categorize by type\n",
"categorized_elements = []\n",
"for element in raw_pdf_elements:\n",
@@ -259,14 +262,14 @@
"metadata": {},
"outputs": [],
"source": [
"# Prompt \n",
"prompt_text=\"\"\"You are an assistant tasked with summarizing tables and text. \\ \n",
"# Prompt\n",
"prompt_text = \"\"\"You are an assistant tasked with summarizing tables and text. \\ \n",
"Give a concise summary of the table or text. Table or text chunk: {element} \"\"\"\n",
"prompt = ChatPromptTemplate.from_template(prompt_text) \n",
"prompt = ChatPromptTemplate.from_template(prompt_text)\n",
"\n",
"# Summary chain \n",
"model = ChatOpenAI(temperature=0,model=\"gpt-4\")\n",
"summarize_chain = {\"element\": lambda x:x} | prompt | model | StrOutputParser()"
"# Summary chain\n",
"model = ChatOpenAI(temperature=0, model=\"gpt-4\")\n",
"summarize_chain = {\"element\": lambda x: x} | prompt | model | StrOutputParser()"
]
},
{
@@ -321,10 +324,7 @@
"from langchain.retrievers.multi_vector import MultiVectorRetriever\n",
"\n",
"# The vectorstore to use to index the child chunks\n",
"vectorstore = Chroma(\n",
" collection_name=\"summaries\",\n",
" embedding_function=OpenAIEmbeddings()\n",
")\n",
"vectorstore = Chroma(collection_name=\"summaries\", embedding_function=OpenAIEmbeddings())\n",
"\n",
"# The storage layer for the parent documents\n",
"store = InMemoryStore()\n",
@@ -332,20 +332,26 @@
"\n",
"# The retriever (empty to start)\n",
"retriever = MultiVectorRetriever(\n",
" vectorstore=vectorstore, \n",
" docstore=store, \n",
" vectorstore=vectorstore,\n",
" docstore=store,\n",
" id_key=id_key,\n",
")\n",
"\n",
"# Add texts\n",
"doc_ids = [str(uuid.uuid4()) for _ in texts]\n",
"summary_texts = [Document(page_content=s,metadata={id_key: doc_ids[i]}) for i, s in enumerate(text_summaries)]\n",
"summary_texts = [\n",
" Document(page_content=s, metadata={id_key: doc_ids[i]})\n",
" for i, s in enumerate(text_summaries)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_texts)\n",
"retriever.docstore.mset(list(zip(doc_ids, texts)))\n",
"\n",
"# Add tables\n",
"table_ids = [str(uuid.uuid4()) for _ in tables]\n",
"summary_tables = [Document(page_content=s,metadata={id_key: table_ids[i]}) for i, s in enumerate(table_summaries)]\n",
"summary_tables = [\n",
" Document(page_content=s, metadata={id_key: table_ids[i]})\n",
" for i, s in enumerate(table_summaries)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_tables)\n",
"retriever.docstore.mset(list(zip(table_ids, tables)))"
]
@@ -378,13 +384,13 @@
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"# LLM\n",
"model = ChatOpenAI(temperature=0,model=\"gpt-4\")\n",
"model = ChatOpenAI(temperature=0, model=\"gpt-4\")\n",
"\n",
"# RAG pipeline\n",
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")"
]

View File

@@ -98,22 +98,24 @@
"from unstructured.partition.pdf import partition_pdf\n",
"\n",
"# Get elements\n",
"raw_pdf_elements = partition_pdf(filename=path+\"LLaVA.pdf\",\n",
" # Using pdf format to find embedded image blocks\n",
" extract_images_in_pdf=True,\n",
" # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles\n",
" # Titles are any sub-section of the document \n",
" infer_table_structure=True, \n",
" # Post processing to aggregate text once we have the title \n",
" chunking_strategy=\"by_title\",\n",
" # Chunking params to aggregate text blocks\n",
" # Attempt to create a new chunk 3800 chars\n",
" # Attempt to keep chunks > 2000 chars \n",
" # Hard max on chunks\n",
" max_characters=4000, \n",
" new_after_n_chars=3800, \n",
" combine_text_under_n_chars=2000,\n",
" image_output_dir_path=path)"
"raw_pdf_elements = partition_pdf(\n",
" filename=path + \"LLaVA.pdf\",\n",
" # Using pdf format to find embedded image blocks\n",
" extract_images_in_pdf=True,\n",
" # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles\n",
" # Titles are any sub-section of the document\n",
" infer_table_structure=True,\n",
" # Post processing to aggregate text once we have the title\n",
" chunking_strategy=\"by_title\",\n",
" # Chunking params to aggregate text blocks\n",
" # Attempt to create a new chunk 3800 chars\n",
" # Attempt to keep chunks > 2000 chars\n",
" # Hard max on chunks\n",
" max_characters=4000,\n",
" new_after_n_chars=3800,\n",
" combine_text_under_n_chars=2000,\n",
" image_output_dir_path=path,\n",
")"
]
},
{
@@ -170,6 +172,7 @@
" type: str\n",
" text: Any\n",
"\n",
"\n",
"# Categorize by type\n",
"categorized_elements = []\n",
"for element in raw_pdf_elements:\n",
@@ -220,14 +223,14 @@
"metadata": {},
"outputs": [],
"source": [
"# Prompt \n",
"prompt_text=\"\"\"You are an assistant tasked with summarizing tables and text. \\ \n",
"# Prompt\n",
"prompt_text = \"\"\"You are an assistant tasked with summarizing tables and text. \\ \n",
"Give a concise summary of the table or text. Table or text chunk: {element} \"\"\"\n",
"prompt = ChatPromptTemplate.from_template(prompt_text) \n",
"prompt = ChatPromptTemplate.from_template(prompt_text)\n",
"\n",
"# Summary chain \n",
"model = ChatOpenAI(temperature=0,model=\"gpt-4\")\n",
"summarize_chain = {\"element\": lambda x:x} | prompt | model | StrOutputParser()"
"# Summary chain\n",
"model = ChatOpenAI(temperature=0, model=\"gpt-4\")\n",
"summarize_chain = {\"element\": lambda x: x} | prompt | model | StrOutputParser()"
]
},
{
@@ -342,11 +345,11 @@
"# Read each file and store its content in a list\n",
"img_summaries = []\n",
"for file_path in file_paths:\n",
" with open(file_path, 'r') as file:\n",
" with open(file_path, \"r\") as file:\n",
" img_summaries.append(file.read())\n",
"\n",
"# Remove any logging prior to summary\n",
"logging_header=\"clip_model_load: total allocated memory: 201.27 MB\\n\\n\"\n",
"logging_header = \"clip_model_load: total allocated memory: 201.27 MB\\n\\n\"\n",
"cleaned_img_summary = [s.split(logging_header, 1)[1].strip() for s in img_summaries]"
]
},
@@ -375,10 +378,7 @@
"from langchain.retrievers.multi_vector import MultiVectorRetriever\n",
"\n",
"# The vectorstore to use to index the child chunks\n",
"vectorstore = Chroma(\n",
" collection_name=\"summaries\",\n",
" embedding_function=OpenAIEmbeddings()\n",
")\n",
"vectorstore = Chroma(collection_name=\"summaries\", embedding_function=OpenAIEmbeddings())\n",
"\n",
"# The storage layer for the parent documents\n",
"store = InMemoryStore()\n",
@@ -386,20 +386,26 @@
"\n",
"# The retriever (empty to start)\n",
"retriever = MultiVectorRetriever(\n",
" vectorstore=vectorstore, \n",
" docstore=store, \n",
" vectorstore=vectorstore,\n",
" docstore=store,\n",
" id_key=id_key,\n",
")\n",
"\n",
"# Add texts\n",
"doc_ids = [str(uuid.uuid4()) for _ in texts]\n",
"summary_texts = [Document(page_content=s,metadata={id_key: doc_ids[i]}) for i, s in enumerate(text_summaries)]\n",
"summary_texts = [\n",
" Document(page_content=s, metadata={id_key: doc_ids[i]})\n",
" for i, s in enumerate(text_summaries)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_texts)\n",
"retriever.docstore.mset(list(zip(doc_ids, texts)))\n",
"\n",
"# Add tables\n",
"table_ids = [str(uuid.uuid4()) for _ in tables]\n",
"summary_tables = [Document(page_content=s,metadata={id_key: table_ids[i]}) for i, s in enumerate(table_summaries)]\n",
"summary_tables = [\n",
" Document(page_content=s, metadata={id_key: table_ids[i]})\n",
" for i, s in enumerate(table_summaries)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_tables)\n",
"retriever.docstore.mset(list(zip(table_ids, tables)))"
]
@@ -423,9 +429,12 @@
"source": [
"# Add image summaries\n",
"img_ids = [str(uuid.uuid4()) for _ in cleaned_img_summary]\n",
"summary_img = [Document(page_content=s,metadata={id_key: img_ids[i]}) for i, s in enumerate(cleaned_img_summary)]\n",
"summary_img = [\n",
" Document(page_content=s, metadata={id_key: img_ids[i]})\n",
" for i, s in enumerate(cleaned_img_summary)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_img)\n",
"retriever.docstore.mset(list(zip(img_ids, cleaned_img_summary))) "
"retriever.docstore.mset(list(zip(img_ids, cleaned_img_summary)))"
]
},
{
@@ -449,10 +458,19 @@
"source": [
"# Add images\n",
"img_ids = [str(uuid.uuid4()) for _ in cleaned_img_summary]\n",
"summary_img = [Document(page_content=s,metadata={id_key: img_ids[i]}) for i, s in enumerate(cleaned_img_summary)]\n",
"summary_img = [\n",
" Document(page_content=s, metadata={id_key: img_ids[i]})\n",
" for i, s in enumerate(cleaned_img_summary)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_img)\n",
"### Fetch images\n",
"retriever.docstore.mset(list(zip(img_ids, ### image ### ))) "
"retriever.docstore.mset(\n",
" list(\n",
" zip(\n",
" img_ids,\n",
" )\n",
" )\n",
")"
]
},
{
@@ -542,7 +560,9 @@
],
"source": [
"# We can retrieve this table\n",
"retriever.get_relevant_documents(\"What are results for LLaMA across across domains / subjects?\")[1]"
"retriever.get_relevant_documents(\n",
" \"What are results for LLaMA across across domains / subjects?\"\n",
")[1]"
]
},
{
@@ -592,7 +612,9 @@
}
],
"source": [
"retriever.get_relevant_documents(\"Images / figures with playful and creative examples\")[1]"
"retriever.get_relevant_documents(\"Images / figures with playful and creative examples\")[\n",
" 1\n",
"]"
]
},
{
@@ -633,15 +655,15 @@
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"# Option 1: LLM\n",
"model = ChatOpenAI(temperature=0,model=\"gpt-4\")\n",
"model = ChatOpenAI(temperature=0, model=\"gpt-4\")\n",
"# Option 2: Multi-modal LLM\n",
"# model = GPT4-V or LLaVA\n",
"\n",
"# RAG pipeline\n",
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")"
]
@@ -664,7 +686,9 @@
}
],
"source": [
"chain.invoke(\"What is the performance of LLaVa across across multiple image domains / subjects?\")"
"chain.invoke(\n",
" \"What is the performance of LLaVa across across multiple image domains / subjects?\"\n",
")"
]
},
{
@@ -713,7 +737,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -92,22 +92,24 @@
"path = \"/Users/rlm/Desktop/Papers/LLaVA/\"\n",
"\n",
"# Get elements\n",
"raw_pdf_elements = partition_pdf(filename=path+\"LLaVA.pdf\",\n",
" # Using pdf format to find embedded image blocks\n",
" extract_images_in_pdf=True,\n",
" # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles\n",
" # Titles are any sub-section of the document \n",
" infer_table_structure=True, \n",
" # Post processing to aggregate text once we have the title \n",
" chunking_strategy=\"by_title\",\n",
" # Chunking params to aggregate text blocks\n",
" # Attempt to create a new chunk 3800 chars\n",
" # Attempt to keep chunks > 2000 chars \n",
" # Hard max on chunks\n",
" max_characters=4000, \n",
" new_after_n_chars=3800, \n",
" combine_text_under_n_chars=2000,\n",
" image_output_dir_path=path)"
"raw_pdf_elements = partition_pdf(\n",
" filename=path + \"LLaVA.pdf\",\n",
" # Using pdf format to find embedded image blocks\n",
" extract_images_in_pdf=True,\n",
" # Use layout model (YOLOX) to get bounding boxes (for tables) and find titles\n",
" # Titles are any sub-section of the document\n",
" infer_table_structure=True,\n",
" # Post processing to aggregate text once we have the title\n",
" chunking_strategy=\"by_title\",\n",
" # Chunking params to aggregate text blocks\n",
" # Attempt to create a new chunk 3800 chars\n",
" # Attempt to keep chunks > 2000 chars\n",
" # Hard max on chunks\n",
" max_characters=4000,\n",
" new_after_n_chars=3800,\n",
" combine_text_under_n_chars=2000,\n",
" image_output_dir_path=path,\n",
")"
]
},
{
@@ -165,6 +167,7 @@
" type: str\n",
" text: Any\n",
"\n",
"\n",
"# Categorize by type\n",
"categorized_elements = []\n",
"for element in raw_pdf_elements:\n",
@@ -219,14 +222,14 @@
"metadata": {},
"outputs": [],
"source": [
"# Prompt \n",
"prompt_text=\"\"\"You are an assistant tasked with summarizing tables and text. \\ \n",
"# Prompt\n",
"prompt_text = \"\"\"You are an assistant tasked with summarizing tables and text. \\ \n",
"Give a concise summary of the table or text. Table or text chunk: {element} \"\"\"\n",
"prompt = ChatPromptTemplate.from_template(prompt_text) \n",
"prompt = ChatPromptTemplate.from_template(prompt_text)\n",
"\n",
"# Summary chain \n",
"# Summary chain\n",
"model = ChatOllama(model=\"llama2:13b-chat\")\n",
"summarize_chain = {\"element\": lambda x:x} | prompt | model | StrOutputParser()"
"summarize_chain = {\"element\": lambda x: x} | prompt | model | StrOutputParser()"
]
},
{
@@ -327,11 +330,14 @@
"# Read each file and store its content in a list\n",
"img_summaries = []\n",
"for file_path in file_paths:\n",
" with open(file_path, 'r') as file:\n",
" with open(file_path, \"r\") as file:\n",
" img_summaries.append(file.read())\n",
"\n",
"# Clean up residual logging\n",
"cleaned_img_summary = [s.split(\"clip_model_load: total allocated memory: 201.27 MB\\n\\n\", 1)[1].strip() for s in img_summaries]"
"cleaned_img_summary = [\n",
" s.split(\"clip_model_load: total allocated memory: 201.27 MB\\n\\n\", 1)[1].strip()\n",
" for s in img_summaries\n",
"]"
]
},
{
@@ -377,18 +383,17 @@
"\n",
"# The vectorstore to use to index the child chunks\n",
"vectorstore = Chroma(\n",
" collection_name=\"summaries\",\n",
" embedding_function=GPT4AllEmbeddings()\n",
" collection_name=\"summaries\", embedding_function=GPT4AllEmbeddings()\n",
")\n",
"\n",
"# The storage layer for the parent documents\n",
"store = InMemoryStore() # <- Can we extend this to images \n",
"store = InMemoryStore() # <- Can we extend this to images\n",
"id_key = \"doc_id\"\n",
"\n",
"# The retriever (empty to start)\n",
"retriever = MultiVectorRetriever(\n",
" vectorstore=vectorstore, \n",
" docstore=store, \n",
" vectorstore=vectorstore,\n",
" docstore=store,\n",
" id_key=id_key,\n",
")"
]
@@ -412,21 +417,32 @@
"source": [
"# Add texts\n",
"doc_ids = [str(uuid.uuid4()) for _ in texts]\n",
"summary_texts = [Document(page_content=s,metadata={id_key: doc_ids[i]}) for i, s in enumerate(text_summaries)]\n",
"summary_texts = [\n",
" Document(page_content=s, metadata={id_key: doc_ids[i]})\n",
" for i, s in enumerate(text_summaries)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_texts)\n",
"retriever.docstore.mset(list(zip(doc_ids, texts)))\n",
"\n",
"# Add tables\n",
"table_ids = [str(uuid.uuid4()) for _ in tables]\n",
"summary_tables = [Document(page_content=s,metadata={id_key: table_ids[i]}) for i, s in enumerate(table_summaries)]\n",
"summary_tables = [\n",
" Document(page_content=s, metadata={id_key: table_ids[i]})\n",
" for i, s in enumerate(table_summaries)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_tables)\n",
"retriever.docstore.mset(list(zip(table_ids, tables)))\n",
"\n",
"# Add images\n",
"img_ids = [str(uuid.uuid4()) for _ in cleaned_img_summary]\n",
"summary_img = [Document(page_content=s,metadata={id_key: img_ids[i]}) for i, s in enumerate(cleaned_img_summary)]\n",
"summary_img = [\n",
" Document(page_content=s, metadata={id_key: img_ids[i]})\n",
" for i, s in enumerate(cleaned_img_summary)\n",
"]\n",
"retriever.vectorstore.add_documents(summary_img)\n",
"retriever.docstore.mset(list(zip(img_ids, cleaned_img_summary))) # Store the image summary as the raw document"
"retriever.docstore.mset(\n",
" list(zip(img_ids, cleaned_img_summary))\n",
") # Store the image summary as the raw document"
]
},
{
@@ -484,7 +500,9 @@
}
],
"source": [
"retriever.get_relevant_documents(\"Images / figures with playful and creative examples\")[0]"
"retriever.get_relevant_documents(\"Images / figures with playful and creative examples\")[\n",
" 0\n",
"]"
]
},
{
@@ -530,9 +548,9 @@
"\n",
"# RAG pipeline\n",
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")"
]
@@ -555,7 +573,9 @@
}
],
"source": [
"chain.invoke(\"What is the performance of LLaVa across across multiple image domains / subjects?\")"
"chain.invoke(\n",
" \"What is the performance of LLaVa across across multiple image domains / subjects?\"\n",
")"
]
},
{
@@ -584,7 +604,9 @@
}
],
"source": [
"chain.invoke(\"Explain any images / figures in the paper with playful and creative examples.\")"
"chain.invoke(\n",
" \"Explain any images / figures in the paper with playful and creative examples.\"\n",
")"
]
},
{

File diff suppressed because one or more lines are too long

View File

@@ -837,7 +837,9 @@
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.chains import ConversationalRetrievalChain\n",
"\n",
"model = ChatOpenAI(model_name=\"gpt-3.5-turbo-0613\") # 'ada' 'gpt-3.5-turbo-0613' 'gpt-4',\n",
"model = ChatOpenAI(\n",
" model_name=\"gpt-3.5-turbo-0613\"\n",
") # 'ada' 'gpt-3.5-turbo-0613' 'gpt-4',\n",
"qa = ConversationalRetrievalChain.from_llm(model, retriever=retriever)"
]
},

View File

@@ -0,0 +1,213 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "2def22ea",
"metadata": {},
"source": [
"# Extraction with OpenAI Tools\n",
"\n",
"Performing extraction has never been easier! OpenAI's tool calling ability is the perfect thing to use as it allows for extracting multiple different elements from text that are different types. \n",
"\n",
"Models after 1106 use tools and support \"parallel function calling\" which makes this super easy."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "5c628496",
"metadata": {},
"outputs": [],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.pydantic_v1 import BaseModel\n",
"from typing import Optional, List\n",
"from langchain.chains.openai_tools import create_extraction_chain_pydantic"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "afe9657b",
"metadata": {},
"outputs": [],
"source": [
"# Make sure to use a recent model that supports tools\n",
"model = ChatOpenAI(model=\"gpt-3.5-turbo-1106\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "bc0ca3b6",
"metadata": {},
"outputs": [],
"source": [
"# Pydantic is an easy way to define a schema\n",
"class Person(BaseModel):\n",
" \"\"\"Information about people to extract.\"\"\"\n",
"\n",
" name: str\n",
" age: Optional[int] = None"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2036af68",
"metadata": {},
"outputs": [],
"source": [
"chain = create_extraction_chain_pydantic(Person, model)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "1748ad21",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Person(name='jane', age=2), Person(name='bob', age=3)]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"input\": \"jane is 2 and bob is 3\"})"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "c8262ce5",
"metadata": {},
"outputs": [],
"source": [
"# Let's define another element\n",
"class Class(BaseModel):\n",
" \"\"\"Information about classes to extract.\"\"\"\n",
"\n",
" teacher: str\n",
" students: List[str]"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "4973c104",
"metadata": {},
"outputs": [],
"source": [
"chain = create_extraction_chain_pydantic([Person, Class], model)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "e976a15e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Person(name='jane', age=2),\n",
" Person(name='bob', age=3),\n",
" Class(teacher='Mrs Sampson', students=['jane', 'bob'])]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"input\": \"jane is 2 and bob is 3 and they are in Mrs Sampson's class\"})"
]
},
{
"cell_type": "markdown",
"id": "6575a7d6",
"metadata": {},
"source": [
"## Under the hood\n",
"\n",
"Under the hood, this is a simple chain:"
]
},
{
"cell_type": "markdown",
"id": "b8ba83e5",
"metadata": {},
"source": [
"```python\n",
"from typing import Union, List, Type, Optional\n",
"\n",
"from langchain.output_parsers.openai_tools import PydanticToolsParser\n",
"from langchain.utils.openai_functions import convert_pydantic_to_openai_tool\n",
"from langchain.schema.runnable import Runnable\n",
"from langchain.pydantic_v1 import BaseModel\n",
"from langchain.prompts import ChatPromptTemplate\n",
"from langchain.schema.messages import SystemMessage\n",
"from langchain.schema.language_model import BaseLanguageModel\n",
"\n",
"_EXTRACTION_TEMPLATE = \"\"\"Extract and save the relevant entities mentioned \\\n",
"in the following passage together with their properties.\n",
"\n",
"If a property is not present and is not required in the function parameters, do not include it in the output.\"\"\" # noqa: E501\n",
"\n",
"\n",
"def create_extraction_chain_pydantic(\n",
" pydantic_schemas: Union[List[Type[BaseModel]], Type[BaseModel]],\n",
" llm: BaseLanguageModel,\n",
" system_message: str = _EXTRACTION_TEMPLATE,\n",
") -> Runnable:\n",
" if not isinstance(pydantic_schemas, list):\n",
" pydantic_schemas = [pydantic_schemas]\n",
" prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", system_message),\n",
" (\"user\", \"{input}\")\n",
" ])\n",
" tools = [convert_pydantic_to_openai_tool(p) for p in pydantic_schemas]\n",
" model = llm.bind(tools=tools)\n",
" chain = prompt | model | PydanticToolsParser(tools=pydantic_schemas)\n",
" return chain\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2eac6b68",
"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

@@ -77,6 +77,7 @@
"source": [
"from langchain.llms import OpenAI\n",
"from langchain_experimental.autonomous_agents import HuggingGPT\n",
"\n",
"# %env OPENAI_API_BASE=http://localhost:8000/v1"
]
},

View File

@@ -50,6 +50,7 @@
"# pick and configure the LLM of your choice\n",
"\n",
"from langchain.llms import OpenAI\n",
"\n",
"llm = OpenAI(model=\"text-davinci-003\")"
]
},
@@ -85,8 +86,8 @@
"\"\"\"\n",
"\n",
"PROMPT = PromptTemplate(\n",
" input_variables=[\"meal\", \"text_to_personalize\", \"user\", \"preference\"], \n",
" template=PROMPT_TEMPLATE\n",
" input_variables=[\"meal\", \"text_to_personalize\", \"user\", \"preference\"],\n",
" template=PROMPT_TEMPLATE,\n",
")"
]
},
@@ -105,7 +106,7 @@
"source": [
"import langchain_experimental.rl_chain as rl_chain\n",
"\n",
"chain = rl_chain.PickBest.from_llm(llm=llm, prompt=PROMPT)\n"
"chain = rl_chain.PickBest.from_llm(llm=llm, prompt=PROMPT)"
]
},
{
@@ -122,10 +123,10 @@
"outputs": [],
"source": [
"response = chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs \\\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs \\\n",
" believe you will love it!\",\n",
")"
]
@@ -193,10 +194,10 @@
"for _ in range(5):\n",
" try:\n",
" response = chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" )\n",
" except Exception as e:\n",
" print(e)\n",
@@ -223,12 +224,16 @@
"metadata": {},
"outputs": [],
"source": [
"scoring_criteria_template = \"Given {preference} rank how good or bad this selection is {meal}\"\n",
"scoring_criteria_template = (\n",
" \"Given {preference} rank how good or bad this selection is {meal}\"\n",
")\n",
"\n",
"chain = rl_chain.PickBest.from_llm(\n",
" llm=llm,\n",
" prompt=PROMPT,\n",
" selection_scorer=rl_chain.AutoSelectionScorer(llm=llm, scoring_criteria_template_str=scoring_criteria_template),\n",
" selection_scorer=rl_chain.AutoSelectionScorer(\n",
" llm=llm, scoring_criteria_template_str=scoring_criteria_template\n",
" ),\n",
")"
]
},
@@ -255,14 +260,16 @@
],
"source": [
"response = chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
")\n",
"print(response[\"response\"])\n",
"selection_metadata = response[\"selection_metadata\"]\n",
"print(f\"selected index: {selection_metadata.selected.index}, score: {selection_metadata.selected.score}\")"
"print(\n",
" f\"selected index: {selection_metadata.selected.index}, score: {selection_metadata.selected.score}\"\n",
")"
]
},
{
@@ -280,8 +287,8 @@
"source": [
"class CustomSelectionScorer(rl_chain.SelectionScorer):\n",
" def score_response(\n",
" self, inputs, llm_response: str, event: rl_chain.PickBestEvent) -> float:\n",
"\n",
" self, inputs, llm_response: str, event: rl_chain.PickBestEvent\n",
" ) -> float:\n",
" print(event.based_on)\n",
" print(event.to_select_from)\n",
"\n",
@@ -336,10 +343,10 @@
],
"source": [
"response = chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
")"
]
},
@@ -370,9 +377,10 @@
" return 1.0\n",
" else:\n",
" return 0.0\n",
" def score_response(\n",
" self, inputs, llm_response: str, event: rl_chain.PickBestEvent) -> float:\n",
"\n",
" def score_response(\n",
" self, inputs, llm_response: str, event: rl_chain.PickBestEvent\n",
" ) -> float:\n",
" selected_meal = event.to_select_from[\"meal\"][event.selected.index]\n",
"\n",
" if \"Tom\" in event.based_on[\"user\"]:\n",
@@ -394,7 +402,7 @@
" prompt=PROMPT,\n",
" selection_scorer=CustomSelectionScorer(),\n",
" metrics_step=5,\n",
" metrics_window_size=5, # rolling window average\n",
" metrics_window_size=5, # rolling window average\n",
")\n",
"\n",
"random_chain = rl_chain.PickBest.from_llm(\n",
@@ -402,8 +410,8 @@
" prompt=PROMPT,\n",
" selection_scorer=CustomSelectionScorer(),\n",
" metrics_step=5,\n",
" metrics_window_size=5, # rolling window average\n",
" policy=rl_chain.PickBestRandomPolicy # set the random policy instead of default\n",
" metrics_window_size=5, # rolling window average\n",
" policy=rl_chain.PickBestRandomPolicy, # set the random policy instead of default\n",
")"
]
},
@@ -416,29 +424,29 @@
"for _ in range(20):\n",
" try:\n",
" chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" )\n",
" random_chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" )\n",
" \n",
"\n",
" chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Anna\"),\n",
" preference = rl_chain.BasedOn([\"Loves meat\", \"especially beef\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Anna\"),\n",
" preference=rl_chain.BasedOn([\"Loves meat\", \"especially beef\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" )\n",
" random_chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Anna\"),\n",
" preference = rl_chain.BasedOn([\"Loves meat\", \"especially beef\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Anna\"),\n",
" preference=rl_chain.BasedOn([\"Loves meat\", \"especially beef\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" )\n",
" except Exception as e:\n",
" print(e)"
@@ -477,12 +485,17 @@
],
"source": [
"from matplotlib import pyplot as plt\n",
"chain.metrics.to_pandas()['score'].plot(label=\"default learning policy\")\n",
"random_chain.metrics.to_pandas()['score'].plot(label=\"random selection policy\")\n",
"\n",
"chain.metrics.to_pandas()[\"score\"].plot(label=\"default learning policy\")\n",
"random_chain.metrics.to_pandas()[\"score\"].plot(label=\"random selection policy\")\n",
"plt.legend()\n",
"\n",
"print(f\"The final average score for the default policy, calculated over a rolling window, is: {chain.metrics.to_pandas()['score'].iloc[-1]}\")\n",
"print(f\"The final average score for the random policy, calculated over a rolling window, is: {random_chain.metrics.to_pandas()['score'].iloc[-1]}\")"
"print(\n",
" f\"The final average score for the default policy, calculated over a rolling window, is: {chain.metrics.to_pandas()['score'].iloc[-1]}\"\n",
")\n",
"print(\n",
" f\"The final average score for the random policy, calculated over a rolling window, is: {random_chain.metrics.to_pandas()['score'].iloc[-1]}\"\n",
")"
]
},
{
@@ -803,10 +816,10 @@
")\n",
"\n",
"chain.run(\n",
" meal = rl_chain.ToSelectFrom(meals),\n",
" user = rl_chain.BasedOn(\"Tom\"),\n",
" preference = rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize = \"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
" meal=rl_chain.ToSelectFrom(meals),\n",
" user=rl_chain.BasedOn(\"Tom\"),\n",
" preference=rl_chain.BasedOn([\"Vegetarian\", \"regular dairy is ok\"]),\n",
" text_to_personalize=\"This is the weeks specialty dish, our master chefs believe you will love it!\",\n",
")"
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -27,11 +27,12 @@
"metadata": {},
"outputs": [],
"source": [
"\n",
"from os import environ\n",
"import getpass\n",
"from typing import Dict, Any\n",
"from langchain.llms import OpenAI\nfrom langchain.utilities import SQLDatabase\nfrom langchain.chains import LLMChain\n",
"from langchain.llms import OpenAI\n",
"from langchain.utilities import SQLDatabase\n",
"from langchain.chains import LLMChain\n",
"from langchain_experimental.sql.vector_sql import VectorSQLDatabaseChain\n",
"from sqlalchemy import create_engine, Column, MetaData\n",
"from langchain.prompts import PromptTemplate\n",
@@ -39,7 +40,7 @@
"\n",
"from sqlalchemy import create_engine\n",
"\n",
"MYSCALE_HOST = \"msc-1decbcc9.us-east-1.aws.staging.myscale.cloud\"\n",
"MYSCALE_HOST = \"msc-4a9e710a.us-east-1.aws.staging.myscale.cloud\"\n",
"MYSCALE_PORT = 443\n",
"MYSCALE_USER = \"chatdata\"\n",
"MYSCALE_PASSWORD = \"myscale_rocks\"\n",
@@ -76,7 +77,6 @@
"metadata": {},
"outputs": [],
"source": [
"\n",
"from langchain.llms import OpenAI\n",
"from langchain.callbacks import StdOutCallbackHandler\n",
"\n",
@@ -124,8 +124,9 @@
"from langchain.chains.qa_with_sources.retrieval import RetrievalQAWithSourcesChain\n",
"\n",
"from langchain_experimental.sql.vector_sql import VectorSQLDatabaseChain\n",
"from langchain_experimental.retrievers.vector_sql_database \\\n",
" import VectorSQLDatabaseChainRetriever\n",
"from langchain_experimental.retrievers.vector_sql_database import (\n",
" VectorSQLDatabaseChainRetriever,\n",
")\n",
"from langchain_experimental.sql.prompt import MYSCALE_PROMPT\n",
"from langchain_experimental.sql.vector_sql import VectorSQLRetrieveAllOutputParser\n",
"\n",
@@ -144,7 +145,9 @@
")\n",
"\n",
"# You need all those keys to get docs\n",
"retriever = VectorSQLDatabaseChainRetriever(sql_db_chain=chain, page_content_key=\"abstract\")\n",
"retriever = VectorSQLDatabaseChainRetriever(\n",
" sql_db_chain=chain, page_content_key=\"abstract\"\n",
")\n",
"\n",
"document_with_metadata_prompt = PromptTemplate(\n",
" input_variables=[\"page_content\", \"id\", \"title\", \"authors\", \"pubdate\", \"categories\"],\n",
@@ -162,8 +165,10 @@
" },\n",
" return_source_documents=True,\n",
")\n",
"ans = chain(\"Please give me 10 papers to ask what is PageRank?\",\n",
" callbacks=[StdOutCallbackHandler()])\n",
"ans = chain(\n",
" \"Please give me 10 papers to ask what is PageRank?\",\n",
" callbacks=[StdOutCallbackHandler()],\n",
")\n",
"print(ans[\"answer\"])"
]
},

View File

@@ -0,0 +1,506 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "f970f757-ec76-4bf0-90cd-a2fb68b945e3",
"metadata": {},
"source": [
"# Exploring OpenAI V1 functionality\n",
"\n",
"On 11.06.23 OpenAI released a number of new features, and along with it bumped their Python SDK to 1.0.0. This notebook shows off the new features and how to use them with LangChain."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee897729-263a-4073-898f-bb4cf01ed829",
"metadata": {},
"outputs": [],
"source": [
"# need openai>=1.1.0, langchain>=0.0.333, langchain-experimental>=0.0.39\n",
"!pip install -U openai langchain langchain-experimental"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "c3e067ce-7a43-47a7-bc89-41f1de4cf136",
"metadata": {},
"outputs": [],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.schema.messages import HumanMessage, SystemMessage"
]
},
{
"cell_type": "markdown",
"id": "fa7e7e95-90a1-4f73-98fe-10c4b4e0951b",
"metadata": {},
"source": [
"## [Vision](https://platform.openai.com/docs/guides/vision)\n",
"\n",
"OpenAI released multi-modal models, which can take a sequence of text and images as input."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1c8c3965-d3c9-4186-b5f3-5e67855ef916",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='The image appears to be a diagram representing the architecture or components of a software system or framework related to language processing, possibly named LangChain or associated with a project or product called LangChain, based on the prominent appearance of that term. The diagram is organized into several layers or aspects, each containing various elements or modules:\\n\\n1. **Protocol**: This may be the foundational layer, which includes \"LCEL\" and terms like parallelization, fallbacks, tracing, batching, streaming, async, and composition. These seem related to communication and execution protocols for the system.\\n\\n2. **Integrations Components**: This layer includes \"Model I/O\" with elements such as the model, output parser, prompt, and example selector. It also has a \"Retrieval\" section with a document loader, retriever, embedding model, vector store, and text splitter. Lastly, there\\'s an \"Agent Tooling\" section. These components likely deal with the interaction with external data, models, and tools.\\n\\n3. **Application**: The application layer features \"LangChain\" with chains, agents, agent executors, and common application logic. This suggests that the system uses a modular approach with chains and agents to process language tasks.\\n\\n4. **Deployment**: This contains \"Lang')"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat = ChatOpenAI(model=\"gpt-4-vision-preview\", max_tokens=256)\n",
"chat.invoke(\n",
" [\n",
" HumanMessage(\n",
" content=[\n",
" {\"type\": \"text\", \"text\": \"What is this image showing\"},\n",
" {\n",
" \"type\": \"image_url\",\n",
" \"image_url\": {\n",
" \"url\": \"https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/static/img/langchain_stack.png\",\n",
" \"detail\": \"auto\",\n",
" },\n",
" },\n",
" ]\n",
" )\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"id": "210f8248-fcf3-4052-a4a3-0684e08f8785",
"metadata": {},
"source": [
"## [OpenAI assistants](https://platform.openai.com/docs/assistants/overview)\n",
"\n",
"> The Assistants API allows you to build AI assistants within your own applications. An Assistant has instructions and can leverage models, tools, and knowledge to respond to user queries. The Assistants API currently supports three types of tools: Code Interpreter, Retrieval, and Function calling\n",
"\n",
"\n",
"You can interact with OpenAI Assistants using OpenAI tools or custom tools. When using exclusively OpenAI tools, you can just invoke the assistant directly and get final answers. When using custom tools, you can run the assistant and tool execution loop using the built-in AgentExecutor or easily write your own executor.\n",
"\n",
"Below we show the different ways to interact with Assistants. As a simple example, let's build a math tutor that can write and run code."
]
},
{
"cell_type": "markdown",
"id": "318da28d-4cec-42ab-ae3e-76d95bb34fa5",
"metadata": {},
"source": [
"### Using only OpenAI tools"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "a9064bbe-d9f7-4a29-a7b3-73933b3197e7",
"metadata": {},
"outputs": [],
"source": [
"from langchain_experimental.openai_assistant import OpenAIAssistantRunnable"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "7a20a008-49ac-46d2-aa26-b270118af5ea",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[ThreadMessage(id='msg_g9OJv0rpPgnc3mHmocFv7OVd', assistant_id='asst_hTwZeNMMphxzSOqJ01uBMsJI', content=[MessageContentText(text=Text(annotations=[], value='The result of \\\\(10 - 4^{2.7}\\\\) is approximately \\\\(-32.224\\\\).'), type='text')], created_at=1699460600, file_ids=[], metadata={}, object='thread.message', role='assistant', run_id='run_nBIT7SiAwtUfSCTrQNSPLOfe', thread_id='thread_14n4GgXwxgNL0s30WJW5F6p0')]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interpreter_assistant = OpenAIAssistantRunnable.create_assistant(\n",
" name=\"langchain assistant\",\n",
" instructions=\"You are a personal math tutor. Write and run code to answer math questions.\",\n",
" tools=[{\"type\": \"code_interpreter\"}],\n",
" model=\"gpt-4-1106-preview\",\n",
")\n",
"output = interpreter_assistant.invoke({\"content\": \"What's 10 - 4 raised to the 2.7\"})\n",
"output"
]
},
{
"cell_type": "markdown",
"id": "a8ddd181-ac63-4ab6-a40d-a236120379c1",
"metadata": {},
"source": [
"### As a LangChain agent with arbitrary tools\n",
"\n",
"Now let's recreate this functionality using our own tools. For this example we'll use the [E2B sandbox runtime tool](https://e2b.dev/docs?ref=landing-page-get-started)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee4cc355-f2d6-4c51-bcf7-f502868357d3",
"metadata": {},
"outputs": [],
"source": [
"!pip install e2b duckduckgo-search"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "48681ac7-b267-48d4-972c-8a7df8393a21",
"metadata": {},
"outputs": [],
"source": [
"from langchain.tools import E2BDataAnalysisTool, DuckDuckGoSearchRun\n",
"\n",
"tools = [E2BDataAnalysisTool(api_key=\"...\"), DuckDuckGoSearchRun()]"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1c01dd79-dd3e-4509-a2e2-009a7f99f16a",
"metadata": {},
"outputs": [],
"source": [
"agent = OpenAIAssistantRunnable.create_assistant(\n",
" name=\"langchain assistant e2b tool\",\n",
" instructions=\"You are a personal math tutor. Write and run code to answer math questions. You can also search the internet.\",\n",
" tools=tools,\n",
" model=\"gpt-4-1106-preview\",\n",
" as_agent=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "1ac71d8b-4b4b-4f98-b826-6b3c57a34166",
"metadata": {},
"source": [
"#### Using AgentExecutor"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "1f137f94-801f-4766-9ff5-2de9df5e8079",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'content': \"What's the weather in SF today divided by 2.7\",\n",
" 'output': \"The weather in San Francisco today is reported to have temperatures as high as 66 °F. To get the temperature divided by 2.7, we will calculate that:\\n\\n66 °F / 2.7 = 24.44 °F\\n\\nSo, when the high temperature of 66 °F is divided by 2.7, the result is approximately 24.44 °F. Please note that this doesn't have a meteorological meaning; it's purely a mathematical operation based on the given temperature.\"}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.agents import AgentExecutor\n",
"\n",
"agent_executor = AgentExecutor(agent=agent, tools=tools)\n",
"agent_executor.invoke({\"content\": \"What's the weather in SF today divided by 2.7\"})"
]
},
{
"cell_type": "markdown",
"id": "2d0a0b1d-c1b3-4b50-9dce-1189b51a6206",
"metadata": {},
"source": [
"#### Custom execution"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c0475fa7-b6c1-4331-b8e2-55407466c724",
"metadata": {},
"outputs": [],
"source": [
"agent = OpenAIAssistantRunnable.create_assistant(\n",
" name=\"langchain assistant e2b tool\",\n",
" instructions=\"You are a personal math tutor. Write and run code to answer math questions.\",\n",
" tools=tools,\n",
" model=\"gpt-4-1106-preview\",\n",
" as_agent=True,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "b76cb669-6aba-4827-868f-00aa960026f2",
"metadata": {},
"outputs": [],
"source": [
"from langchain.schema.agent import AgentFinish\n",
"\n",
"\n",
"def execute_agent(agent, tools, input):\n",
" tool_map = {tool.name: tool for tool in tools}\n",
" response = agent.invoke(input)\n",
" while not isinstance(response, AgentFinish):\n",
" tool_outputs = []\n",
" for action in response:\n",
" tool_output = tool_map[action.tool].invoke(action.tool_input)\n",
" print(action.tool, action.tool_input, tool_output, end=\"\\n\\n\")\n",
" tool_outputs.append(\n",
" {\"output\": tool_output, \"tool_call_id\": action.tool_call_id}\n",
" )\n",
" response = agent.invoke(\n",
" {\n",
" \"tool_outputs\": tool_outputs,\n",
" \"run_id\": action.run_id,\n",
" \"thread_id\": action.thread_id,\n",
" }\n",
" )\n",
"\n",
" return response"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7946116a-b82f-492e-835e-ca958a8949a5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"e2b_data_analysis {'python_code': 'print(10 - 4 ** 2.7)'} {\"stdout\": \"-32.22425314473263\", \"stderr\": \"\", \"artifacts\": []}\n",
"\n",
"\\( 10 - 4^{2.7} \\) is approximately \\(-32.22425314473263\\).\n"
]
}
],
"source": [
"response = execute_agent(agent, tools, {\"content\": \"What's 10 - 4 raised to the 2.7\"})\n",
"print(response.return_values[\"output\"])"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "f2744a56-9f4f-4899-827a-fa55821c318c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"e2b_data_analysis {'python_code': 'result = 10 - 4 ** 2.7\\nprint(result + 17.241)'} {\"stdout\": \"-14.983253144732629\", \"stderr\": \"\", \"artifacts\": []}\n",
"\n",
"When you add \\( 17.241 \\) to \\( 10 - 4^{2.7} \\), the result is approximately \\( -14.98325314473263 \\).\n"
]
}
],
"source": [
"next_response = execute_agent(\n",
" agent, tools, {\"content\": \"now add 17.241\", \"thread_id\": response.thread_id}\n",
")\n",
"print(next_response.return_values[\"output\"])"
]
},
{
"cell_type": "markdown",
"id": "71c34763-d1e7-4b9a-a9d7-3e4cc0dfc2c4",
"metadata": {},
"source": [
"## [JSON mode](https://platform.openai.com/docs/guides/text-generation/json-mode)\n",
"\n",
"Constrain the model to only generate valid JSON. Note that you must include a system message with instructions to use JSON for this mode to work.\n",
"\n",
"Only works with certain models. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "db6072c4-f3f3-415d-872b-71ea9f3c02bb",
"metadata": {},
"outputs": [],
"source": [
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\").bind(\n",
" response_format={\"type\": \"json_object\"}\n",
")\n",
"\n",
"output = chat.invoke(\n",
" [\n",
" SystemMessage(\n",
" content=\"Extract the 'name' and 'origin' of any companies mentioned in the following statement. Return a JSON list.\"\n",
" ),\n",
" HumanMessage(\n",
" content=\"Google was founded in the USA, while Deepmind was founded in the UK\"\n",
" ),\n",
" ]\n",
")\n",
"print(output.content)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "08e00ccf-b991-4249-846b-9500a0ccbfa0",
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"json.loads(output.content)"
]
},
{
"cell_type": "markdown",
"id": "aa9a94d9-4319-4ab7-a979-c475ce6b5f50",
"metadata": {},
"source": [
"## [System fingerprint](https://platform.openai.com/docs/guides/text-generation/reproducible-outputs)\n",
"\n",
"OpenAI sometimes changes model configurations in a way that impacts outputs. Whenever this happens, the system_fingerprint associated with a generation will change."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1281883c-bf8f-4665-89cd-4f33ccde69ab",
"metadata": {},
"outputs": [],
"source": [
"chat = ChatOpenAI(model=\"gpt-3.5-turbo-1106\")\n",
"output = chat.generate(\n",
" [\n",
" [\n",
" SystemMessage(\n",
" content=\"Extract the 'name' and 'origin' of any companies mentioned in the following statement. Return a JSON list.\"\n",
" ),\n",
" HumanMessage(\n",
" content=\"Google was founded in the USA, while Deepmind was founded in the UK\"\n",
" ),\n",
" ]\n",
" ]\n",
")\n",
"print(output.llm_output)"
]
},
{
"cell_type": "markdown",
"id": "aa6565be-985d-4127-848e-c3bca9d7b434",
"metadata": {},
"source": [
"## Breaking changes to Azure classes\n",
"\n",
"OpenAI V1 rewrote their clients and separated Azure and OpenAI clients. This has led to some changes in LangChain interfaces when using OpenAI V1.\n",
"\n",
"BREAKING CHANGES:\n",
"- To use Azure embeddings with OpenAI V1, you'll need to use the new `AzureOpenAIEmbeddings` instead of the existing `OpenAIEmbeddings`. `OpenAIEmbeddings` continue to work when using Azure with `openai<1`.\n",
"```python\n",
"from langchain.embeddings import AzureOpenAIEmbeddings\n",
"```\n",
"\n",
"\n",
"RECOMMENDED CHANGES:\n",
"- When using AzureChatOpenAI, if passing in an Azure endpoint (eg https://example-resource.azure.openai.com/) this should be specified via the `azure_endpoint` parameter or the `AZURE_OPENAI_ENDPOINT`. We're maintaining backwards compatibility for now with specifying this via `openai_api_base`/`base_url` or env var `OPENAI_API_BASE` but this shouldn't be relied upon.\n",
"- When using Azure chat or embedding models, pass in API keys either via `openai_api_key` parameter or `AZURE_OPENAI_API_KEY` parameter. We're maintaining backwards compatibility for now with specifying this via `OPENAI_API_KEY` but this shouldn't be relied upon."
]
},
{
"cell_type": "markdown",
"id": "49944887-3972-497e-8da2-6d32d44345a9",
"metadata": {},
"source": [
"## Tools\n",
"\n",
"Use tools for parallel function calling."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "916292d8-0f89-40a6-af1c-5a1122327de8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[GetCurrentWeather(location='New York, NY', unit='fahrenheit'),\n",
" GetCurrentWeather(location='Los Angeles, CA', unit='fahrenheit'),\n",
" GetCurrentWeather(location='San Francisco, CA', unit='fahrenheit')]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from typing import Literal\n",
"\n",
"from langchain.output_parsers.openai_tools import PydanticToolsParser\n",
"from langchain.utils.openai_functions import convert_pydantic_to_openai_tool\n",
"from langchain.prompts import ChatPromptTemplate\n",
"from langchain.pydantic_v1 import BaseModel, Field\n",
"\n",
"\n",
"class GetCurrentWeather(BaseModel):\n",
" \"\"\"Get the current weather in a location.\"\"\"\n",
"\n",
" location: str = Field(description=\"The city and state, e.g. San Francisco, CA\")\n",
" unit: Literal[\"celsius\", \"fahrenheit\"] = Field(\n",
" default=\"fahrenheit\", description=\"The temperature unit, default to fahrenheit\"\n",
" )\n",
"\n",
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", \"You are a helpful assistant\"), (\"user\", \"{input}\")]\n",
")\n",
"model = ChatOpenAI(model=\"gpt-3.5-turbo-1106\").bind(\n",
" tools=[convert_pydantic_to_openai_tool(GetCurrentWeather)]\n",
")\n",
"chain = prompt | model | PydanticToolsParser(tools=[GetCurrentWeather])\n",
"\n",
"chain.invoke({\"input\": \"what's the weather in NYC, LA, and SF\"})"
]
}
],
"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

@@ -34,7 +34,11 @@
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.llms import OpenAI\n",
"from langchain.utilities import DuckDuckGoSearchAPIWrapper\n",
"from langchain_experimental.plan_and_execute import PlanAndExecute, load_agent_executor, load_chat_planner"
"from langchain_experimental.plan_and_execute import (\n",
" PlanAndExecute,\n",
" load_agent_executor,\n",
" load_chat_planner,\n",
")"
]
},
{
@@ -56,16 +60,16 @@
"llm = OpenAI(temperature=0)\n",
"llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)\n",
"tools = [\n",
" Tool(\n",
" name=\"Search\",\n",
" func=search.run,\n",
" description=\"useful for when you need to answer questions about current events\"\n",
" ),\n",
" Tool(\n",
" name=\"Calculator\",\n",
" func=llm_math_chain.run,\n",
" description=\"useful for when you need to answer questions about math\"\n",
" ),\n",
" Tool(\n",
" name=\"Search\",\n",
" func=search.run,\n",
" description=\"useful for when you need to answer questions about current events\",\n",
" ),\n",
" Tool(\n",
" name=\"Calculator\",\n",
" func=llm_math_chain.run,\n",
" description=\"useful for when you need to answer questions about math\",\n",
" ),\n",
"]"
]
},
@@ -216,7 +220,9 @@
}
],
"source": [
"agent.run(\"Who is the current prime minister of the UK? What is their current age raised to the 0.43 power?\")"
"agent.run(\n",
" \"Who is the current prime minister of the UK? What is their current age raised to the 0.43 power?\"\n",
")"
]
},
{

View File

@@ -55,6 +55,7 @@
"source": [
"# Setup API keys for Kay and OpenAI\n",
"from getpass import getpass\n",
"\n",
"KAY_API_KEY = getpass()\n",
"OPENAI_API_KEY = getpass()"
]
@@ -67,6 +68,7 @@
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ[\"KAY_API_KEY\"] = KAY_API_KEY\n",
"os.environ[\"OPENAI_API_KEY\"] = OPENAI_API_KEY"
]
@@ -83,7 +85,9 @@
"from langchain.retrievers import KayAiRetriever\n",
"\n",
"model = ChatOpenAI(model_name=\"gpt-3.5-turbo\")\n",
"retriever = KayAiRetriever.create(dataset_id=\"company\", data_types=[\"PressRelease\"], num_contexts=6)\n",
"retriever = KayAiRetriever.create(\n",
" dataset_id=\"company\", data_types=[\"PressRelease\"], num_contexts=6\n",
")\n",
"qa = ConversationalRetrievalChain.from_llm(model, retriever=retriever)"
]
},
@@ -116,7 +120,7 @@
"# More sample questions in the Playground on https://kay.ai\n",
"questions = [\n",
" \"How is the healthcare industry adopting generative AI tools?\",\n",
" #\"What are some recent challenges faced by the renewable energy sector?\",\n",
" # \"What are some recent challenges faced by the renewable energy sector?\",\n",
"]\n",
"chat_history = []\n",
"\n",

View File

@@ -0,0 +1,168 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# RAG based on Qianfan and BES"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook is an implementation of Retrieval augmented generation (RAG) using Baidu Qianfan Platform combined with Baidu ElasricSearch, where the original data is located on BOS.\n",
"## Baidu Qianfan\n",
"Baidu AI Cloud Qianfan Platform is a one-stop large model development and service operation platform for enterprise developers. Qianfan not only provides including the model of Wenxin Yiyan (ERNIE-Bot) and the third-party open-source models, but also provides various AI development tools and the whole set of development environment, which facilitates customers to use and develop large model applications easily.\n",
"\n",
"## Baidu ElasticSearch\n",
"[Baidu Cloud VectorSearch](https://cloud.baidu.com/doc/BES/index.html?from=productToDoc) is a fully managed, enterprise-level distributed search and analysis service which is 100% compatible to open source. Baidu Cloud VectorSearch provides low-cost, high-performance, and reliable retrieval and analysis platform level product services for structured/unstructured data. As a vector database , it supports multiple index types and similarity distance methods. "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Installation and Setup\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#!pip install qianfan\n",
"#!pip install bce-python-sdk\n",
"#!pip install elasticsearch == 7.11.0"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Imports"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from baidubce.bce_client_configuration import BceClientConfiguration\n",
"from baidubce.auth.bce_credentials import BceCredentials\n",
"from langchain.document_loaders.baiducloud_bos_directory import BaiduBOSDirectoryLoader\n",
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"from langchain.embeddings.huggingface import HuggingFaceEmbeddings\n",
"from langchain.vectorstores import BESVectorStore\n",
"from langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Document loading"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"bos_host = \"your bos eddpoint\"\n",
"access_key_id = \"your bos access ak\"\n",
"secret_access_key = \"your bos access sk\"\n",
"\n",
"# create BceClientConfiguration\n",
"config = BceClientConfiguration(credentials=BceCredentials(access_key_id, secret_access_key), endpoint = bos_host)\n",
"\n",
"loader = BaiduBOSDirectoryLoader(conf=config, bucket=\"llm-test\", prefix=\"llm/\")\n",
"documents = loader.load()\n",
"\n",
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=0)\n",
"split_docs = text_splitter.split_documents(documents)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Embedding and VectorStore"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"embeddings = HuggingFaceEmbeddings(model_name=\"shibing624/text2vec-base-chinese\")\n",
"embeddings.client = sentence_transformers.SentenceTransformer(embeddings.model_name)\n",
"\n",
"db = BESVectorStore.from_documents(\n",
" documents=split_docs, embedding=embeddings, bes_url=\"your bes url\", index_name='test-index', vector_query_field='vector'\n",
" )\n",
"\n",
"db.client.indices.refresh(index='test-index')\n",
"retriever = db.as_retriever()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## QA Retriever"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"llm = QianfanLLMEndpoint(model=\"ERNIE-Bot\", qianfan_ak='your qianfan ak', qianfan_sk='your qianfan sk', streaming=True)\n",
"qa = RetrievalQA.from_chain_type(llm=llm, chain_type=\"refine\", retriever=retriever, return_source_documents=True)\n",
"\n",
"query = \"什么是张量?\"\n",
"print(qa.run(query))"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"> 张量Tensor是一个数学概念用于表示多维数据。它是一个可以表示多个数值的数组可以是标量、向量、矩阵等。在深度学习和人工智能领域中张量常用于表示神经网络的输入、输出和权重等。"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.9.17"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -33,7 +33,7 @@
"from langchain.vectorstores import Pinecone\n",
"from langchain.embeddings import OpenAIEmbeddings\n",
"\n",
"pinecone.init(api_key=\"...\",environment=\"...\")"
"pinecone.init(api_key=\"...\", environment=\"...\")"
]
},
{
@@ -53,7 +53,7 @@
" \"doc7\": \"Climate change: The science and models.\",\n",
" \"doc8\": \"Global warming: A subset of climate change.\",\n",
" \"doc9\": \"How climate change affects daily weather.\",\n",
" \"doc10\": \"The history of climate change activism.\"\n",
" \"doc10\": \"The history of climate change activism.\",\n",
"}"
]
},
@@ -64,7 +64,9 @@
"metadata": {},
"outputs": [],
"source": [
"vectorstore = Pinecone.from_texts(list(all_documents.values()), OpenAIEmbeddings(), index_name='rag-fusion')"
"vectorstore = Pinecone.from_texts(\n",
" list(all_documents.values()), OpenAIEmbeddings(), index_name=\"rag-fusion\"\n",
")"
]
},
{
@@ -98,7 +100,7 @@
"source": [
"from langchain import hub\n",
"\n",
"prompt = hub.pull('langchain-ai/rag-fusion-query-generation')"
"prompt = hub.pull(\"langchain-ai/rag-fusion-query-generation\")"
]
},
{
@@ -122,7 +124,9 @@
"metadata": {},
"outputs": [],
"source": [
"generate_queries = prompt | ChatOpenAI(temperature=0) | StrOutputParser() | (lambda x: x.split(\"\\n\"))"
"generate_queries = (\n",
" prompt | ChatOpenAI(temperature=0) | StrOutputParser() | (lambda x: x.split(\"\\n\"))\n",
")"
]
},
{
@@ -171,6 +175,8 @@
"outputs": [],
"source": [
"from langchain.load import dumps, loads\n",
"\n",
"\n",
"def reciprocal_rank_fusion(results: list[list], k=60):\n",
" fused_scores = {}\n",
" for docs in results:\n",
@@ -181,9 +187,12 @@
" fused_scores[doc_str] = 0\n",
" previous_score = fused_scores[doc_str]\n",
" fused_scores[doc_str] += 1 / (rank + k)\n",
" \n",
" reranked_results = [(loads(doc), score) for doc, score in sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)]\n",
" return reranked_results "
"\n",
" reranked_results = [\n",
" (loads(doc), score)\n",
" for doc, score in sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)\n",
" ]\n",
" return reranked_results"
]
},
{

View File

@@ -0,0 +1,688 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Incoporating semantic similarity in tabular databases\n",
"\n",
"In this notebook we will cover how to run semantic search over a specific table column within a single SQL query, combining tabular query with RAG.\n",
"\n",
"\n",
"### Overall workflow\n",
"\n",
"1. Generating embeddings for a specific column\n",
"2. Storing the embeddings in a new column (if column has low cardinality, it's better to use another table containing unique values and their embeddings)\n",
"3. Querying using standard SQL queries with [PGVector](https://github.com/pgvector/pgvector) extension which allows using L2 distance (`<->`), Cosine distance (`<=>` or cosine similarity using `1 - <=>`) and Inner product (`<#>`)\n",
"4. Running standard SQL query\n",
"\n",
"### Requirements\n",
"\n",
"We will need a PostgreSQL database with [pgvector](https://github.com/pgvector/pgvector) extension enabled. For this example, we will use a `Chinook` database using a local PostgreSQL server."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import getpass\n",
"\n",
"os.environ[\"OPENAI_API_KEY\"] = os.environ.get(\"OPENAI_API_KEY\") or getpass.getpass(\n",
" \"OpenAI API Key:\"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain.sql_database import SQLDatabase\n",
"from langchain.chat_models import ChatOpenAI\n",
"\n",
"CONNECTION_STRING = \"postgresql+psycopg2://postgres:test@localhost:5432/vectordb\" # Replace with your own\n",
"db = SQLDatabase.from_uri(CONNECTION_STRING)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Embedding the song titles"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"For this example, we will run queries based on semantic meaning of song titles. In order to do this, let's start by adding a new column in the table for storing the embeddings:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# db.run('ALTER TABLE \"Track\" ADD COLUMN \"embeddings\" vector;')"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's generate the embedding for each *track title* and store it as a new column in our \"Track\" table"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from langchain.embeddings import OpenAIEmbeddings\n",
"\n",
"embeddings_model = OpenAIEmbeddings()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3503"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tracks = db.run('SELECT \"Name\" FROM \"Track\"')\n",
"song_titles = [s[0] for s in eval(tracks)]\n",
"title_embeddings = embeddings_model.embed_documents(song_titles)\n",
"len(title_embeddings)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's insert the embeddings in the into the new column from our table"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from tqdm import tqdm\n",
"\n",
"for i in tqdm(range(len(title_embeddings))):\n",
" title = titles[i].replace(\"'\", \"''\")\n",
" embedding = title_embeddings[i]\n",
" sql_command = (\n",
" f'UPDATE \"Track\" SET \"embeddings\" = ARRAY{embedding} WHERE \"Name\" ='\n",
" + f\"'{title}'\"\n",
" )\n",
" db.run(sql_command)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"We can test the semantic search running the following query:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'[(\"Tomorrow\\'s Dream\",), (\\'Remember Tomorrow\\',), (\\'Remember Tomorrow\\',), (\\'The Best Is Yet To Come\\',), (\"Thinking \\'Bout Tomorrow\",)]'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"embeded_title = embeddings_model.embed_query(\"hope about the future\")\n",
"query = (\n",
" 'SELECT \"Track\".\"Name\" FROM \"Track\" WHERE \"Track\".\"embeddings\" IS NOT NULL ORDER BY \"embeddings\" <-> '\n",
" + f\"'{embeded_title}' LIMIT 5\"\n",
")\n",
"db.run(query)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Creating the SQL Chain"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's start by defining useful functions to get info from database and running the query:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def get_schema(_):\n",
" return db.get_table_info()\n",
"\n",
"\n",
"def run_query(query):\n",
" return db.run(query)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's build the **prompt** we will use. This prompt is an extension from [text-to-postgres-sql](https://smith.langchain.com/hub/jacob/text-to-postgres-sql?organizationId=f9b614b8-5c3a-4e7c-afbc-6d7ad4fd8892) prompt"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"from langchain.prompts import ChatPromptTemplate\n",
"\n",
"template = \"\"\"You are a Postgres expert. Given an input question, first create a syntactically correct Postgres query to run, then look at the results of the query and return the answer to the input question.\n",
"Unless the user specifies in the question a specific number of examples to obtain, query for at most 5 results using the LIMIT clause as per Postgres. You can order the results to return the most informative data in the database.\n",
"Never query for all columns from a table. You must query only the columns that are needed to answer the question. Wrap each column name in double quotes (\") to denote them as delimited identifiers.\n",
"Pay attention to use only the column names you can see in the tables below. Be careful to not query for columns that do not exist. Also, pay attention to which column is in which table.\n",
"Pay attention to use date('now') function to get the current date, if the question involves \"today\".\n",
"\n",
"You can use an extra extension which allows you to run semantic similarity using <-> operator on tables containing columns named \"embeddings\".\n",
"<-> operator can ONLY be used on embeddings columns.\n",
"The embeddings value for a given row typically represents the semantic meaning of that row.\n",
"The vector represents an embedding representation of the question, given below. \n",
"Do NOT fill in the vector values directly, but rather specify a `[search_word]` placeholder, which should contain the word that would be embedded for filtering.\n",
"For example, if the user asks for songs about 'the feeling of loneliness' the query could be:\n",
"'SELECT \"[whatever_table_name]\".\"SongName\" FROM \"[whatever_table_name]\" ORDER BY \"embeddings\" <-> '[loneliness]' LIMIT 5'\n",
"\n",
"Use the following format:\n",
"\n",
"Question: <Question here>\n",
"SQLQuery: <SQL Query to run>\n",
"SQLResult: <Result of the SQLQuery>\n",
"Answer: <Final answer here>\n",
"\n",
"Only use the following tables:\n",
"\n",
"{schema}\n",
"\"\"\"\n",
"\n",
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", template), (\"human\", \"{question}\")]\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"And we can create the chain using **[LangChain Expression Language](https://python.langchain.com/docs/expression_language/)**:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain.schema.runnable import RunnablePassthrough\n",
"\n",
"db = SQLDatabase.from_uri(\n",
" CONNECTION_STRING\n",
") # We reconnect to db so the new columns are loaded as well.\n",
"llm = ChatOpenAI(model_name=\"gpt-4\", temperature=0)\n",
"\n",
"sql_query_chain = (\n",
" RunnablePassthrough.assign(schema=get_schema)\n",
" | prompt\n",
" | llm.bind(stop=[\"\\nSQLResult:\"])\n",
" | StrOutputParser()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'SQLQuery: SELECT \"Track\".\"Name\" FROM \"Track\" JOIN \"Genre\" ON \"Track\".\"GenreId\" = \"Genre\".\"GenreId\" WHERE \"Genre\".\"Name\" = \\'Rock\\' ORDER BY \"Track\".\"embeddings\" <-> \\'[dispair]\\' LIMIT 5'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sql_query_chain.invoke(\n",
" {\n",
" \"question\": \"Which are the 5 rock songs with titles about deep feeling of dispair?\"\n",
" }\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This chain simply generates the query. Now we will create the full chain that also handles the execution and the final result for the user:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"from langchain.schema.runnable import RunnableLambda\n",
"\n",
"\n",
"def replace_brackets(match):\n",
" words_inside_brackets = match.group(1).split(\", \")\n",
" embedded_words = [\n",
" str(embeddings_model.embed_query(word)) for word in words_inside_brackets\n",
" ]\n",
" return \"', '\".join(embedded_words)\n",
"\n",
"\n",
"def get_query(query):\n",
" sql_query = re.sub(r\"\\[([\\w\\s,]+)\\]\", replace_brackets, query)\n",
" return sql_query\n",
"\n",
"\n",
"template = \"\"\"Based on the table schema below, question, sql query, and sql response, write a natural language response:\n",
"{schema}\n",
"\n",
"Question: {question}\n",
"SQL Query: {query}\n",
"SQL Response: {response}\"\"\"\n",
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", template), (\"human\", \"{question}\")]\n",
")\n",
"\n",
"full_chain = (\n",
" RunnablePassthrough.assign(query=sql_query_chain)\n",
" | RunnablePassthrough.assign(\n",
" schema=get_schema,\n",
" response=RunnableLambda(lambda x: db.run(get_query(x[\"query\"]))),\n",
" )\n",
" | prompt\n",
" | llm\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using the Chain"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example 1: Filtering a column based on semantic meaning"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's say we want to retrieve songs that express `deep feeling of dispair`, but filtering based on genre:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"The 5 rock songs with titles that convey a deep feeling of despair are 'Sea Of Sorrow', 'Surrender', 'Indifference', 'Hard Luck Woman', and 'Desire'.\")"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"full_chain.invoke(\n",
" {\n",
" \"question\": \"Which are the 5 rock songs with titles about deep feeling of dispair?\"\n",
" }\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"What is substantially different in implementing this method is that we have combined:\n",
"- Semantic search (songs that have titles with some semantic meaning)\n",
"- Traditional tabular querying (running JOIN statements to filter track based on genre)\n",
"\n",
"This is something we _could_ potentially achieve using metadata filtering, but it's more complex to do so (we would need to use a vector database containing the embeddings, and use metadata filtering based on genre).\n",
"\n",
"However, for other use cases metadata filtering **wouldn't be enough**."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example 2: Combining filters"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"The three albums which have the most amount of songs in the top 150 saddest songs are 'International Superhits' with 5 songs, 'Ten' with 4 songs, and 'Album Of The Year' with 3 songs.\")"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"full_chain.invoke(\n",
" {\n",
" \"question\": \"I want to know the 3 albums which have the most amount of songs in the top 150 saddest songs\"\n",
" }\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"So we have result for 3 albums with most amount of songs in top 150 saddest ones. This **wouldn't** be possible using only standard metadata filtering. Without this _hybdrid query_, we would need some postprocessing to get the result.\n",
"\n",
"Another similar exmaple:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"The 6 albums with the shortest titles that contain songs which are in the 20 saddest song list are 'Ten', 'Core', 'Big Ones', 'One By One', 'Black Album', and 'Miles Ahead'.\")"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"full_chain.invoke(\n",
" {\n",
" \"question\": \"I need the 6 albums with shortest title, as long as they contain songs which are in the 20 saddest song list.\"\n",
" }\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see what the query looks like to double check:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WITH \"SadSongs\" AS (\n",
" SELECT \"TrackId\" FROM \"Track\" \n",
" ORDER BY \"embeddings\" <-> '[sad]' LIMIT 20\n",
"),\n",
"\"SadAlbums\" AS (\n",
" SELECT DISTINCT \"AlbumId\" FROM \"Track\" \n",
" WHERE \"TrackId\" IN (SELECT \"TrackId\" FROM \"SadSongs\")\n",
")\n",
"SELECT \"Album\".\"Title\" FROM \"Album\" \n",
"WHERE \"AlbumId\" IN (SELECT \"AlbumId\" FROM \"SadAlbums\") \n",
"ORDER BY \"title_len\" ASC \n",
"LIMIT 6\n"
]
}
],
"source": [
"print(\n",
" sql_query_chain.invoke(\n",
" {\n",
" \"question\": \"I need the 6 albums with shortest title, as long as they contain songs which are in the 20 saddest song list.\"\n",
" }\n",
" )\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example 3: Combining two separate semantic searches\n",
"\n",
"One interesting aspect of this approach which is **substantially different from using standar RAG** is that we can even **combine** two semantic search filters:\n",
"- _Get 5 saddest songs..._\n",
"- _**...obtained from albums with \"lovely\" titles**_\n",
"\n",
"This could generalize to **any kind of combined RAG** (paragraphs discussing _X_ topic belonging from books about _Y_, replies to a tweet about _ABC_ topic that express _XYZ_ feeling)\n",
"\n",
"We will combine semantic search on songs and album titles, so we need to do the same for `Album` table:\n",
"1. Generate the embeddings\n",
"2. Add them to the table as a new column (which we need to add in the table)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
"# db.run('ALTER TABLE \"Album\" ADD COLUMN \"embeddings\" vector;')"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 347/347 [00:01<00:00, 179.64it/s]\n"
]
}
],
"source": [
"albums = db.run('SELECT \"Title\" FROM \"Album\"')\n",
"album_titles = [title[0] for title in eval(albums)]\n",
"album_title_embeddings = embeddings_model.embed_documents(album_titles)\n",
"for i in tqdm(range(len(album_title_embeddings))):\n",
" album_title = album_titles[i].replace(\"'\", \"''\")\n",
" album_embedding = album_title_embeddings[i]\n",
" sql_command = (\n",
" f'UPDATE \"Album\" SET \"embeddings\" = ARRAY{album_embedding} WHERE \"Title\" ='\n",
" + f\"'{album_title}'\"\n",
" )\n",
" db.run(sql_command)"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"\"[('Realize',), ('Morning Dance',), ('Into The Light',), ('New Adventures In Hi-Fi',), ('Miles Ahead',)]\""
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"embeded_title = embeddings_model.embed_query(\"hope about the future\")\n",
"query = (\n",
" 'SELECT \"Album\".\"Title\" FROM \"Album\" WHERE \"Album\".\"embeddings\" IS NOT NULL ORDER BY \"embeddings\" <-> '\n",
" + f\"'{embeded_title}' LIMIT 5\"\n",
")\n",
"db.run(query)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can combine both filters:"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"db = SQLDatabase.from_uri(\n",
" CONNECTION_STRING\n",
") # We reconnect to dbso the new columns are loaded as well."
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='The songs about breakouts obtained from the top 5 albums about love are \\'Royal Orleans\\', \"Nobody\\'s Fault But Mine\", \\'Achilles Last Stand\\', \\'For Your Life\\', and \\'Hots On For Nowhere\\'.')"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"full_chain.invoke(\n",
" {\n",
" \"question\": \"I want to know songs about breakouts obtained from top 5 albums about love\"\n",
" }\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This is something **different** that **couldn't be achieved** using standard metadata filtering over a vectordb."
]
}
],
"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.18"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -74,9 +74,9 @@
"outputs": [],
"source": [
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")"
]
@@ -245,6 +245,7 @@
"source": [
"# Parser to remove the `**`\n",
"\n",
"\n",
"def _parse(text):\n",
" return text.strip(\"**\")"
]
@@ -290,9 +291,10 @@
"rewrite_retrieve_read_chain = (\n",
" {\n",
" \"context\": {\"x\": RunnablePassthrough()} | rewriter | retriever,\n",
" \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" \"question\": RunnablePassthrough(),\n",
" }\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")"
]

View File

@@ -0,0 +1,177 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e93283d1",
"metadata": {},
"source": [
"# Selecting LLMs based on Context Length\n",
"\n",
"Different LLMs have different context lengths. As a very immediate an practical example, OpenAI has two versions of GPT-3.5-Turbo: one with 4k context, another with 16k context. This notebook shows how to route between them based on input."
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "cc453450",
"metadata": {},
"outputs": [],
"source": [
"from langchain.prompts import PromptTemplate\n",
"from langchain.schema.prompt import PromptValue\n",
"from langchain.schema.messages import BaseMessage\n",
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from typing import Union, Sequence"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1cec6a10",
"metadata": {},
"outputs": [],
"source": [
"short_context_model = ChatOpenAI(model=\"gpt-3.5-turbo\")\n",
"long_context_model = ChatOpenAI(model=\"gpt-3.5-turbo-16k\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "772da153",
"metadata": {},
"outputs": [],
"source": [
"def get_context_length(prompt: PromptValue):\n",
" messages = prompt.to_messages()\n",
" tokens = short_context_model.get_num_tokens_from_messages(messages)\n",
" return tokens"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "db771e20",
"metadata": {},
"outputs": [],
"source": [
"prompt = PromptTemplate.from_template(\"Summarize this passage: {context}\")"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "af057e2f",
"metadata": {},
"outputs": [],
"source": [
"def choose_model(prompt: PromptValue):\n",
" context_len = get_context_length(prompt)\n",
" if context_len < 30:\n",
" print(\"short model\")\n",
" return short_context_model\n",
" else:\n",
" print(\"long model\")\n",
" return long_context_model"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "84f3e07d",
"metadata": {},
"outputs": [],
"source": [
"chain = prompt | choose_model | StrOutputParser()"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "d8b14f8f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"short model\n"
]
},
{
"data": {
"text/plain": [
"'The passage mentions that a frog visited a pond.'"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke({\"context\": \"a frog went to a pond\"})"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "70ebd3dd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"long model\n"
]
},
{
"data": {
"text/plain": [
"'The passage describes a frog that moved from one pond to another and perched on a log.'"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chain.invoke(\n",
" {\"context\": \"a frog went to a pond and sat on a log and went to a different pond\"}\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a7e29fef",
"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.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -7,9 +7,33 @@
"source": [
"# Building hotel room search with self-querying retrieval\n",
"\n",
"In this example we'll walk through how to build and iterate on a hotel room search service that leverages an LLM to generate structured filter queries that can then be passed to a vector store.\n",
"\n",
"For an introduction to self-querying retrieval [check out the docs](https://python.langchain.com/docs/modules/data_connection/retrievers/self_query)."
]
},
{
"cell_type": "markdown",
"id": "d621de99-d993-4f4b-b94a-d02b2c7ad4e0",
"metadata": {},
"source": [
"## Imports and data prep\n",
"\n",
"In this example we use `ChatOpenAI` for the model and `ElasticsearchStore` for the vector store, but these can be swapped out with an LLM/ChatModel and [any VectorStore that support self-querying](https://python.langchain.com/docs/integrations/retrievers/self_query/).\n",
"\n",
"Download data from: https://www.kaggle.com/datasets/keshavramaiah/hotel-recommendation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ecd1fbb-bdba-420b-bcc7-5ea8a232ab11",
"metadata": {},
"outputs": [],
"source": [
"!pip install langchain lark openai elasticsearch pandas"
]
},
{
"cell_type": "code",
"execution_count": 1,
@@ -27,8 +51,14 @@
"metadata": {},
"outputs": [],
"source": [
"details = pd.read_csv(\"~/Downloads/archive/Hotel_details.csv\").drop_duplicates(subset=\"hotelid\").set_index(\"hotelid\")\n",
"attributes = pd.read_csv(\"~/Downloads/archive/Hotel_Room_attributes.csv\", index_col=\"id\")\n",
"details = (\n",
" pd.read_csv(\"~/Downloads/archive/Hotel_details.csv\")\n",
" .drop_duplicates(subset=\"hotelid\")\n",
" .set_index(\"hotelid\")\n",
")\n",
"attributes = pd.read_csv(\n",
" \"~/Downloads/archive/Hotel_Room_attributes.csv\", index_col=\"id\"\n",
")\n",
"price = pd.read_csv(\"~/Downloads/archive/hotels_RoomPrice.csv\", index_col=\"id\")"
]
},
@@ -184,9 +214,20 @@
}
],
"source": [
"latest_price = price.drop_duplicates(subset=\"refid\", keep=\"last\")[[\"hotelcode\", \"roomtype\", \"onsiterate\", \"roomamenities\", \"maxoccupancy\", \"mealinclusiontype\"]]\n",
"latest_price = price.drop_duplicates(subset=\"refid\", keep=\"last\")[\n",
" [\n",
" \"hotelcode\",\n",
" \"roomtype\",\n",
" \"onsiterate\",\n",
" \"roomamenities\",\n",
" \"maxoccupancy\",\n",
" \"mealinclusiontype\",\n",
" ]\n",
"]\n",
"latest_price[\"ratedescription\"] = attributes.loc[latest_price.index][\"ratedescription\"]\n",
"latest_price = latest_price.join(details[[\"hotelname\", \"city\", \"country\", \"starrating\"]], on=\"hotelcode\")\n",
"latest_price = latest_price.join(\n",
" details[[\"hotelname\", \"city\", \"country\", \"starrating\"]], on=\"hotelcode\"\n",
")\n",
"latest_price = latest_price.rename({\"ratedescription\": \"roomdescription\"}, axis=1)\n",
"latest_price[\"mealsincluded\"] = ~latest_price[\"mealinclusiontype\"].isnull()\n",
"latest_price.pop(\"hotelcode\")\n",
@@ -220,7 +261,7 @@
"res = model.predict(\n",
" \"Below is a table with information about hotel rooms. \"\n",
" \"Return a JSON list with an entry for each column. Each entry should have \"\n",
" \"{\\\"name\\\": \\\"column name\\\", \\\"description\\\": \\\"column description\\\", \\\"type\\\": \\\"column data type\\\"}\"\n",
" '{\"name\": \"column name\", \"description\": \"column description\", \"type\": \"column data type\"}'\n",
" f\"\\n\\n{latest_price.head()}\\n\\nJSON:\\n\"\n",
")"
]
@@ -314,9 +355,15 @@
"metadata": {},
"outputs": [],
"source": [
"attribute_info[-2]['description'] += f\". Valid values are {sorted(latest_price['starrating'].value_counts().index.tolist())}\"\n",
"attribute_info[3]['description'] += f\". Valid values are {sorted(latest_price['maxoccupancy'].value_counts().index.tolist())}\"\n",
"attribute_info[-3]['description'] += f\". Valid values are {sorted(latest_price['country'].value_counts().index.tolist())}\""
"attribute_info[-2][\n",
" \"description\"\n",
"] += f\". Valid values are {sorted(latest_price['starrating'].value_counts().index.tolist())}\"\n",
"attribute_info[3][\n",
" \"description\"\n",
"] += f\". Valid values are {sorted(latest_price['maxoccupancy'].value_counts().index.tolist())}\"\n",
"attribute_info[-3][\n",
" \"description\"\n",
"] += f\". Valid values are {sorted(latest_price['country'].value_counts().index.tolist())}\""
]
},
{
@@ -384,7 +431,10 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains.query_constructor.base import get_query_constructor_prompt, load_query_constructor_runnable"
"from langchain.chains.query_constructor.base import (\n",
" get_query_constructor_prompt,\n",
" load_query_constructor_runnable,\n",
")"
]
},
{
@@ -568,7 +618,9 @@
"metadata": {},
"outputs": [],
"source": [
"chain = load_query_constructor_runnable(ChatOpenAI(model='gpt-3.5-turbo', temperature=0), doc_contents, attribute_info)"
"chain = load_query_constructor_runnable(\n",
" ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0), doc_contents, attribute_info\n",
")"
]
},
{
@@ -610,7 +662,11 @@
}
],
"source": [
"chain.invoke({\"query\": \"Find a 2-person room in Vienna or London, preferably with meals included and AC\"})"
"chain.invoke(\n",
" {\n",
" \"query\": \"Find a 2-person room in Vienna or London, preferably with meals included and AC\"\n",
" }\n",
")"
]
},
{
@@ -632,10 +688,12 @@
"metadata": {},
"outputs": [],
"source": [
"attribute_info[-3]['description'] += \". NOTE: Only use the 'eq' operator if a specific country is mentioned. If a region is mentioned, include all relevant countries in filter.\"\n",
"attribute_info[-3][\n",
" \"description\"\n",
"] += \". NOTE: Only use the 'eq' operator if a specific country is mentioned. If a region is mentioned, include all relevant countries in filter.\"\n",
"chain = load_query_constructor_runnable(\n",
" ChatOpenAI(model='gpt-3.5-turbo', temperature=0), \n",
" doc_contents, \n",
" ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0),\n",
" doc_contents,\n",
" attribute_info,\n",
")"
]
@@ -680,10 +738,12 @@
"source": [
"content_attr = [\"roomtype\", \"roomamenities\", \"roomdescription\", \"hotelname\"]\n",
"doc_contents = \"A detailed description of a hotel room, including information about the room type and room amenities.\"\n",
"filter_attribute_info = tuple(ai for ai in attribute_info if ai[\"name\"] not in content_attr)\n",
"filter_attribute_info = tuple(\n",
" ai for ai in attribute_info if ai[\"name\"] not in content_attr\n",
")\n",
"chain = load_query_constructor_runnable(\n",
" ChatOpenAI(model='gpt-3.5-turbo', temperature=0), \n",
" doc_contents, \n",
" ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0),\n",
" doc_contents,\n",
" filter_attribute_info,\n",
")"
]
@@ -706,7 +766,11 @@
}
],
"source": [
"chain.invoke({\"query\": \"Find a 2-person room in Vienna or London, preferably with meals included and AC\"})"
"chain.invoke(\n",
" {\n",
" \"query\": \"Find a 2-person room in Vienna or London, preferably with meals included and AC\"\n",
" }\n",
")"
]
},
{
@@ -836,14 +900,22 @@
"examples = [\n",
" (\n",
" \"I want a hotel in the Balkans with a king sized bed and a hot tub. Budget is $300 a night\",\n",
" {\"query\": \"king-sized bed, hot tub\", \"filter\": 'and(in(\"country\", [\"Bulgaria\", \"Greece\", \"Croatia\", \"Serbia\"]), lte(\"onsiterate\", 300))'}\n",
" {\n",
" \"query\": \"king-sized bed, hot tub\",\n",
" \"filter\": 'and(in(\"country\", [\"Bulgaria\", \"Greece\", \"Croatia\", \"Serbia\"]), lte(\"onsiterate\", 300))',\n",
" },\n",
" ),\n",
" (\n",
" \"A room with breakfast included for 3 people, at a Hilton\",\n",
" {\"query\": \"Hilton\", \"filter\": 'and(eq(\"mealsincluded\", true), gte(\"maxoccupancy\", 3))'}\n",
" {\n",
" \"query\": \"Hilton\",\n",
" \"filter\": 'and(eq(\"mealsincluded\", true), gte(\"maxoccupancy\", 3))',\n",
" },\n",
" ),\n",
"]\n",
"prompt = get_query_constructor_prompt(doc_contents, filter_attribute_info, examples=examples)\n",
"prompt = get_query_constructor_prompt(\n",
" doc_contents, filter_attribute_info, examples=examples\n",
")\n",
"print(prompt.format(query=\"{query}\"))"
]
},
@@ -855,10 +927,10 @@
"outputs": [],
"source": [
"chain = load_query_constructor_runnable(\n",
" ChatOpenAI(model='gpt-3.5-turbo', temperature=0), \n",
" doc_contents, \n",
" ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0),\n",
" doc_contents,\n",
" filter_attribute_info,\n",
" examples=examples\n",
" examples=examples,\n",
")"
]
},
@@ -880,7 +952,11 @@
}
],
"source": [
"chain.invoke({\"query\": \"Find a 2-person room in Vienna or London, preferably with meals included and AC\"})"
"chain.invoke(\n",
" {\n",
" \"query\": \"Find a 2-person room in Vienna or London, preferably with meals included and AC\"\n",
" }\n",
")"
]
},
{
@@ -932,7 +1008,11 @@
}
],
"source": [
"chain.invoke({\"query\": \"I want to stay somewhere highly rated along the coast. I want a room with a patio and a fireplace.\"})"
"chain.invoke(\n",
" {\n",
" \"query\": \"I want to stay somewhere highly rated along the coast. I want a room with a patio and a fireplace.\"\n",
" }\n",
")"
]
},
{
@@ -953,11 +1033,11 @@
"outputs": [],
"source": [
"chain = load_query_constructor_runnable(\n",
" ChatOpenAI(model='gpt-3.5-turbo', temperature=0), \n",
" doc_contents, \n",
" ChatOpenAI(model=\"gpt-3.5-turbo\", temperature=0),\n",
" doc_contents,\n",
" filter_attribute_info,\n",
" examples=examples,\n",
" fix_invalid=True\n",
" fix_invalid=True,\n",
")"
]
},
@@ -979,7 +1059,11 @@
}
],
"source": [
"chain.invoke({\"query\": \"I want to stay somewhere highly rated along the coast. I want a room with a patio and a fireplace.\"})"
"chain.invoke(\n",
" {\n",
" \"query\": \"I want to stay somewhere highly rated along the coast. I want a room with a patio and a fireplace.\"\n",
" }\n",
")"
]
},
{
@@ -1032,8 +1116,8 @@
"# docs.append(doc)\n",
"# vecstore = ElasticsearchStore.from_documents(\n",
"# docs,\n",
"# embeddings, \n",
"# es_url=\"http://localhost:9200\", \n",
"# embeddings,\n",
"# es_url=\"http://localhost:9200\",\n",
"# index_name=\"hotel_rooms\",\n",
"# # strategy=ElasticsearchStore.ApproxRetrievalStrategy(\n",
"# # hybrid=True,\n",
@@ -1049,9 +1133,9 @@
"outputs": [],
"source": [
"vecstore = ElasticsearchStore(\n",
" \"hotel_rooms\", \n",
" embedding=embeddings, \n",
" es_url=\"http://localhost:9200\", \n",
" \"hotel_rooms\",\n",
" embedding=embeddings,\n",
" es_url=\"http://localhost:9200\",\n",
" # strategy=ElasticsearchStore.ApproxRetrievalStrategy(hybrid=True) # seems to not be available in community version\n",
")"
]
@@ -1065,7 +1149,9 @@
"source": [
"from langchain.retrievers import SelfQueryRetriever\n",
"\n",
"retriever = SelfQueryRetriever(query_constructor=chain, vectorstore=vecstore, verbose=True)"
"retriever = SelfQueryRetriever(\n",
" query_constructor=chain, vectorstore=vecstore, verbose=True\n",
")"
]
},
{
@@ -1142,7 +1228,9 @@
}
],
"source": [
"results = retriever.get_relevant_documents(\"I want to stay somewhere highly rated along the coast. I want a room with a patio and a fireplace.\")\n",
"results = retriever.get_relevant_documents(\n",
" \"I want to stay somewhere highly rated along the coast. I want a room with a patio and a fireplace.\"\n",
")\n",
"for res in results:\n",
" print(res.page_content)\n",
" print(\"\\n\" + \"-\" * 20 + \"\\n\")"

View File

@@ -40,11 +40,11 @@
"examples = [\n",
" {\n",
" \"input\": \"Could the members of The Police perform lawful arrests?\",\n",
" \"output\": \"what can the members of The Police do?\"\n",
" \"output\": \"what can the members of The Police do?\",\n",
" },\n",
" {\n",
" \"input\": \"Jan Sindels was born in what country?\", \n",
" \"output\": \"what is Jan Sindels personal history?\"\n",
" \"input\": \"Jan Sindels was born in what country?\",\n",
" \"output\": \"what is Jan Sindels personal history?\",\n",
" },\n",
"]\n",
"# We now transform these to example messages\n",
@@ -67,13 +67,18 @@
"metadata": {},
"outputs": [],
"source": [
"prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"\"\"You are an expert at world knowledge. Your task is to step back and paraphrase a question to a more generic step-back question, which is easier to answer. Here are a few examples:\"\"\"),\n",
" # Few shot examples\n",
" few_shot_prompt,\n",
" # New question\n",
" (\"user\", \"{question}\"),\n",
"])"
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"\"\"You are an expert at world knowledge. Your task is to step back and paraphrase a question to a more generic step-back question, which is easier to answer. Here are a few examples:\"\"\",\n",
" ),\n",
" # Few shot examples\n",
" few_shot_prompt,\n",
" # New question\n",
" (\"user\", \"{question}\"),\n",
" ]\n",
")"
]
},
{
@@ -129,6 +134,7 @@
"\n",
"search = DuckDuckGoSearchAPIWrapper(max_results=4)\n",
"\n",
"\n",
"def retriever(query):\n",
" return search.run(query)"
]
@@ -211,14 +217,19 @@
"metadata": {},
"outputs": [],
"source": [
"chain = {\n",
" # Retrieve context using the normal question\n",
" \"normal_context\": RunnableLambda(lambda x: x['question']) | retriever,\n",
" # Retrieve context using the step-back question\n",
" \"step_back_context\": question_gen | retriever,\n",
" # Pass on the question\n",
" \"question\": lambda x: x[\"question\"]\n",
"} | response_prompt | ChatOpenAI(temperature=0) | StrOutputParser()"
"chain = (\n",
" {\n",
" # Retrieve context using the normal question\n",
" \"normal_context\": RunnableLambda(lambda x: x[\"question\"]) | retriever,\n",
" # Retrieve context using the step-back question\n",
" \"step_back_context\": question_gen | retriever,\n",
" # Pass on the question\n",
" \"question\": lambda x: x[\"question\"],\n",
" }\n",
" | response_prompt\n",
" | ChatOpenAI(temperature=0)\n",
" | StrOutputParser()\n",
")"
]
},
{
@@ -273,12 +284,17 @@
"metadata": {},
"outputs": [],
"source": [
"chain = {\n",
" # Retrieve context using the normal question (only the first 3 results)\n",
" \"normal_context\": RunnableLambda(lambda x: x['question']) | retriever,\n",
" # Pass on the question\n",
" \"question\": lambda x: x[\"question\"]\n",
"} | response_prompt | ChatOpenAI(temperature=0) | StrOutputParser()"
"chain = (\n",
" {\n",
" # Retrieve context using the normal question (only the first 3 results)\n",
" \"normal_context\": RunnableLambda(lambda x: x[\"question\"]) | retriever,\n",
" # Pass on the question\n",
" \"question\": lambda x: x[\"question\"],\n",
" }\n",
" | response_prompt\n",
" | ChatOpenAI(temperature=0)\n",
" | StrOutputParser()\n",
")"
]
},
{

View File

@@ -51,7 +51,7 @@
}
],
"source": [
"sudoku_puzzle = \"3,*,*,2|1,*,3,*|*,1,*,3|4,*,*,1\"\n",
"sudoku_puzzle = \"3,*,*,2|1,*,3,*|*,1,*,3|4,*,*,1\"\n",
"sudoku_solution = \"3,4,1,2|1,2,3,4|2,1,4,3|4,3,2,1\"\n",
"problem_description = f\"\"\"\n",
"{sudoku_puzzle}\n",
@@ -64,7 +64,7 @@
"- Keep the known digits from previous valid thoughts in place.\n",
"- Each thought can be a partial or the final solution.\n",
"\"\"\".strip()\n",
"print(problem_description)\n"
"print(problem_description)"
]
},
{
@@ -89,8 +89,11 @@
"from langchain_experimental.tot.thought import ThoughtValidity\n",
"import re\n",
"\n",
"\n",
"class MyChecker(ToTChecker):\n",
" def evaluate(self, problem_description: str, thoughts: Tuple[str, ...] = ()) -> ThoughtValidity:\n",
" def evaluate(\n",
" self, problem_description: str, thoughts: Tuple[str, ...] = ()\n",
" ) -> ThoughtValidity:\n",
" last_thought = thoughts[-1]\n",
" clean_solution = last_thought.replace(\" \", \"\").replace('\"', \"\")\n",
" regex_solution = clean_solution.replace(\"*\", \".\").replace(\"|\", \"\\\\|\")\n",
@@ -116,10 +119,22 @@
"outputs": [],
"source": [
"checker = MyChecker()\n",
"assert checker.evaluate(\"\", (\"3,*,*,2|1,*,3,*|*,1,*,3|4,*,*,1\",)) == ThoughtValidity.VALID_INTERMEDIATE\n",
"assert checker.evaluate(\"\", (\"3,4,1,2|1,2,3,4|2,1,4,3|4,3,2,1\",)) == ThoughtValidity.VALID_FINAL\n",
"assert checker.evaluate(\"\", (\"3,4,1,2|1,2,3,4|2,1,4,3|4,3,*,1\",)) == ThoughtValidity.VALID_INTERMEDIATE\n",
"assert checker.evaluate(\"\", (\"3,4,1,2|1,2,3,4|2,1,4,3|4,*,3,1\",)) == ThoughtValidity.INVALID"
"assert (\n",
" checker.evaluate(\"\", (\"3,*,*,2|1,*,3,*|*,1,*,3|4,*,*,1\",))\n",
" == ThoughtValidity.VALID_INTERMEDIATE\n",
")\n",
"assert (\n",
" checker.evaluate(\"\", (\"3,4,1,2|1,2,3,4|2,1,4,3|4,3,2,1\",))\n",
" == ThoughtValidity.VALID_FINAL\n",
")\n",
"assert (\n",
" checker.evaluate(\"\", (\"3,4,1,2|1,2,3,4|2,1,4,3|4,3,*,1\",))\n",
" == ThoughtValidity.VALID_INTERMEDIATE\n",
")\n",
"assert (\n",
" checker.evaluate(\"\", (\"3,4,1,2|1,2,3,4|2,1,4,3|4,*,3,1\",))\n",
" == ThoughtValidity.INVALID\n",
")"
]
},
{
@@ -203,7 +218,9 @@
"source": [
"from langchain_experimental.tot.base import ToTChain\n",
"\n",
"tot_chain = ToTChain(llm=llm, checker=MyChecker(), k=30, c=5, verbose=True, verbose_llm=False)\n",
"tot_chain = ToTChain(\n",
" llm=llm, checker=MyChecker(), k=30, c=5, verbose=True, verbose_llm=False\n",
")\n",
"tot_chain.run(problem_description=problem_description)"
]
},

View File

@@ -35,7 +35,7 @@
"tags": []
},
"source": [
"### API keys and other secrats\n",
"### API keys and other secrets\n",
"\n",
"We use an `.ini` file, like this: \n",
"```\n",

View File

@@ -15,7 +15,7 @@ poetry run python scripts/model_feat_table.py
poetry run nbdoc_build --srcdir docs
cp ../cookbook/README.md src/pages/cookbook.mdx
cp ../.github/CONTRIBUTING.md docs/contributing.md
wget https://raw.githubusercontent.com/langchain-ai/langserve/main/README.md -O docs/guides/deployments/langserve.md
wget https://raw.githubusercontent.com/langchain-ai/langserve/main/README.md -O docs/langserve.md
poetry run python scripts/generate_api_reference_links.py
yarn install
yarn start

View File

@@ -2,9 +2,9 @@
import importlib
import inspect
import typing
from pathlib import Path
from typing import TypedDict, Sequence, List, Dict, Literal, Union, Optional
from enum import Enum
from pathlib import Path
from typing import Dict, List, Literal, Optional, Sequence, TypedDict, Union
from pydantic import BaseModel

File diff suppressed because one or more lines are too long

View File

@@ -6,10 +6,13 @@ Below are links to tutorials and courses on LangChain. For written guides on com
---------------------
### [LangChain on Wikipedia](https://en.wikipedia.org/wiki/LangChain)
### DeepLearning.AI courses
by [Harrison Chase](https://github.com/hwchase17) and [Andrew Ng](https://en.wikipedia.org/wiki/Andrew_Ng)
by [Harrison Chase](https://en.wikipedia.org/wiki/LangChain) and [Andrew Ng](https://en.wikipedia.org/wiki/Andrew_Ng)
- [LangChain for LLM Application Development](https://learn.deeplearning.ai/langchain)
- [LangChain Chat with Your Data](https://learn.deeplearning.ai/langchain-chat-with-your-data)
- ⛓ [Functions, Tools and Agents with LangChain](https://learn.deeplearning.ai/functions-tools-agents-langchain)
### Handbook
[LangChain AI Handbook](https://www.pinecone.io/learn/langchain/) By **James Briggs** and **Francisco Ingham**

View File

@@ -115,7 +115,9 @@
"agent = (\n",
" {\n",
" \"question\": lambda x: x[\"question\"],\n",
" \"intermediate_steps\": lambda x: convert_intermediate_steps(x[\"intermediate_steps\"])\n",
" \"intermediate_steps\": lambda x: convert_intermediate_steps(\n",
" x[\"intermediate_steps\"]\n",
" ),\n",
" }\n",
" | prompt.partial(tools=convert_tools(tool_list))\n",
" | model.bind(stop=[\"</tool_input>\", \"</final_answer>\"])\n",

View File

@@ -18,7 +18,11 @@
"outputs": [],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate\n",
"from langchain.prompts import (\n",
" ChatPromptTemplate,\n",
" SystemMessagePromptTemplate,\n",
" HumanMessagePromptTemplate,\n",
")\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain_experimental.utilities import PythonREPL"
]
@@ -37,9 +41,7 @@
"```python\n",
"....\n",
"```\"\"\"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", template), (\"human\", \"{input}\")]\n",
")\n",
"prompt = ChatPromptTemplate.from_messages([(\"system\", template), (\"human\", \"{input}\")])\n",
"\n",
"model = ChatOpenAI()"
]

View File

@@ -0,0 +1,155 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "cf4fb76d-c534-485b-8b51-a0714ee3b82e",
"metadata": {},
"source": [
"# Routing by semantic similarity\n",
"\n",
"With LCEL you can easily add [custom routing logic](/docs/expression_language/how_to/routing#using-a-custom-function) to your chain to dynamically determine the chain logic based on user input. All you need to do is define a function that given an input returns a `Runnable`.\n",
"\n",
"One especially useful technique is to use embeddings to route a query to the most relevant prompt. Here's a very simple example."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "eef9020a-5f7c-4291-98eb-fa73f17d4b92",
"metadata": {},
"outputs": [],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.embeddings import OpenAIEmbeddings\n",
"from langchain.prompts import PromptTemplate\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain.schema.runnable import RunnableLambda, RunnablePassthrough\n",
"from langchain.utils.math import cosine_similarity\n",
"\n",
"\n",
"physics_template = \"\"\"You are a very smart physics professor. \\\n",
"You are great at answering questions about physics in a concise and easy to understand manner. \\\n",
"When you don't know the answer to a question you admit that you don't know.\n",
"\n",
"Here is a question:\n",
"{query}\"\"\"\n",
"\n",
"math_template = \"\"\"You are a very good mathematician. You are great at answering math questions. \\\n",
"You are so good because you are able to break down hard problems into their component parts, \\\n",
"answer the component parts, and then put them together to answer the broader question.\n",
"\n",
"Here is a question:\n",
"{query}\"\"\"\n",
"\n",
"embeddings = OpenAIEmbeddings()\n",
"prompt_templates = [physics_template, math_template]\n",
"prompt_embeddings = embeddings.embed_documents(prompt_templates)\n",
"\n",
"\n",
"def prompt_router(input):\n",
" query_embedding = embeddings.embed_query(input[\"query\"])\n",
" similarity = cosine_similarity([query_embedding], prompt_embeddings)[0]\n",
" most_similar = prompt_templates[similarity.argmax()]\n",
" print(\"Using MATH\" if most_similar == math_template else \"Using PHYSICS\")\n",
" return PromptTemplate.from_template(most_similar)\n",
"\n",
"\n",
"chain = (\n",
" {\"query\": RunnablePassthrough()}\n",
" | RunnableLambda(prompt_router)\n",
" | ChatOpenAI()\n",
" | StrOutputParser()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "4d22b0f3-24f2-4a47-9440-065b57ebcdbd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using PHYSICS\n",
"A black hole is a region in space where gravity is extremely strong, so strong that nothing, not even light, can escape its gravitational pull. It is formed when a massive star collapses under its own gravity during a supernova explosion. The collapse causes an incredibly dense mass to be concentrated in a small volume, creating a gravitational field that is so intense that it warps space and time. Black holes have a boundary called the event horizon, which marks the point of no return for anything that gets too close. Beyond the event horizon, the gravitational pull is so strong that even light cannot escape, hence the name \"black hole.\" While we have a good understanding of black holes, there is still much to learn, especially about what happens inside them.\n"
]
}
],
"source": [
"print(chain.invoke(\"What's a black hole\"))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f261910d-1de1-4a01-8c8a-308db02b81de",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using MATH\n",
"Thank you for your kind words! I will do my best to break down the concept of a path integral for you.\n",
"\n",
"In mathematics and physics, a path integral is a mathematical tool used to calculate the probability amplitude or wave function of a particle or system of particles. It was introduced by Richard Feynman and is an integral over all possible paths that a particle can take to go from an initial state to a final state.\n",
"\n",
"To understand the concept better, let's consider an example. Suppose we have a particle moving from point A to point B in space. Classically, we would describe this particle's motion using a definite trajectory, but in quantum mechanics, particles can simultaneously take multiple paths from A to B.\n",
"\n",
"The path integral formalism considers all possible paths that the particle could take and assigns a probability amplitude to each path. These probability amplitudes are then added up, taking into account the interference effects between different paths.\n",
"\n",
"To calculate a path integral, we need to define an action, which is a mathematical function that describes the behavior of the system. The action is usually expressed in terms of the particle's position, velocity, and time.\n",
"\n",
"Once we have the action, we can write down the path integral as an integral over all possible paths. Each path is weighted by a factor determined by the action and the principle of least action, which states that a particle takes a path that minimizes the action.\n",
"\n",
"Mathematically, the path integral is expressed as:\n",
"\n",
"∫ e^(iS/ħ) D[x(t)]\n",
"\n",
"Here, S is the action, ħ is the reduced Planck's constant, and D[x(t)] represents the integration over all possible paths x(t) of the particle.\n",
"\n",
"By evaluating this integral, we can obtain the probability amplitude for the particle to go from the initial state to the final state. The absolute square of this amplitude gives us the probability of finding the particle in a particular state.\n",
"\n",
"Path integrals have proven to be a powerful tool in various areas of physics, including quantum mechanics, quantum field theory, and statistical mechanics. They allow us to study complex systems and calculate probabilities that are difficult to obtain using other methods.\n",
"\n",
"I hope this explanation helps you understand the concept of a path integral. If you have any further questions, feel free to ask!\n"
]
}
],
"source": [
"print(chain.invoke(\"What's a path integral\"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f0c1732a-01ca-4d10-977c-29ed7480972b",
"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

@@ -24,11 +24,13 @@
"from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"\n",
"model = ChatOpenAI()\n",
"prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"You are a helpful chatbot\"),\n",
" MessagesPlaceholder(variable_name=\"history\"),\n",
" (\"human\", \"{input}\")\n",
"])\n"
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"You are a helpful chatbot\"),\n",
" MessagesPlaceholder(variable_name=\"history\"),\n",
" (\"human\", \"{input}\"),\n",
" ]\n",
")"
]
},
{
@@ -38,7 +40,7 @@
"metadata": {},
"outputs": [],
"source": [
"memory = ConversationBufferMemory(return_messages=True)\n"
"memory = ConversationBufferMemory(return_messages=True)"
]
},
{
@@ -59,7 +61,7 @@
}
],
"source": [
"memory.load_memory_variables({})\n"
"memory.load_memory_variables({})"
]
},
{
@@ -69,9 +71,13 @@
"metadata": {},
"outputs": [],
"source": [
"chain = RunnablePassthrough.assign(\n",
" memory=RunnableLambda(memory.load_memory_variables) | itemgetter(\"history\")\n",
") | prompt | model\n"
"chain = (\n",
" RunnablePassthrough.assign(\n",
" history=RunnableLambda(memory.load_memory_variables) | itemgetter(\"history\")\n",
" )\n",
" | prompt\n",
" | model\n",
")"
]
},
{
@@ -94,7 +100,7 @@
"source": [
"inputs = {\"input\": \"hi im bob\"}\n",
"response = chain.invoke(inputs)\n",
"response\n"
"response"
]
},
{
@@ -104,7 +110,7 @@
"metadata": {},
"outputs": [],
"source": [
"memory.save_context(inputs, {\"output\": response.content})\n"
"memory.save_context(inputs, {\"output\": response.content})"
]
},
{
@@ -126,7 +132,7 @@
}
],
"source": [
"memory.load_memory_variables({})\n"
"memory.load_memory_variables({})"
]
},
{
@@ -149,7 +155,7 @@
"source": [
"inputs = {\"input\": \"whats my name\"}\n",
"response = chain.invoke(inputs)\n",
"response\n"
"response"
]
}
],

View File

@@ -40,9 +40,7 @@
"outputs": [],
"source": [
"model = OpenAI()\n",
"prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"repeat after me: {input}\")\n",
"])"
"prompt = ChatPromptTemplate.from_messages([(\"system\", \"repeat after me: {input}\")])"
]
},
{

View File

@@ -44,13 +44,20 @@
"from langchain.schema import StrOutputParser\n",
"\n",
"prompt1 = ChatPromptTemplate.from_template(\"what is the city {person} is from?\")\n",
"prompt2 = ChatPromptTemplate.from_template(\"what country is the city {city} in? respond in {language}\")\n",
"prompt2 = ChatPromptTemplate.from_template(\n",
" \"what country is the city {city} in? respond in {language}\"\n",
")\n",
"\n",
"model = ChatOpenAI()\n",
"\n",
"chain1 = prompt1 | model | StrOutputParser()\n",
"\n",
"chain2 = {\"city\": chain1, \"language\": itemgetter(\"language\")} | prompt2 | model | StrOutputParser()\n",
"chain2 = (\n",
" {\"city\": chain1, \"language\": itemgetter(\"language\")}\n",
" | prompt2\n",
" | model\n",
" | StrOutputParser()\n",
")\n",
"\n",
"chain2.invoke({\"person\": \"obama\", \"language\": \"spanish\"})"
]
@@ -64,17 +71,29 @@
"source": [
"from langchain.schema.runnable import RunnableMap, RunnablePassthrough\n",
"\n",
"prompt1 = ChatPromptTemplate.from_template(\"generate a {attribute} color. Return the name of the color and nothing else:\")\n",
"prompt2 = ChatPromptTemplate.from_template(\"what is a fruit of color: {color}. Return the name of the fruit and nothing else:\")\n",
"prompt3 = ChatPromptTemplate.from_template(\"what is a country with a flag that has the color: {color}. Return the name of the country and nothing else:\")\n",
"prompt4 = ChatPromptTemplate.from_template(\"What is the color of {fruit} and the flag of {country}?\")\n",
"prompt1 = ChatPromptTemplate.from_template(\n",
" \"generate a {attribute} color. Return the name of the color and nothing else:\"\n",
")\n",
"prompt2 = ChatPromptTemplate.from_template(\n",
" \"what is a fruit of color: {color}. Return the name of the fruit and nothing else:\"\n",
")\n",
"prompt3 = ChatPromptTemplate.from_template(\n",
" \"what is a country with a flag that has the color: {color}. Return the name of the country and nothing else:\"\n",
")\n",
"prompt4 = ChatPromptTemplate.from_template(\n",
" \"What is the color of {fruit} and the flag of {country}?\"\n",
")\n",
"\n",
"model_parser = model | StrOutputParser()\n",
"\n",
"color_generator = {\"attribute\": RunnablePassthrough()} | prompt1 | {\"color\": model_parser}\n",
"color_generator = (\n",
" {\"attribute\": RunnablePassthrough()} | prompt1 | {\"color\": model_parser}\n",
")\n",
"color_to_fruit = prompt2 | model_parser\n",
"color_to_country = prompt3 | model_parser\n",
"question_generator = color_generator | {\"fruit\": color_to_fruit, \"country\": color_to_country} | prompt4"
"question_generator = (\n",
" color_generator | {\"fruit\": color_to_fruit, \"country\": color_to_country} | prompt4\n",
")"
]
},
{
@@ -148,9 +167,7 @@
"outputs": [],
"source": [
"planner = (\n",
" ChatPromptTemplate.from_template(\n",
" \"Generate an argument about: {input}\"\n",
" )\n",
" ChatPromptTemplate.from_template(\"Generate an argument about: {input}\")\n",
" | ChatOpenAI()\n",
" | StrOutputParser()\n",
" | {\"base_response\": RunnablePassthrough()}\n",
@@ -163,7 +180,7 @@
" | ChatOpenAI()\n",
" | StrOutputParser()\n",
")\n",
"arguments_against = (\n",
"arguments_against = (\n",
" ChatPromptTemplate.from_template(\n",
" \"List the cons or negative aspects of {base_response}\"\n",
" )\n",
@@ -184,7 +201,7 @@
")\n",
"\n",
"chain = (\n",
" planner \n",
" planner\n",
" | {\n",
" \"results_1\": arguments_for,\n",
" \"results_2\": arguments_against,\n",

View File

@@ -30,7 +30,7 @@
"source": [
"## PromptTemplate + LLM\n",
"\n",
"The simplest composition is just combing a prompt and model to create a chain that takes user input, adds it to a prompt, passes it to a model, and returns the raw model output.\n",
"The simplest composition is just combining a prompt and model to create a chain that takes user input, adds it to a prompt, passes it to a model, and returns the raw model output.\n",
"\n",
"Note, you can mix and match PromptTemplate/ChatPromptTemplates and LLMs/ChatModels as you like here."
]
@@ -47,7 +47,7 @@
"\n",
"prompt = ChatPromptTemplate.from_template(\"tell me a joke about {foo}\")\n",
"model = ChatOpenAI()\n",
"chain = prompt | model\n"
"chain = prompt | model"
]
},
{
@@ -68,7 +68,7 @@
}
],
"source": [
"chain.invoke({\"foo\": \"bears\"})\n"
"chain.invoke({\"foo\": \"bears\"})"
]
},
{
@@ -94,7 +94,7 @@
"metadata": {},
"outputs": [],
"source": [
"chain = prompt | model.bind(stop=[\"\\n\"])\n"
"chain = prompt | model.bind(stop=[\"\\n\"])"
]
},
{
@@ -115,7 +115,7 @@
}
],
"source": [
"chain.invoke({\"foo\": \"bears\"})\n"
"chain.invoke({\"foo\": \"bears\"})"
]
},
{
@@ -135,25 +135,22 @@
"source": [
"functions = [\n",
" {\n",
" \"name\": \"joke\",\n",
" \"description\": \"A joke\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"setup\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The setup for the joke\"\n",
" },\n",
" \"punchline\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The punchline for the joke\"\n",
" }\n",
" \"name\": \"joke\",\n",
" \"description\": \"A joke\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"setup\": {\"type\": \"string\", \"description\": \"The setup for the joke\"},\n",
" \"punchline\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The punchline for the joke\",\n",
" },\n",
" },\n",
" \"required\": [\"setup\", \"punchline\"],\n",
" },\n",
" \"required\": [\"setup\", \"punchline\"]\n",
" }\n",
" }\n",
" ]\n",
"chain = prompt | model.bind(function_call= {\"name\": \"joke\"}, functions= functions)\n"
"]\n",
"chain = prompt | model.bind(function_call={\"name\": \"joke\"}, functions=functions)"
]
},
{
@@ -174,7 +171,7 @@
}
],
"source": [
"chain.invoke({\"foo\": \"bears\"}, config={})\n"
"chain.invoke({\"foo\": \"bears\"}, config={})"
]
},
{
@@ -196,7 +193,7 @@
"source": [
"from langchain.schema.output_parser import StrOutputParser\n",
"\n",
"chain = prompt | model | StrOutputParser()\n"
"chain = prompt | model | StrOutputParser()"
]
},
{
@@ -225,7 +222,7 @@
}
],
"source": [
"chain.invoke({\"foo\": \"bears\"})\n"
"chain.invoke({\"foo\": \"bears\"})"
]
},
{
@@ -248,10 +245,10 @@
"from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser\n",
"\n",
"chain = (\n",
" prompt \n",
" | model.bind(function_call= {\"name\": \"joke\"}, functions= functions) \n",
" prompt\n",
" | model.bind(function_call={\"name\": \"joke\"}, functions=functions)\n",
" | JsonOutputFunctionsParser()\n",
")\n"
")"
]
},
{
@@ -273,7 +270,7 @@
}
],
"source": [
"chain.invoke({\"foo\": \"bears\"})\n"
"chain.invoke({\"foo\": \"bears\"})"
]
},
{
@@ -286,10 +283,10 @@
"from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser\n",
"\n",
"chain = (\n",
" prompt \n",
" | model.bind(function_call= {\"name\": \"joke\"}, functions= functions) \n",
" prompt\n",
" | model.bind(function_call={\"name\": \"joke\"}, functions=functions)\n",
" | JsonKeyOutputFunctionsParser(key_name=\"setup\")\n",
")\n"
")"
]
},
{
@@ -310,7 +307,7 @@
}
],
"source": [
"chain.invoke({\"foo\": \"bears\"})\n"
"chain.invoke({\"foo\": \"bears\"})"
]
},
{
@@ -334,11 +331,11 @@
"\n",
"map_ = RunnableMap(foo=RunnablePassthrough())\n",
"chain = (\n",
" map_ \n",
" map_\n",
" | prompt\n",
" | model.bind(function_call= {\"name\": \"joke\"}, functions= functions) \n",
" | model.bind(function_call={\"name\": \"joke\"}, functions=functions)\n",
" | JsonKeyOutputFunctionsParser(key_name=\"setup\")\n",
")\n"
")"
]
},
{
@@ -359,7 +356,7 @@
}
],
"source": [
"chain.invoke(\"bears\")\n"
"chain.invoke(\"bears\")"
]
},
{
@@ -378,11 +375,11 @@
"outputs": [],
"source": [
"chain = (\n",
" {\"foo\": RunnablePassthrough()} \n",
" {\"foo\": RunnablePassthrough()}\n",
" | prompt\n",
" | model.bind(function_call= {\"name\": \"joke\"}, functions= functions) \n",
" | model.bind(function_call={\"name\": \"joke\"}, functions=functions)\n",
" | JsonKeyOutputFunctionsParser(key_name=\"setup\")\n",
")\n"
")"
]
},
{
@@ -403,7 +400,7 @@
}
],
"source": [
"chain.invoke(\"bears\")\n"
"chain.invoke(\"bears\")"
]
}
],

View File

@@ -26,7 +26,7 @@
"metadata": {},
"outputs": [],
"source": [
"!pip install langchain openai faiss-cpu tiktoken\n"
"!pip install langchain openai faiss-cpu tiktoken"
]
},
{
@@ -43,7 +43,7 @@
"from langchain.embeddings import OpenAIEmbeddings\n",
"from langchain.schema.output_parser import StrOutputParser\n",
"from langchain.schema.runnable import RunnablePassthrough, RunnableLambda\n",
"from langchain.vectorstores import FAISS\n"
"from langchain.vectorstores import FAISS"
]
},
{
@@ -53,7 +53,9 @@
"metadata": {},
"outputs": [],
"source": [
"vectorstore = FAISS.from_texts([\"harrison worked at kensho\"], embedding=OpenAIEmbeddings())\n",
"vectorstore = FAISS.from_texts(\n",
" [\"harrison worked at kensho\"], embedding=OpenAIEmbeddings()\n",
")\n",
"retriever = vectorstore.as_retriever()\n",
"\n",
"template = \"\"\"Answer the question based only on the following context:\n",
@@ -63,7 +65,7 @@
"\"\"\"\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"model = ChatOpenAI()\n"
"model = ChatOpenAI()"
]
},
{
@@ -74,11 +76,11 @@
"outputs": [],
"source": [
"chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")\n"
")"
]
},
{
@@ -99,7 +101,7 @@
}
],
"source": [
"chain.invoke(\"where did harrison work?\")\n"
"chain.invoke(\"where did harrison work?\")"
]
},
{
@@ -118,11 +120,16 @@
"\"\"\"\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"chain = {\n",
" \"context\": itemgetter(\"question\") | retriever, \n",
" \"question\": itemgetter(\"question\"), \n",
" \"language\": itemgetter(\"language\")\n",
"} | prompt | model | StrOutputParser()\n"
"chain = (\n",
" {\n",
" \"context\": itemgetter(\"question\") | retriever,\n",
" \"question\": itemgetter(\"question\"),\n",
" \"language\": itemgetter(\"language\"),\n",
" }\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")"
]
},
{
@@ -143,7 +150,7 @@
}
],
"source": [
"chain.invoke({\"question\": \"where did harrison work\", \"language\": \"italian\"})\n"
"chain.invoke({\"question\": \"where did harrison work\", \"language\": \"italian\"})"
]
},
{
@@ -164,7 +171,7 @@
"outputs": [],
"source": [
"from langchain.schema.runnable import RunnableMap\n",
"from langchain.schema import format_document\n"
"from langchain.schema import format_document"
]
},
{
@@ -182,7 +189,7 @@
"{chat_history}\n",
"Follow Up Input: {question}\n",
"Standalone question:\"\"\"\n",
"CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)\n"
"CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)"
]
},
{
@@ -197,7 +204,7 @@
"\n",
"Question: {question}\n",
"\"\"\"\n",
"ANSWER_PROMPT = ChatPromptTemplate.from_template(template)\n"
"ANSWER_PROMPT = ChatPromptTemplate.from_template(template)"
]
},
{
@@ -208,9 +215,13 @@
"outputs": [],
"source": [
"DEFAULT_DOCUMENT_PROMPT = PromptTemplate.from_template(template=\"{page_content}\")\n",
"def _combine_documents(docs, document_prompt = DEFAULT_DOCUMENT_PROMPT, document_separator=\"\\n\\n\"):\n",
"\n",
"\n",
"def _combine_documents(\n",
" docs, document_prompt=DEFAULT_DOCUMENT_PROMPT, document_separator=\"\\n\\n\"\n",
"):\n",
" doc_strings = [format_document(doc, document_prompt) for doc in docs]\n",
" return document_separator.join(doc_strings)\n"
" return document_separator.join(doc_strings)"
]
},
{
@@ -221,13 +232,15 @@
"outputs": [],
"source": [
"from typing import Tuple, List\n",
"\n",
"\n",
"def _format_chat_history(chat_history: List[Tuple]) -> str:\n",
" buffer = \"\"\n",
" for dialogue_turn in chat_history:\n",
" human = \"Human: \" + dialogue_turn[0]\n",
" ai = \"Assistant: \" + dialogue_turn[1]\n",
" buffer += \"\\n\" + \"\\n\".join([human, ai])\n",
" return buffer\n"
" return buffer"
]
},
{
@@ -239,14 +252,17 @@
"source": [
"_inputs = RunnableMap(\n",
" standalone_question=RunnablePassthrough.assign(\n",
" chat_history=lambda x: _format_chat_history(x['chat_history'])\n",
" ) | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),\n",
" chat_history=lambda x: _format_chat_history(x[\"chat_history\"])\n",
" )\n",
" | CONDENSE_QUESTION_PROMPT\n",
" | ChatOpenAI(temperature=0)\n",
" | StrOutputParser(),\n",
")\n",
"_context = {\n",
" \"context\": itemgetter(\"standalone_question\") | retriever | _combine_documents,\n",
" \"question\": lambda x: x[\"standalone_question\"]\n",
" \"question\": lambda x: x[\"standalone_question\"],\n",
"}\n",
"conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI()\n"
"conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI()"
]
},
{
@@ -267,10 +283,12 @@
}
],
"source": [
"conversational_qa_chain.invoke({\n",
" \"question\": \"where did harrison work?\",\n",
" \"chat_history\": [],\n",
"})\n"
"conversational_qa_chain.invoke(\n",
" {\n",
" \"question\": \"where did harrison work?\",\n",
" \"chat_history\": [],\n",
" }\n",
")"
]
},
{
@@ -291,10 +309,12 @@
}
],
"source": [
"conversational_qa_chain.invoke({\n",
" \"question\": \"where did he work?\",\n",
" \"chat_history\": [(\"Who wrote this notebook?\", \"Harrison\")],\n",
"})\n"
"conversational_qa_chain.invoke(\n",
" {\n",
" \"question\": \"where did he work?\",\n",
" \"chat_history\": [(\"Who wrote this notebook?\", \"Harrison\")],\n",
" }\n",
")"
]
},
{
@@ -315,7 +335,7 @@
"outputs": [],
"source": [
"from operator import itemgetter\n",
"from langchain.memory import ConversationBufferMemory\n"
"from langchain.memory import ConversationBufferMemory"
]
},
{
@@ -325,7 +345,9 @@
"metadata": {},
"outputs": [],
"source": [
"memory = ConversationBufferMemory(return_messages=True, output_key=\"answer\", input_key=\"question\")\n"
"memory = ConversationBufferMemory(\n",
" return_messages=True, output_key=\"answer\", input_key=\"question\"\n",
")"
]
},
{
@@ -344,18 +366,21 @@
"standalone_question = {\n",
" \"standalone_question\": {\n",
" \"question\": lambda x: x[\"question\"],\n",
" \"chat_history\": lambda x: _format_chat_history(x['chat_history'])\n",
" } | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),\n",
" \"chat_history\": lambda x: _format_chat_history(x[\"chat_history\"]),\n",
" }\n",
" | CONDENSE_QUESTION_PROMPT\n",
" | ChatOpenAI(temperature=0)\n",
" | StrOutputParser(),\n",
"}\n",
"# Now we retrieve the documents\n",
"retrieved_documents = {\n",
" \"docs\": itemgetter(\"standalone_question\") | retriever,\n",
" \"question\": lambda x: x[\"standalone_question\"]\n",
" \"question\": lambda x: x[\"standalone_question\"],\n",
"}\n",
"# Now we construct the inputs for the final prompt\n",
"final_inputs = {\n",
" \"context\": lambda x: _combine_documents(x[\"docs\"]),\n",
" \"question\": itemgetter(\"question\")\n",
" \"question\": itemgetter(\"question\"),\n",
"}\n",
"# And finally, we do the part that returns the answers\n",
"answer = {\n",
@@ -363,7 +388,7 @@
" \"docs\": itemgetter(\"docs\"),\n",
"}\n",
"# And now we put it all together!\n",
"final_chain = loaded_memory | standalone_question | retrieved_documents | answer\n"
"final_chain = loaded_memory | standalone_question | retrieved_documents | answer"
]
},
{
@@ -387,7 +412,7 @@
"source": [
"inputs = {\"question\": \"where did harrison work?\"}\n",
"result = final_chain.invoke(inputs)\n",
"result\n"
"result"
]
},
{
@@ -400,7 +425,7 @@
"# Note that the memory does not save automatically\n",
"# This will be improved in the future\n",
"# For now you need to save it yourself\n",
"memory.save_context(inputs, {\"answer\": result[\"answer\"].content})\n"
"memory.save_context(inputs, {\"answer\": result[\"answer\"].content})"
]
},
{
@@ -422,7 +447,7 @@
}
],
"source": [
"memory.load_memory_variables({})\n"
"memory.load_memory_variables({})"
]
}
],

View File

@@ -33,7 +33,7 @@
"\n",
"Question: {question}\n",
"SQL Query:\"\"\"\n",
"prompt = ChatPromptTemplate.from_template(template)\n"
"prompt = ChatPromptTemplate.from_template(template)"
]
},
{
@@ -43,7 +43,7 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain.utilities import SQLDatabase\n"
"from langchain.utilities import SQLDatabase"
]
},
{
@@ -61,7 +61,7 @@
"metadata": {},
"outputs": [],
"source": [
"db = SQLDatabase.from_uri(\"sqlite:///./Chinook.db\")\n"
"db = SQLDatabase.from_uri(\"sqlite:///./Chinook.db\")"
]
},
{
@@ -72,7 +72,7 @@
"outputs": [],
"source": [
"def get_schema(_):\n",
" return db.get_table_info()\n"
" return db.get_table_info()"
]
},
{
@@ -83,7 +83,7 @@
"outputs": [],
"source": [
"def run_query(query):\n",
" return db.run(query)\n"
" return db.run(query)"
]
},
{
@@ -100,11 +100,11 @@
"model = ChatOpenAI()\n",
"\n",
"sql_response = (\n",
" RunnablePassthrough.assign(schema=get_schema)\n",
" | prompt\n",
" | model.bind(stop=[\"\\nSQLResult:\"])\n",
" | StrOutputParser()\n",
" )\n"
" RunnablePassthrough.assign(schema=get_schema)\n",
" | prompt\n",
" | model.bind(stop=[\"\\nSQLResult:\"])\n",
" | StrOutputParser()\n",
")"
]
},
{
@@ -125,7 +125,7 @@
}
],
"source": [
"sql_response.invoke({\"question\": \"How many employees are there?\"})\n"
"sql_response.invoke({\"question\": \"How many employees are there?\"})"
]
},
{
@@ -141,7 +141,7 @@
"Question: {question}\n",
"SQL Query: {query}\n",
"SQL Response: {response}\"\"\"\n",
"prompt_response = ChatPromptTemplate.from_template(template)\n"
"prompt_response = ChatPromptTemplate.from_template(template)"
]
},
{
@@ -152,14 +152,14 @@
"outputs": [],
"source": [
"full_chain = (\n",
" RunnablePassthrough.assign(query=sql_response) \n",
" RunnablePassthrough.assign(query=sql_response)\n",
" | RunnablePassthrough.assign(\n",
" schema=get_schema,\n",
" response=lambda x: db.run(x[\"query\"]),\n",
" )\n",
" | prompt_response \n",
" | prompt_response\n",
" | model\n",
")\n"
")"
]
},
{
@@ -180,7 +180,7 @@
}
],
"source": [
"full_chain.invoke({\"question\": \"How many employees are there?\"})\n"
"full_chain.invoke({\"question\": \"How many employees are there?\"})"
]
},
{

View File

@@ -12,6 +12,19 @@
"Suppose we have a simple prompt + model sequence:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "950297ed-2d67-4091-8ea7-1d412d259d04",
"metadata": {},
"outputs": [],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.prompts import ChatPromptTemplate\n",
"from langchain.schema import StrOutputParser\n",
"from langchain.schema.runnable import RunnablePassthrough"
]
},
{
"cell_type": "code",
"execution_count": 11,
@@ -37,19 +50,19 @@
}
],
"source": [
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.prompts import ChatPromptTemplate\n",
"from langchain.schema import StrOutputParser\n",
"from langchain.schema.runnable import RunnablePassthrough\n",
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"Write out the following equation using algebraic symbols then solve it. Use the format\\n\\nEQUATION:...\\nSOLUTION:...\\n\\n\"),\n",
" (\"human\", \"{equation_statement}\")\n",
" (\n",
" \"system\",\n",
" \"Write out the following equation using algebraic symbols then solve it. Use the format\\n\\nEQUATION:...\\nSOLUTION:...\\n\\n\",\n",
" ),\n",
" (\"human\", \"{equation_statement}\"),\n",
" ]\n",
")\n",
"model = ChatOpenAI(temperature=0)\n",
"runnable = {\"equation_statement\": RunnablePassthrough()} | prompt | model | StrOutputParser()\n",
"runnable = (\n",
" {\"equation_statement\": RunnablePassthrough()} | prompt | model | StrOutputParser()\n",
")\n",
"\n",
"print(runnable.invoke(\"x raised to the third plus seven equals 12\"))"
]
@@ -80,9 +93,9 @@
],
"source": [
"runnable = (\n",
" {\"equation_statement\": RunnablePassthrough()} \n",
" | prompt \n",
" | model.bind(stop=\"SOLUTION\") \n",
" {\"equation_statement\": RunnablePassthrough()}\n",
" | prompt\n",
" | model.bind(stop=\"SOLUTION\")\n",
" | StrOutputParser()\n",
")\n",
"print(runnable.invoke(\"x raised to the third plus seven equals 12\"))"
@@ -100,31 +113,29 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 3,
"id": "f66a0fe4-fde0-4706-8863-d60253f211c7",
"metadata": {},
"outputs": [],
"source": [
"functions = [\n",
" {\n",
" \"name\": \"solver\",\n",
" \"description\": \"Formulates and solves an equation\",\n",
" \"parameters\": {\n",
"function = {\n",
" \"name\": \"solver\",\n",
" \"description\": \"Formulates and solves an equation\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"equation\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The algebraic expression of the equation\"\n",
" },\n",
" \"solution\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The solution to the equation\"\n",
" }\n",
" \"equation\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The algebraic expression of the equation\",\n",
" },\n",
" \"solution\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The solution to the equation\",\n",
" },\n",
" },\n",
" \"required\": [\"equation\", \"solution\"]\n",
" }\n",
" }\n",
" ]\n"
" \"required\": [\"equation\", \"solution\"],\n",
" },\n",
"}"
]
},
{
@@ -148,26 +159,78 @@
"# Need gpt-4 to solve this one correctly\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"Write out the following equation using algebraic symbols then solve it.\"),\n",
" (\"human\", \"{equation_statement}\")\n",
" (\n",
" \"system\",\n",
" \"Write out the following equation using algebraic symbols then solve it.\",\n",
" ),\n",
" (\"human\", \"{equation_statement}\"),\n",
" ]\n",
")\n",
"model = ChatOpenAI(model=\"gpt-4\", temperature=0).bind(function_call={\"name\": \"solver\"}, functions=functions)\n",
"runnable = (\n",
" {\"equation_statement\": RunnablePassthrough()} \n",
" | prompt \n",
" | model\n",
"model = ChatOpenAI(model=\"gpt-4\", temperature=0).bind(\n",
" function_call={\"name\": \"solver\"}, functions=[function]\n",
")\n",
"runnable = {\"equation_statement\": RunnablePassthrough()} | prompt | model\n",
"runnable.invoke(\"x raised to the third plus seven equals 12\")"
]
},
{
"cell_type": "markdown",
"id": "f07d7528-9269-4d6f-b12e-3669592a9e03",
"metadata": {},
"source": [
"## Attaching OpenAI tools"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"id": "2cdeeb4c-0c1f-43da-bd58-4f591d9e0671",
"metadata": {},
"outputs": [],
"source": []
"source": [
"tools = [\n",
" {\n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"get_current_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
" },\n",
" \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]},\n",
" },\n",
" \"required\": [\"location\"],\n",
" },\n",
" },\n",
" }\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "2b65beab-48bb-46ff-a5a4-ef8ac95a513c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_zHN0ZHwrxM7nZDdqTp6dkPko', 'function': {'arguments': '{\"location\": \"San Francisco, CA\", \"unit\": \"celsius\"}', 'name': 'get_current_weather'}, 'type': 'function'}, {'id': 'call_aqdMm9HBSlFW9c9rqxTa7eQv', 'function': {'arguments': '{\"location\": \"New York, NY\", \"unit\": \"celsius\"}', 'name': 'get_current_weather'}, 'type': 'function'}, {'id': 'call_cx8E567zcLzYV2WSWVgO63f1', 'function': {'arguments': '{\"location\": \"Los Angeles, CA\", \"unit\": \"celsius\"}', 'name': 'get_current_weather'}, 'type': 'function'}]})"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = ChatOpenAI(model=\"gpt-3.5-turbo-1106\").bind(tools=tools)\n",
"model.invoke(\"What's the weather in SF, NYC and LA?\")"
]
}
],
"metadata": {

View File

@@ -5,7 +5,7 @@
"id": "39eaf61b",
"metadata": {},
"source": [
"# Configuration\n",
"# Configure chain internals at runtime\n",
"\n",
"Oftentimes you may want to experiment with, or even expose to the end user, multiple different ways of doing things.\n",
"In order to make this experience as easy as possible, we have defined two methods.\n",
@@ -92,7 +92,7 @@
}
],
"source": [
"model.with_config(configurable={\"llm_temperature\": .9}).invoke(\"pick a random number\")"
"model.with_config(configurable={\"llm_temperature\": 0.9}).invoke(\"pick a random number\")"
]
},
{
@@ -153,7 +153,7 @@
}
],
"source": [
"chain.with_config(configurable={\"llm_temperature\": .9}).invoke({\"x\": 0})"
"chain.with_config(configurable={\"llm_temperature\": 0.9}).invoke({\"x\": 0})"
]
},
{
@@ -231,7 +231,9 @@
}
],
"source": [
"prompt.with_config(configurable={\"hub_commit\": \"rlm/rag-prompt-llama\"}).invoke({\"question\": \"foo\", \"context\": \"bar\"})"
"prompt.with_config(configurable={\"hub_commit\": \"rlm/rag-prompt-llama\"}).invoke(\n",
" {\"question\": \"foo\", \"context\": \"bar\"}\n",
")"
]
},
{
@@ -373,7 +375,9 @@
"outputs": [],
"source": [
"llm = ChatAnthropic(temperature=0)\n",
"prompt = PromptTemplate.from_template(\"Tell me a joke about {topic}\").configurable_alternatives(\n",
"prompt = PromptTemplate.from_template(\n",
" \"Tell me a joke about {topic}\"\n",
").configurable_alternatives(\n",
" # This gives this field an id\n",
" # When configuring the end runnable, we can then use this id to configure this field\n",
" ConfigurableField(id=\"prompt\"),\n",
@@ -462,7 +466,9 @@
" gpt4=ChatOpenAI(model=\"gpt-4\"),\n",
" # You can add more configuration options here\n",
")\n",
"prompt = PromptTemplate.from_template(\"Tell me a joke about {topic}\").configurable_alternatives(\n",
"prompt = PromptTemplate.from_template(\n",
" \"Tell me a joke about {topic}\"\n",
").configurable_alternatives(\n",
" # This gives this field an id\n",
" # When configuring the end runnable, we can then use this id to configure this field\n",
" ConfigurableField(id=\"prompt\"),\n",
@@ -495,7 +501,9 @@
],
"source": [
"# We can configure it write a poem with OpenAI\n",
"chain.with_config(configurable={\"prompt\": \"poem\", \"llm\": \"openai\"}).invoke({\"topic\": \"bears\"})"
"chain.with_config(configurable={\"prompt\": \"poem\", \"llm\": \"openai\"}).invoke(\n",
" {\"topic\": \"bears\"}\n",
")"
]
},
{
@@ -586,7 +594,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -82,9 +82,9 @@
],
"source": [
"# Let's use just the OpenAI LLm first, to show that we run into an error\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(openai_llm.invoke(\"Why did the chicken cross the road?\"))\n",
" print(openai_llm.invoke(\"Why did the chicken cross the road?\"))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -105,9 +105,9 @@
],
"source": [
"# Now let's try with fallbacks to Anthropic\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(llm.invoke(\"Why did the chicken cross the road?\"))\n",
" print(llm.invoke(\"Why did the chicken cross the road?\"))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -139,14 +139,17 @@
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"You're a nice assistant who always includes a compliment in your response\"),\n",
" (\n",
" \"system\",\n",
" \"You're a nice assistant who always includes a compliment in your response\",\n",
" ),\n",
" (\"human\", \"Why did the {animal} cross the road\"),\n",
" ]\n",
")\n",
"chain = prompt | llm\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(chain.invoke({\"animal\": \"kangaroo\"}))\n",
" print(chain.invoke({\"animal\": \"kangaroo\"}))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -176,12 +179,14 @@
}
],
"source": [
"llm = openai_llm.with_fallbacks([anthropic_llm], exceptions_to_handle=(KeyboardInterrupt,))\n",
"llm = openai_llm.with_fallbacks(\n",
" [anthropic_llm], exceptions_to_handle=(KeyboardInterrupt,)\n",
")\n",
"\n",
"chain = prompt | llm\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(chain.invoke({\"animal\": \"kangaroo\"}))\n",
" print(chain.invoke({\"animal\": \"kangaroo\"}))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -209,7 +214,10 @@
"\n",
"chat_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"You're a nice assistant who always includes a compliment in your response\"),\n",
" (\n",
" \"system\",\n",
" \"You're a nice assistant who always includes a compliment in your response\",\n",
" ),\n",
" (\"human\", \"Why did the {animal} cross the road\"),\n",
" ]\n",
")\n",

View File

@@ -5,7 +5,7 @@
"id": "fbc4bf6e",
"metadata": {},
"source": [
"# Run arbitrary functions\n",
"# Run custom functions\n",
"\n",
"You can use arbitrary functions in the pipeline\n",
"\n",
@@ -24,24 +24,33 @@
"from langchain.chat_models import ChatOpenAI\n",
"from operator import itemgetter\n",
"\n",
"\n",
"def length_function(text):\n",
" return len(text)\n",
"\n",
"\n",
"def _multiple_length_function(text1, text2):\n",
" return len(text1) * len(text2)\n",
"\n",
"\n",
"def multiple_length_function(_dict):\n",
" return _multiple_length_function(_dict[\"text1\"], _dict[\"text2\"])\n",
"\n",
"\n",
"prompt = ChatPromptTemplate.from_template(\"what is {a} + {b}\")\n",
"model = ChatOpenAI()\n",
"\n",
"chain1 = prompt | model\n",
"\n",
"chain = {\n",
" \"a\": itemgetter(\"foo\") | RunnableLambda(length_function),\n",
" \"b\": {\"text1\": itemgetter(\"foo\"), \"text2\": itemgetter(\"bar\")} | RunnableLambda(multiple_length_function)\n",
"} | prompt | model"
"chain = (\n",
" {\n",
" \"a\": itemgetter(\"foo\") | RunnableLambda(length_function),\n",
" \"b\": {\"text1\": itemgetter(\"foo\"), \"text2\": itemgetter(\"bar\")}\n",
" | RunnableLambda(multiple_length_function),\n",
" }\n",
" | prompt\n",
" | model\n",
")"
]
},
{
@@ -95,6 +104,7 @@
"source": [
"import json\n",
"\n",
"\n",
"def parse_or_fix(text: str, config: RunnableConfig):\n",
" fixing_chain = (\n",
" ChatPromptTemplate.from_template(\n",
@@ -134,7 +144,9 @@
"from langchain.callbacks import get_openai_callback\n",
"\n",
"with get_openai_callback() as cb:\n",
" RunnableLambda(parse_or_fix).invoke(\"{foo: bar}\", {\"tags\": [\"my-tag\"], \"callbacks\": [cb]})\n",
" RunnableLambda(parse_or_fix).invoke(\n",
" \"{foo: bar}\", {\"tags\": [\"my-tag\"], \"callbacks\": [cb]}\n",
" )\n",
" print(cb)"
]
},
@@ -163,7 +175,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Custom generator functions\n",
"# Stream custom generator functions\n",
"\n",
"You can use generator functions (ie. functions that use the `yield` keyword, and behave like iterators) in a LCEL pipeline.\n",
"\n",
@@ -21,15 +21,7 @@
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lion, tiger, wolf, gorilla, panda\n"
]
}
],
"outputs": [],
"source": [
"from typing import Iterator, List\n",
"\n",
@@ -43,16 +35,51 @@
")\n",
"model = ChatOpenAI(temperature=0.0)\n",
"\n",
"\n",
"str_chain = prompt | model | StrOutputParser()\n",
"\n",
"print(str_chain.invoke({\"animal\": \"bear\"}))\n"
"str_chain = prompt | model | StrOutputParser()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lion, tiger, wolf, gorilla, panda"
]
}
],
"source": [
"for chunk in str_chain.stream({\"animal\": \"bear\"}):\n",
" print(chunk, end=\"\", flush=True)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'lion, tiger, wolf, gorilla, panda'"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"str_chain.invoke({\"animal\": \"bear\"})"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# This is a custom parser that splits an iterator of llm tokens\n",
@@ -72,27 +99,66 @@
" # save the rest for the next iteration\n",
" buffer = buffer[comma_index + 1 :]\n",
" # yield the last chunk\n",
" yield [buffer.strip()]\n"
" yield [buffer.strip()]"
]
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"list_chain = str_chain | split_into_list"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['lion', 'tiger', 'wolf', 'gorilla', 'panda']\n"
"['lion']\n",
"['tiger']\n",
"['wolf']\n",
"['gorilla']\n",
"['panda']\n"
]
}
],
"source": [
"list_chain = str_chain | split_into_list\n",
"\n",
"print(list_chain.invoke({\"animal\": \"bear\"}))\n"
"for chunk in list_chain.stream({\"animal\": \"bear\"}):\n",
" print(chunk, flush=True)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['lion', 'tiger', 'wolf', 'gorilla', 'panda']"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list_chain.invoke({\"animal\": \"bear\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@@ -111,9 +177,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View File

@@ -5,7 +5,7 @@
"id": "b022ab74-794d-4c54-ad47-ff9549ddb9d2",
"metadata": {},
"source": [
"# Use RunnableParallel/RunnableMap\n",
"# Parallelize steps\n",
"\n",
"RunnableParallel (aka. RunnableMap) makes it easy to execute multiple Runnables in parallel, and to return the output of these Runnables as a map."
]
@@ -36,11 +36,13 @@
"\n",
"model = ChatOpenAI()\n",
"joke_chain = ChatPromptTemplate.from_template(\"tell me a joke about {topic}\") | model\n",
"poem_chain = ChatPromptTemplate.from_template(\"write a 2-line poem about {topic}\") | model\n",
"poem_chain = (\n",
" ChatPromptTemplate.from_template(\"write a 2-line poem about {topic}\") | model\n",
")\n",
"\n",
"map_chain = RunnableParallel(joke=joke_chain, poem=poem_chain)\n",
"\n",
"map_chain.invoke({\"topic\": \"bear\"})\n"
"map_chain.invoke({\"topic\": \"bear\"})"
]
},
{
@@ -75,7 +77,9 @@
"from langchain.schema.runnable import RunnablePassthrough\n",
"from langchain.vectorstores import FAISS\n",
"\n",
"vectorstore = FAISS.from_texts([\"harrison worked at kensho\"], embedding=OpenAIEmbeddings())\n",
"vectorstore = FAISS.from_texts(\n",
" [\"harrison worked at kensho\"], embedding=OpenAIEmbeddings()\n",
")\n",
"retriever = vectorstore.as_retriever()\n",
"template = \"\"\"Answer the question based only on the following context:\n",
"{context}\n",
@@ -85,13 +89,13 @@
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"retrieval_chain = (\n",
" {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
" | prompt \n",
" | model \n",
" {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")\n",
"\n",
"retrieval_chain.invoke(\"where did harrison work?\")\n"
"retrieval_chain.invoke(\"where did harrison work?\")"
]
},
{
@@ -131,7 +135,7 @@
"source": [
"%%timeit\n",
"\n",
"joke_chain.invoke({\"topic\": \"bear\"})\n"
"joke_chain.invoke({\"topic\": \"bear\"})"
]
},
{
@@ -151,7 +155,7 @@
"source": [
"%%timeit\n",
"\n",
"poem_chain.invoke({\"topic\": \"bear\"})\n"
"poem_chain.invoke({\"topic\": \"bear\"})"
]
},
{
@@ -171,7 +175,7 @@
"source": [
"%%timeit\n",
"\n",
"map_chain.invoke({\"topic\": \"bear\"})\n"
"map_chain.invoke({\"topic\": \"bear\"})"
]
}
],
@@ -191,7 +195,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -5,7 +5,7 @@
"id": "4b47436a",
"metadata": {},
"source": [
"# Route between multiple Runnables\n",
"# Dynamically route logic based on input\n",
"\n",
"This notebook covers how to do routing in the LangChain Expression Language.\n",
"\n",
@@ -60,7 +60,9 @@
"metadata": {},
"outputs": [],
"source": [
"chain = PromptTemplate.from_template(\"\"\"Given the user question below, classify it as either being about `LangChain`, `Anthropic`, or `Other`.\n",
"chain = (\n",
" PromptTemplate.from_template(\n",
" \"\"\"Given the user question below, classify it as either being about `LangChain`, `Anthropic`, or `Other`.\n",
" \n",
"Do not respond with more than one word.\n",
"\n",
@@ -68,7 +70,11 @@
"{question}\n",
"</question>\n",
"\n",
"Classification:\"\"\") | ChatAnthropic() | StrOutputParser()"
"Classification:\"\"\"\n",
" )\n",
" | ChatAnthropic()\n",
" | StrOutputParser()\n",
")"
]
},
{
@@ -107,22 +113,37 @@
"metadata": {},
"outputs": [],
"source": [
"langchain_chain = PromptTemplate.from_template(\"\"\"You are an expert in langchain. \\\n",
"langchain_chain = (\n",
" PromptTemplate.from_template(\n",
" \"\"\"You are an expert in langchain. \\\n",
"Always answer questions starting with \"As Harrison Chase told me\". \\\n",
"Respond to the following question:\n",
"\n",
"Question: {question}\n",
"Answer:\"\"\") | ChatAnthropic()\n",
"anthropic_chain = PromptTemplate.from_template(\"\"\"You are an expert in anthropic. \\\n",
"Answer:\"\"\"\n",
" )\n",
" | ChatAnthropic()\n",
")\n",
"anthropic_chain = (\n",
" PromptTemplate.from_template(\n",
" \"\"\"You are an expert in anthropic. \\\n",
"Always answer questions starting with \"As Dario Amodei told me\". \\\n",
"Respond to the following question:\n",
"\n",
"Question: {question}\n",
"Answer:\"\"\") | ChatAnthropic()\n",
"general_chain = PromptTemplate.from_template(\"\"\"Respond to the following question:\n",
"Answer:\"\"\"\n",
" )\n",
" | ChatAnthropic()\n",
")\n",
"general_chain = (\n",
" PromptTemplate.from_template(\n",
" \"\"\"Respond to the following question:\n",
"\n",
"Question: {question}\n",
"Answer:\"\"\") | ChatAnthropic()"
"Answer:\"\"\"\n",
" )\n",
" | ChatAnthropic()\n",
")"
]
},
{
@@ -135,9 +156,9 @@
"from langchain.schema.runnable import RunnableBranch\n",
"\n",
"branch = RunnableBranch(\n",
" (lambda x: \"anthropic\" in x[\"topic\"].lower(), anthropic_chain),\n",
" (lambda x: \"langchain\" in x[\"topic\"].lower(), langchain_chain),\n",
" general_chain\n",
" (lambda x: \"anthropic\" in x[\"topic\"].lower(), anthropic_chain),\n",
" (lambda x: \"langchain\" in x[\"topic\"].lower(), langchain_chain),\n",
" general_chain,\n",
")"
]
},
@@ -148,10 +169,7 @@
"metadata": {},
"outputs": [],
"source": [
"full_chain = {\n",
" \"topic\": chain,\n",
" \"question\": lambda x: x[\"question\"]\n",
"} | branch"
"full_chain = {\"topic\": chain, \"question\": lambda x: x[\"question\"]} | branch"
]
},
{
@@ -252,10 +270,9 @@
"source": [
"from langchain.schema.runnable import RunnableLambda\n",
"\n",
"full_chain = {\n",
" \"topic\": chain,\n",
" \"question\": lambda x: x[\"question\"]\n",
"} | RunnableLambda(route)"
"full_chain = {\"topic\": chain, \"question\": lambda x: x[\"question\"]} | RunnableLambda(\n",
" route\n",
")"
]
},
{

View File

@@ -4,33 +4,30 @@ sidebar_class_name: hidden
# LangChain Expression Language (LCEL)
LangChain Expression Language or LCEL is a declarative way to easily compose chains together.
There are several benefits to writing chains in this manner (as opposed to writing normal code):
LangChain Expression Language, or LCEL, is a declarative way to easily compose chains together.
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 (weve seen folks successfully run LCEL chains with 100s of steps in production). To highlight a few of the reasons you might want to use LCEL:
**Async, Batch, and Streaming Support**
Any chain constructed this way will automatically have full sync, async, batch, and streaming support.
This makes it easy to prototype a chain in a Jupyter notebook using the sync interface, and then expose it as an async streaming interface.
**Streaming support**
When you build your chains with LCEL you get the best possible time-to-first-token (time elapsed until the first chunk of output comes out). For some chains this means eg. we stream tokens straight from an LLM to a streaming output parser, and you get back parsed, incremental chunks of output at the same rate as the LLM provider outputs the raw tokens.
**Fallbacks**
The non-determinism of LLMs makes it important to be able to handle errors gracefully.
With LCEL you can easily attach fallbacks to any chain.
**Async support**
Any chain built with LCEL can be called both with the synchronous API (eg. in your Jupyter notebook while prototyping) as well as with the asynchronous API (eg. in a [LangServe](/docs/langsmith) server). This enables using the same code for prototypes and in production, with great performance, and the ability to handle many concurrent requests in the same server.
**Parallelism**
Since LLM applications involve (sometimes long) API calls, it often becomes important to run things in parallel.
With LCEL syntax, any components that can be run in parallel automatically are.
**Optimized parallel execution**
Whenever your LCEL chains have steps that can be executed in parallel (eg if you fetch documents from multiple retrievers) we automatically do it, both in the sync and the async interfaces, for the smallest possible latency.
**Seamless LangSmith Tracing Integration**
**Retries and fallbacks**
Configure retries and fallbacks for any part of your LCEL chain. This is a great way to make your chains more reliable at scale. Were currently working on adding streaming support for retries/fallbacks, so you can get the added reliability without any latency cost.
**Access intermediate results**
For more complex chains its often very useful to access the results of intermediate steps even before the final output is produced. This can be used let end-users know something is happening, or even just to debug your chain. You can stream intermediate results, and its available on every [LangServe](/docs/langserve) server.
**Input and output schemas**
Input and output schemas give every LCEL chain Pydantic and JSONSchema schemas inferred from the structure of your chain. This can be used for validation of inputs and outputs, and is an integral part of LangServe.
**Seamless LangSmith tracing integration**
As your chains get more and more complex, it becomes increasingly important to understand what exactly is happening at every step.
With LCEL, **all** steps are automatically logged to [LangSmith](https://smith.langchain.com) for maximal observability and debuggability.
With LCEL, **all** steps are automatically logged to [LangSmith](/docs/langsmith/) for maximum observability and debuggability.
#### [Interface](/docs/expression_language/interface)
The base interface shared by all LCEL objects
#### [How to](/docs/expression_language/how_to)
How to use core features of LCEL
#### [Cookbook](/docs/expression_language/cookbook)
Examples of common LCEL usage patterns
#### [Why use LCEL](/docs/expression_language/why)
A deeper dive into the benefits of LCEL
**Seamless LangServe deployment integration**
Any chain created with LCEL can be easily deployed using LangServe.

View File

@@ -8,7 +8,7 @@
"---\n",
"sidebar_position: 0\n",
"title: Interface\n",
"---\n"
"---"
]
},
{
@@ -31,26 +31,17 @@
"- [`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",
"\n",
"The **input type** varies by component:\n",
"The **input type** and **output type** varies by component:\n",
"\n",
"| Component | Input Type |\n",
"| --- | --- |\n",
"|Prompt|Dictionary|\n",
"|Retriever|Single string|\n",
"|LLM, ChatModel| Single string, list of chat messages or a PromptValue|\n",
"|Tool|Single string, or dictionary, depending on the tool|\n",
"|OutputParser|The output of an LLM or ChatModel|\n",
"| Component | Input Type | Output Type |\n",
"| --- | --- | --- |\n",
"| Prompt | Dictionary | PromptValue |\n",
"| ChatModel | Single string, list of chat messages or a PromptValue | ChatMessage |\n",
"| LLM | Single string, list of chat messages or a PromptValue | String |\n",
"| OutputParser | The output of an LLM or ChatModel | Depends on the parser |\n",
"| Retriever | Single string | List of Documents |\n",
"| Tool | Single string or dictionary, depending on the tool | Depends on the tool |\n",
"\n",
"The **output type** also varies by component:\n",
"\n",
"| Component | Output Type |\n",
"| --- | --- |\n",
"| LLM | String |\n",
"| ChatModel | ChatMessage |\n",
"| Prompt | PromptValue |\n",
"| Retriever | List of documents |\n",
"| Tool | Depends on the tool |\n",
"| OutputParser | Depends on the parser |\n",
"\n",
"All runnables expose input and output **schemas** to inspect the inputs and outputs:\n",
"- [`input_schema`](#input-schema): an input Pydantic model auto-generated from the structure of the Runnable\n",
@@ -680,19 +671,26 @@
"\"\"\"\n",
"prompt = ChatPromptTemplate.from_template(template)\n",
"\n",
"vectorstore = FAISS.from_texts([\"harrison worked at kensho\"], embedding=OpenAIEmbeddings())\n",
"vectorstore = FAISS.from_texts(\n",
" [\"harrison worked at kensho\"], embedding=OpenAIEmbeddings()\n",
")\n",
"retriever = vectorstore.as_retriever()\n",
"\n",
"retrieval_chain = (\n",
" {\"context\": retriever.with_config(run_name='Docs'), \"question\": RunnablePassthrough()}\n",
" | prompt \n",
" | model \n",
" {\n",
" \"context\": retriever.with_config(run_name=\"Docs\"),\n",
" \"question\": RunnablePassthrough(),\n",
" }\n",
" | prompt\n",
" | model\n",
" | StrOutputParser()\n",
")\n",
"\n",
"async for chunk in retrieval_chain.astream_log(\"where did harrison work?\", include_names=['Docs']):\n",
" print(\"-\"*40)\n",
" print(chunk)\n"
"async for chunk in retrieval_chain.astream_log(\n",
" \"where did harrison work?\", include_names=[\"Docs\"]\n",
"):\n",
" print(\"-\" * 40)\n",
" print(chunk)"
]
},
{
@@ -897,8 +895,10 @@
}
],
"source": [
"async for chunk in retrieval_chain.astream_log(\"where did harrison work?\", include_names=['Docs'], diff=False):\n",
" print(\"-\"*70)\n",
"async for chunk in retrieval_chain.astream_log(\n",
" \"where did harrison work?\", include_names=[\"Docs\"], diff=False\n",
"):\n",
" print(\"-\" * 70)\n",
" print(chunk)"
]
},
@@ -921,8 +921,12 @@
"outputs": [],
"source": [
"from langchain.schema.runnable import RunnableParallel\n",
"\n",
"chain1 = ChatPromptTemplate.from_template(\"tell me a joke about {topic}\") | model\n",
"chain2 = ChatPromptTemplate.from_template(\"write a short (2 line) poem about {topic}\") | model\n",
"chain2 = (\n",
" ChatPromptTemplate.from_template(\"write a short (2 line) poem about {topic}\")\n",
" | model\n",
")\n",
"combined = RunnableParallel(joke=chain1, poem=chain2)"
]
},
@@ -1148,7 +1152,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -1,11 +0,0 @@
# Why use LCEL?
The LangChain Expression Language 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 (weve seen folks successfully running in production LCEL chains with 100s of steps). To highlight a few of the reasons you might want to use LCEL:
- first-class support for streaming: when you build your chains with LCEL you get the best possible time-to-first-token (time elapsed until the first chunk of output comes out). For some chains this means eg. we stream tokens straight from an LLM to a streaming output parser, and you get back parsed, incremental chunks of output at the same rate as the LLM provider outputs the raw tokens. Were constantly improving streaming support, recently we added a [streaming JSON parser](https://twitter.com/LangChainAI/status/1709690468030914584), and more is in the works.
- first-class async support: any chain built with LCEL can be called both with the synchronous API (eg. in your Jupyter notebook while prototyping) as well as with the asynchronous API (eg. in a [LangServe](https://github.com/langchain-ai/langserve) server). This enables using the same code for prototypes and in production, with great performance, and the ability to handle many concurrent requests in the same server.
- optimised parallel execution: whenever your LCEL chains have steps that can be executed in parallel (eg if you fetch documents from multiple retrievers) we automatically do it, both in the sync and the async interfaces, for the smallest possible latency.
- support for retries and fallbacks: more recently weve added support for configuring retries and fallbacks for any part of your LCEL chain. This is a great way to make your chains more reliable at scale. Were currently working on adding streaming support for retries/fallbacks, so you can get the added reliability without any latency cost.
- accessing intermediate results: for more complex chains its often very useful to access the results of intermediate steps even before the final output is produced. This can be used let end-users know something is happening, or even just to debug your chain. Weve added support for [streaming intermediate results](https://x.com/LangChainAI/status/1711806009097044193?s=20), and its available on every LangServe server.
- [input and output schemas](https://x.com/LangChainAI/status/1711805322195861934?s=20): input and output schemas give every LCEL chain Pydantic and JSONSchema schemas inferred from the structure of your chain. This can be used for validation of inputs and outputs, and is an integral part of LangServe.
- tracing with LangSmith: all chains built with LCEL have first-class tracing support, which can be used to debug your chains, or to understand whats happening in production. To enable this all you have to do is add your [LangSmith](https://www.langchain.com/langsmith) API key as an environment variable.

View File

@@ -19,26 +19,7 @@ import CodeBlock from "@theme/CodeBlock";
This will install the bare minimum requirements of LangChain.
A lot of the value of LangChain comes when integrating it with various model providers, datastores, etc.
By default, the dependencies needed to do that are NOT installed.
However, there are two other ways to install LangChain that do bring in those dependencies.
To install modules needed for the common LLM providers, run:
```bash
pip install langchain[llms]
```
To install all modules needed for all integrations, run:
```bash
pip install langchain[all]
```
Note that if you are using `zsh`, you'll need to quote square brackets when passing them as an argument to a command, for example:
```bash
pip install 'langchain[all]'
```
By default, the dependencies needed to do that are NOT installed. You will need to install the dependencies for specific integrations separately.
## From source
@@ -47,3 +28,37 @@ If you want to install from source, you can do so by cloning the repo and be sur
```bash
pip install -e .
```
## Langchain experimental
The `langchain-experimental` package holds experimental LangChain code, intended for research and experimental uses.
Install with:
```bash
pip install langchain-experimental
```
## LangChain CLI
The LangChain CLI is useful for working with LangChain templates and other LangServe projects.
Install with:
```bash
pip install langchain-cli
```
## LangServe
LangServe helps developers deploy LangChain runnables and chains as a REST API.
LangServe is automatically installed by LangChain CLI.
If not using LangChain CLI, install with:
```bash
pip install "langserve[all]"
```
for both client and server dependencies. Or `pip install "langserve[client]"` for client code, and `pip install "langserve[server]"` for server code.
## LangSmith SDK
The LangSmith SDK is automatically installed by LangChain.
If not using LangChain, install with:
```bash
pip install langsmith
```

View File

@@ -8,11 +8,26 @@ sidebar_position: 0
- **Are context-aware**: connect a language model to sources of context (prompt instructions, few shot examples, content to ground its response in, etc.)
- **Reason**: rely on a language model to reason (about how to answer based on provided context, what actions to take, etc.)
The main value props of LangChain are:
1. **Components**: abstractions for working with language models, along with a collection of implementations for each abstraction. Components are modular and easy-to-use, whether you are using the rest of the LangChain framework or not
2. **Off-the-shelf chains**: a structured assembly of components for accomplishing specific higher-level tasks
This framework consists of several parts.
- **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.
- **[LangChain Templates](/docs/templates)**: A collection of easily deployable reference architectures for a wide variety of tasks.
- **[LangServe](/docs/langserve)**: A library for deploying LangChain chains as a REST API.
- **[LangSmith](/docs/langsmith)**: A developer platform that lets you debug, test, evaluate, and monitor chains built on any LLM framework and seamlessly integrates with LangChain.
Off-the-shelf chains make it easy to get started. For complex applications, components make it easy to customize existing chains and build new ones.
![LangChain Diagram](/img/langchain_stack.png)
Together, these products simplify the entire application lifecycle:
- **Develop**: Write your applications in LangChain/LangChain.js. Hit the ground running using Templates for reference.
- **Productionize**: Use LangSmith to inspect, test and monitor your chains, so that you can constantly improve and deploy with confidence.
- **Deploy**: Turn any chain into an API with LangServe.
## LangChain Libraries
The main value props of the LangChain packages are:
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
2. **Off-the-shelf chains**: built-in assemblages of components for accomplishing higher-level tasks
Off-the-shelf chains make it easy to get started. Components make it easy to customize existing chains and build new ones.
## Get started
@@ -20,45 +35,59 @@ Off-the-shelf chains make it easy to get started. For complex applications, comp
We recommend following our [Quickstart](/docs/get_started/quickstart) guide to familiarize yourself with the framework by building your first LangChain application.
_**Note**: These docs are for the LangChain [Python package](https://github.com/langchain-ai/langchain). For documentation on [LangChain.js](https://github.com/langchain-ai/langchainjs), the JS/TS version, [head here](https://js.langchain.com/docs)._
Read up on our [Security](/docs/security) best practices to make sure you're developing safely with LangChain.
:::note
These docs focus on the Python LangChain library. [Head here](https://js.langchain.com) for docs on the JavaScript LangChain library.
:::
## LangChain Expression Language (LCEL)
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.
- **[Overview](/docs/expression_language/)**: LCEL and its benefits
- **[Interface](/docs/expression_language/interface)**: The standard interface for LCEL objects
- **[How-to](/docs/expression_language/interface)**: Key features of LCEL
- **[Cookbook](/docs/expression_language/cookbook)**: Example code for accomplishing common tasks
## Modules
LangChain provides standard, extendable interfaces and external integrations for the following modules, listed from least to most complex:
LangChain provides standard, extendable interfaces and integrations for the following modules:
#### [Model I/O](/docs/modules/model_io/)
Interface with language models
#### [Retrieval](/docs/modules/data_connection/)
Interface with application-specific data
#### [Chains](/docs/modules/chains/)
Construct sequences of calls
#### [Agents](/docs/modules/agents/)
Let chains choose which tools to use given high-level directives
#### [Memory](/docs/modules/memory/)
Persist application state between runs of a chain
#### [Callbacks](/docs/modules/callbacks/)
Log and stream intermediate steps of any chain
Let models choose which tools to use given high-level directives
## Examples, ecosystem, and resources
### [Use cases](/docs/use_cases/question_answering/)
Walkthroughs and best-practices for common end-to-end use cases, like:
Walkthroughs and techniques for common end-to-end use cases, like:
- [Document question answering](/docs/use_cases/question_answering/)
- [Chatbots](/docs/use_cases/chatbots/)
- [Analyzing structured data](/docs/use_cases/qa_structured/sql/)
- and much more...
### [Guides](/docs/guides/)
Learn best practices for developing with LangChain.
### [Integrations](/docs/integrations/providers/)
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](/docs/integrations/providers/).
### [Ecosystem](/docs/integrations/providers/)
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](/docs/integrations/providers/) and [dependent repos](/docs/additional_resources/dependents).
### [Guides](/docs/guides/adapters/openai)
Best practices for developing with LangChain.
### [Additional resources](/docs/additional_resources/)
Our community is full of prolific developers, creative builders, and fantastic teachers. Check out [YouTube tutorials](/docs/additional_resources/youtube) for great tutorials from folks in the community, and [Gallery](https://github.com/kyrolabs/awesome-langchain) for a list of awesome LangChain projects, compiled by the folks at [KyroLabs](https://kyrolabs.com).
### [API reference](https://api.python.langchain.com)
Head to the reference section for full documentation of all classes and methods in the LangChain and LangChain Experimental Python packages.
### [Developer's guide](/docs/contributing)
Check out the developer's guide for guidelines on contributing and help getting your dev environment set up.
### [Community](/docs/community)
Head to the [Community navigator](/docs/community) to find places to ask questions, share feedback, meet other developers, and dream about the future of LLMs.
## API reference
Head to the [reference](https://api.python.langchain.com) section for full documentation of all classes and methods in the LangChain Python package.

View File

@@ -1,6 +1,17 @@
# Quickstart
## Installation
In this quickstart we'll show you how to:
- Get setup with LangChain, LangSmith and LangServe
- Use the most basic and common components of LangChain: prompt templates, models, and output parsers
- Use LangChain Expression Language, the protocol that LangChain is built on and which facilitates component chaining
- Build simple application with LangChain
- Trace your application with LangSmith
- Serve your application with LangServe
That's a fair amount to cover! Let's dive in.
## Setup
### Installation
To install LangChain run:
@@ -20,7 +31,7 @@ import CodeBlock from "@theme/CodeBlock";
For more details, see our [Installation guide](/docs/get_started/installation).
## Environment setup
### Environment
Using LangChain will usually require integrations with one or more model providers, data stores, APIs, etc. For this example, we'll use OpenAI's model APIs.
@@ -39,54 +50,79 @@ export OPENAI_API_KEY="..."
If you'd prefer not to set an environment variable you can pass the key in directly via the `openai_api_key` named parameter when initiating the OpenAI LLM class:
```python
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
llm = OpenAI(openai_api_key="...")
llm = ChatOpenAI(openai_api_key="...")
```
### LangSmith
## Building an application
Many of the applications you build with LangChain will contain multiple steps with multiple invocations of LLM calls.
As these applications get more and more complex, it becomes crucial to be able to inspect what exactly is going on inside your chain or agent.
The best way to do this is with [LangSmith](https://smith.langchain.com).
Now we can start building our language model application. LangChain provides many modules that can be used to build language model applications.
Modules can be used as stand-alones in simple applications and they can be combined for more complex use cases.
Note that LangSmith is not needed, but it is helpful.
If you do want to use LangSmith, after you sign up at the link above, make sure to set your environment variables to start logging traces:
The most common and most important chain that LangChain helps create contains three things:
- LLM: The language model is the core reasoning engine here. In order to work with LangChain, you need to understand the different types of language models and how to work with them.
- Prompt Templates: This provides instructions to the language model. This controls what the language model outputs, so understanding how to construct prompts and different prompting strategies is crucial.
- Output Parsers: These translate the raw response from the LLM to a more workable format, making it easy to use the output downstream.
```shell
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY=...
```
In this getting started guide we will cover those three components by themselves, and then go over how to combine all of them.
### LangServe
LangServe helps developers deploy LangChain chains as a REST API. You do not need to use LangServe to use LangChain, but in this guide we'll show how you can deploy your app with LangServe.
Install with:
```bash
pip install "langserve[all]"
```
## Building with LangChain
LangChain provides many modules that can be used to build language model applications.
Modules can be used as standalones in simple applications and they can be composed for more complex use cases.
Composition is powered by **LangChain Expression Language** (LCEL), which defines a unified `Runnable` interface that many modules implement, making it possible to seamlessly chain components.
The simplest and most common chain contains three things:
- LLM/Chat Model: The language model is the core reasoning engine here. In order to work with LangChain, you need to understand the different types of language models and how to work with them.
- Prompt Template: This provides instructions to the language model. This controls what the language model outputs, so understanding how to construct prompts and different prompting strategies is crucial.
- Output Parser: These translate the raw response from the language model to a more workable format, making it easy to use the output downstream.
In this guide we'll cover those three components individually, and then go over how to combine them.
Understanding these concepts will set you up well for being able to use and customize LangChain applications.
Most LangChain applications allow you to configure the LLM and/or the prompt used, so knowing how to take advantage of this will be a big enabler.
Most LangChain applications allow you to configure the model and/or the prompt, so knowing how to take advantage of this will be a big enabler.
## LLMs
### LLM / Chat Model
There are two types of language models, which in LangChain are called:
There are two types of language models:
- LLMs: this is a language model which takes a string as input and returns a string
- ChatModels: this is a language model which takes a list of messages as input and returns a message
- `LLM`: underlying model takes a string as input and returns a string
- `ChatModel`: underlying model takes a list of messages as input and returns a message
The input/output for LLMs is simple and easy to understand - a string.
But what about ChatModels? The input there is a list of `ChatMessages`, and the output is a single `ChatMessage`.
A `ChatMessage` has two required components:
Strings are simple, but what exactly are messages? The base message interface is defined by `BaseMessage`, which has two required attributes:
- `content`: This is the content of the message.
- `role`: This is the role of the entity from which the `ChatMessage` is coming from.
- `content`: The content of the message. Usually a string.
- `role`: The entity from which the `BaseMessage` is coming.
LangChain provides several objects to easily distinguish between different roles:
- `HumanMessage`: A `ChatMessage` coming from a human/user.
- `AIMessage`: A `ChatMessage` coming from an AI/assistant.
- `SystemMessage`: A `ChatMessage` coming from the system.
- `FunctionMessage`: A `ChatMessage` coming from a function call.
- `HumanMessage`: A `BaseMessage` coming from a human/user.
- `AIMessage`: A `BaseMessage` coming from an AI/assistant.
- `SystemMessage`: A `BaseMessage` coming from the system.
- `FunctionMessage` / `ToolMessage`: A `BaseMessage` containing the output of a function or tool call.
If none of those roles sound right, there is also a `ChatMessage` class where you can specify the role manually.
For more information on how to use these different messages most effectively, see our prompting guide.
LangChain provides a standard interface for both, but it's useful to understand this difference in order to construct prompts for a given language model.
The standard interface that LangChain provides has two methods:
- `predict`: Takes in a string, returns a string
- `predict_messages`: Takes in a list of messages, returns a message.
LangChain provides a common interface that's shared by both `LLM`s and `ChatModel`s.
However it's useful to understand the difference in order to most effectively construct prompts for a given language model.
The simplest way to call an `LLM` or `ChatModel` is using `.invoke()`, the universal synchronous call method for all LangChain Expression Language (LCEL) objects:
- `LLM.invoke`: Takes in a string, returns a string.
- `ChatModel.invoke`: Takes in a list of `BaseMessage`, returns a `BaseMessage`.
The input types for these methods are actually more general than this, but for simplicity here we can assume LLMs only take strings and Chat models only takes lists of messages.
Check out the "Go deeper" section below to learn more about model invocation.
Let's see how to work with these different types of models and these different types of inputs.
First, let's import an LLM and a ChatModel.
@@ -97,50 +133,36 @@ from langchain.chat_models import ChatOpenAI
llm = OpenAI()
chat_model = ChatOpenAI()
llm.predict("hi!")
>>> "Hi"
chat_model.predict("hi!")
>>> "Hi"
```
The `OpenAI` and `ChatOpenAI` objects are basically just configuration objects.
`LLM` and `ChatModel` objects are effectively configuration objects.
You can initialize them with parameters like `temperature` and others, and pass them around.
Next, let's use the `predict` method to run over a string input.
```python
text = "What would be a good company name for a company that makes colorful socks?"
llm.predict(text)
# >> Feetful of Fun
chat_model.predict(text)
# >> Socks O'Color
```
Finally, let's use the `predict_messages` method to run over a list of messages.
```python
from langchain.schema import HumanMessage
text = "What would be a good company name for a company that makes colorful socks?"
messages = [HumanMessage(content=text)]
llm.predict_messages(messages)
llm.invoke(text)
# >> Feetful of Fun
chat_model.predict_messages(messages)
# >> Socks O'Color
chat_model.invoke(messages)
# >> AIMessage(content="Socks O'Color")
```
For both these methods, you can also pass in parameters as keyword arguments.
For example, you could pass in `temperature=0` to adjust the temperature that is used from what the object was configured with.
Whatever values are passed in during run time will always override what the object was configured with.
<details> <summary>Go deeper</summary>
`LLM.invoke` and `ChatModel.invoke` actually both support as input any of `Union[str, List[BaseMessage], PromptValue]`.
`PromptValue` is an object that defines it's own custom logic for returning it's inputs either as a string or as messages.
`LLM`s have logic for coercing any of these into a string, and `ChatModel`s have logic for coercing any of these to messages.
The fact that `LLM` and `ChatModel` accept the same inputs means that you can directly swap them for one another in most chains without breaking anything,
though it's of course important to think about how inputs are being coerced and how that may affect model performance.
To dive deeper on models head to the [Language models](/docs/modules/model_io/models) section.
## Prompt templates
</details>
### Prompt templates
Most LLM applications do not pass user input directly into an LLM. Usually they will add the user input to a larger piece of text, called a prompt template, that provides additional context on the specific task at hand.
@@ -157,7 +179,7 @@ prompt = PromptTemplate.from_template("What is a good name for a company that ma
prompt.format(product="colorful socks")
```
```pycon
```python
What is a good name for a company that makes colorful socks?
```
@@ -166,10 +188,10 @@ You can "partial" out variables - e.g. you can format only some of the variables
You can compose them together, easily combining different templates into a single prompt.
For explanations of these functionalities, see the [section on prompts](/docs/modules/model_io/prompts) for more detail.
PromptTemplates can also be used to produce a list of messages.
`PromptTemplate`s can also be used to produce a list of messages.
In this case, the prompt not only contains information about the content, but also each message (its role, its position in the list, etc.).
Here, what happens most often is a ChatPromptTemplate is a list of ChatMessageTemplates.
Each ChatMessageTemplate contains instructions for how to format that ChatMessage - its role, and then also its content.
Here, what happens most often is a `ChatPromptTemplate` is a list of `ChatMessageTemplates`.
Each `ChatMessageTemplate` contains instructions for how to format that `ChatMessage` - its role, and then also its content.
Let's take a look at this below:
```python
@@ -196,13 +218,13 @@ chat_prompt.format_messages(input_language="English", output_language="French",
ChatPromptTemplates can also be constructed in other ways - see the [section on prompts](/docs/modules/model_io/prompts) for more detail.
## Output parsers
### Output parsers
OutputParsers convert the raw output of an LLM into a format that can be used downstream.
There are few main types of OutputParsers, including:
`OutputParsers` convert the raw output of a language model into a format that can be used downstream.
There are few main types of `OutputParser`s, including:
- Convert text from LLM into structured information (e.g. JSON)
- Convert a ChatMessage into just a string
- Convert text from `LLM` into structured information (e.g. JSON)
- Convert a `ChatMessage` into just a string
- Convert the extra information returned from a call besides the message (like OpenAI function invocation) into a string.
For full information on this, see the [section on output parsers](/docs/modules/model_io/output_parsers).
@@ -224,7 +246,7 @@ CommaSeparatedListOutputParser().parse("hi, bye")
# >> ['hi', 'bye']
```
## PromptTemplate + LLM + OutputParser
### Composing with LCEL
We can now combine all these into one chain.
This chain will take input variables, pass those to a prompt template to create a prompt, pass the prompt to a language model, and then pass the output through an (optional) output parser.
@@ -232,15 +254,17 @@ This is a convenient way to bundle up a modular piece of logic.
Let's see it in action!
```python
from typing import List
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import ChatPromptTemplate
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser
class CommaSeparatedListOutputParser(BaseOutputParser):
class CommaSeparatedListOutputParser(BaseOutputParser[List[str]]):
"""Parse the output of an LLM call to a comma-separated list."""
def parse(self, text: str):
def parse(self, text: str) -> List[str]:
"""Parse the output of an LLM call."""
return text.strip().split(", ")
@@ -258,20 +282,118 @@ chain.invoke({"text": "colors"})
# >> ['red', 'blue', 'green', 'yellow', 'orange']
```
Note that we are using the `|` syntax to join these components together.
This `|` syntax is called the LangChain Expression Language.
To learn more about this syntax, read the documentation [here](/docs/expression_language).
This `|` syntax is powered by the LangChain Expression Language (LCEL) and relies on the universal `Runnable` interface that all of these objects implement.
To learn more about LCEL, read the documentation [here](/docs/expression_language).
## Tracing with LangSmith
Assuming we've set our environment variables as shown in the beginning, all of the model and chain calls we've been making will have been automatically logged to LangSmith.
Once there, we can use LangSmith to debug and annotate our application traces, then turn them into datasets for evaluating future iterations of the application.
Check out what the trace for the above chain would look like:
https://smith.langchain.com/public/09370280-4330-4eb4-a7e8-c91817f6aa13/r
For more on LangSmith [head here](/docs/langsmith/).
## Serving with LangServe
Now that we've built an application, we need to serve it. That's where LangServe comes in.
LangServe helps developers deploy LCEL chains as a REST API.
The library is integrated with FastAPI and uses pydantic for data validation.
### Server
To create a server for our application we'll make a `serve.py` file with three things:
1. The definition of our chain (same as above)
2. Our FastAPI app
3. A definition of a route from which to serve the chain, which is done with `langserve.add_routes`
```python
#!/usr/bin/env python
from typing import List
from fastapi import FastAPI
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import BaseOutputParser
from langserve import add_routes
# 1. Chain definition
class CommaSeparatedListOutputParser(BaseOutputParser[List[str]]):
"""Parse the output of an LLM call to a comma-separated list."""
def parse(self, text: str) -> List[str]:
"""Parse the output of an LLM call."""
return text.strip().split(", ")
template = """You are a helpful assistant who generates comma separated lists.
A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
ONLY return a comma separated list, and nothing more."""
human_template = "{text}"
chat_prompt = ChatPromptTemplate.from_messages([
("system", template),
("human", human_template),
])
category_chain = chat_prompt | ChatOpenAI() | CommaSeparatedListOutputParser()
# 2. App definition
app = FastAPI(
title="LangChain Server",
version="1.0",
description="A simple api server using Langchain's Runnable interfaces",
)
# 3. Adding chain route
add_routes(
app,
category_chain,
path="/category_chain",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
```
And that's it! If we execute this file:
```bash
python serve.py
```
we should see our chain being served at localhost:8000.
### Playground
Every LangServe service comes with a simple built-in UI for configuring and invoking the application with streaming output and visibility into intermediate steps.
Head to http://localhost:8000/category_chain/playground/ to try it out!
### Client
Now let's set up a client for programmatically interacting with our service. We can easily do this with the `langserve.RemoteRunnable`.
Using this, we can interact with the served chain as if it were running client-side.
```python
from langserve import RemoteRunnable
remote_chain = RemoteRunnable("http://localhost:8000/category_chain/")
remote_chain.invoke({"text": "colors"})
# >> ['red', 'blue', 'green', 'yellow', 'orange']
```
To learn more about the many other features of LangServe [head here](/docs/langserve).
## Next steps
This is it!
We've now gone over how to create the core building block of LangChain applications.
There is a lot more nuance in all these components (LLMs, prompts, output parsers) and a lot more different components to learn about as well.
We've touched on how to build an application with LangChain, how to trace it with LangSmith, and how to serve it with LangServe.
There are a lot more features in all three of these than we can cover here.
To continue on your journey:
- [Dive deeper](/docs/modules/model_io) into LLMs, prompts, and output parsers
- Learn the other [key components](/docs/modules)
- Read up on [LangChain Expression Language](/docs/expression_language) to learn how to chain these components together
- Check out our [helpful guides](/docs/guides) for detailed walkthroughs on particular topics
- Explore [end-to-end use cases](/docs/use_cases)
- Read up on [LangChain Expression Language (LCEL)](/docs/expression_language) to learn how to chain these components together
- [Dive deeper](/docs/modules/model_io) into LLMs, prompts, and output parsers and learn the other [key components](/docs/modules)
- Explore common [end-to-end use cases](/docs/use_cases/qa_structured/sql) and [template applications](/docs/templates)
- [Read up on LangSmith](/docs/langsmith/), the platform for debugging, testing, monitoring and more
- Learn more about serving your applications with [LangServe](/docs/langserve)

View File

@@ -57,9 +57,7 @@
"outputs": [],
"source": [
"result = openai.ChatCompletion.create(\n",
" messages=messages, \n",
" model=\"gpt-3.5-turbo\", \n",
" temperature=0\n",
" messages=messages, model=\"gpt-3.5-turbo\", temperature=0\n",
")"
]
},
@@ -81,7 +79,7 @@
}
],
"source": [
"result[\"choices\"][0]['message'].to_dict_recursive()"
"result[\"choices\"][0][\"message\"].to_dict_recursive()"
]
},
{
@@ -100,9 +98,7 @@
"outputs": [],
"source": [
"lc_result = lc_openai.ChatCompletion.create(\n",
" messages=messages, \n",
" model=\"gpt-3.5-turbo\", \n",
" temperature=0\n",
" messages=messages, model=\"gpt-3.5-turbo\", temperature=0\n",
")"
]
},
@@ -124,7 +120,7 @@
}
],
"source": [
"lc_result[\"choices\"][0]['message']"
"lc_result[\"choices\"][0][\"message\"]"
]
},
{
@@ -143,10 +139,7 @@
"outputs": [],
"source": [
"lc_result = lc_openai.ChatCompletion.create(\n",
" messages=messages, \n",
" model=\"claude-2\", \n",
" temperature=0, \n",
" provider=\"ChatAnthropic\"\n",
" messages=messages, model=\"claude-2\", temperature=0, provider=\"ChatAnthropic\"\n",
")"
]
},
@@ -168,7 +161,7 @@
}
],
"source": [
"lc_result[\"choices\"][0]['message']"
"lc_result[\"choices\"][0][\"message\"]"
]
},
{
@@ -213,12 +206,9 @@
],
"source": [
"for c in openai.ChatCompletion.create(\n",
" messages = messages,\n",
" model=\"gpt-3.5-turbo\", \n",
" temperature=0,\n",
" stream=True\n",
" messages=messages, model=\"gpt-3.5-turbo\", temperature=0, stream=True\n",
"):\n",
" print(c[\"choices\"][0]['delta'].to_dict_recursive())"
" print(c[\"choices\"][0][\"delta\"].to_dict_recursive())"
]
},
{
@@ -255,12 +245,9 @@
],
"source": [
"for c in lc_openai.ChatCompletion.create(\n",
" messages = messages,\n",
" model=\"gpt-3.5-turbo\", \n",
" temperature=0,\n",
" stream=True\n",
" messages=messages, model=\"gpt-3.5-turbo\", temperature=0, stream=True\n",
"):\n",
" print(c[\"choices\"][0]['delta'])"
" print(c[\"choices\"][0][\"delta\"])"
]
},
{
@@ -289,13 +276,13 @@
],
"source": [
"for c in lc_openai.ChatCompletion.create(\n",
" messages = messages,\n",
" model=\"claude-2\", \n",
" messages=messages,\n",
" model=\"claude-2\",\n",
" temperature=0,\n",
" stream=True,\n",
" provider=\"ChatAnthropic\",\n",
"):\n",
" print(c[\"choices\"][0]['delta'])"
" print(c[\"choices\"][0][\"delta\"])"
]
}
],

View File

@@ -8,7 +8,7 @@ Here are a few different tools and functionalities to aid in debugging.
## Tracing
Platforms with tracing capabilities like [LangSmith](/docs/guides/langsmith/) and [WandB](/docs/integrations/providers/wandb_tracing) are the most comprehensive solutions for debugging. These platforms make it easy to not only log and visualize LLM apps, but also to actively debug, test and refine them.
Platforms with tracing capabilities like [LangSmith](/docs/langsmith/) and [WandB](/docs/integrations/providers/wandb_tracing) are the most comprehensive solutions for debugging. These platforms make it easy to not only log and visualize LLM apps, but also to actively debug, test and refine them.
For anyone building production-grade LLM applications, we highly recommend using a platform like this.

View File

@@ -1,85 +1,7 @@
# Template repos
# LangChain Templates
So, you've created a really cool chain - now what? How do you deploy it and make it easily shareable with the world?
For more information on LangChain Templates, visit
This section covers several options for that. Note that these options are meant for quick deployment of prototypes and demos, not for production systems. If you need help with the deployment of a production system, please contact us directly.
What follows is a list of template GitHub repositories designed to be easily forked and modified to use your chain. This list is far from exhaustive, and we are EXTREMELY open to contributions here.
## [Streamlit](https://github.com/hwchase17/langchain-streamlit-template)
This repo serves as a template for how to deploy a LangChain with Streamlit.
It implements a chatbot interface.
It also contains instructions for how to deploy this app on the Streamlit platform.
## [Gradio (on Hugging Face)](https://github.com/hwchase17/langchain-gradio-template)
This repo serves as a template for how to deploy a LangChain with Gradio.
It implements a chatbot interface, with a "Bring-Your-Own-Token" approach (nice for not wracking up big bills).
It also contains instructions for how to deploy this app on the Hugging Face platform.
This is heavily influenced by James Weaver's [excellent examples](https://huggingface.co/JavaFXpert).
## [Chainlit](https://github.com/Chainlit/cookbook)
This repo is a cookbook explaining how to visualize and deploy LangChain agents with Chainlit.
You create ChatGPT-like UIs with Chainlit. Some of the key features include intermediary steps visualisation, element management & display (images, text, carousel, etc.) as well as cloud deployment.
Chainlit [doc](https://docs.chainlit.io/langchain) on the integration with LangChain
## [Beam](https://github.com/slai-labs/get-beam/tree/main/examples/langchain-question-answering)
This repo serves as a template for how to deploy a LangChain with [Beam](https://beam.cloud).
It implements a Question Answering app and contains instructions for deploying the app as a serverless REST API.
## [Vercel](https://github.com/homanp/vercel-langchain)
A minimal example on how to run LangChain on Vercel using Flask.
## [FastAPI + Vercel](https://github.com/msoedov/langcorn)
A minimal example on how to run LangChain on Vercel using FastAPI and LangCorn/Uvicorn.
## [Kinsta](https://github.com/kinsta/hello-world-langchain)
A minimal example on how to deploy LangChain to [Kinsta](https://kinsta.com) using Flask.
## [Fly.io](https://github.com/fly-apps/hello-fly-langchain)
A minimal example of how to deploy LangChain to [Fly.io](https://fly.io/) using Flask.
## [DigitalOcean App Platform](https://github.com/homanp/digitalocean-langchain)
A minimal example of how to deploy LangChain to DigitalOcean App Platform.
## [CI/CD Google Cloud Build + Dockerfile + Serverless Google Cloud Run](https://github.com/g-emarco/github-assistant)
Boilerplate LangChain project on how to deploy to Google Cloud Run using Docker with Cloud Build CI/CD pipeline.
## [Google Cloud Run](https://github.com/homanp/gcp-langchain)
A minimal example of how to deploy LangChain to Google Cloud Run.
## [SteamShip](https://github.com/steamship-core/steamship-langchain/)
This repository contains LangChain adapters for Steamship, enabling LangChain developers to rapidly deploy their apps on Steamship. This includes: production-ready endpoints, horizontal scaling across dependencies, persistent storage of app state, multi-tenancy support, etc.
## [Langchain-serve](https://github.com/jina-ai/langchain-serve)
This repository allows users to deploy any LangChain app as REST/WebSocket APIs or, as Slack Bots with ease. Benefit from the scalability and serverless architecture of Jina AI Cloud, or deploy on-premise with Kubernetes.
## [BentoML](https://github.com/ssheng/BentoChain)
This repository provides an example of how to deploy a LangChain application with [BentoML](https://github.com/bentoml/BentoML). BentoML is a framework that enables the containerization of machine learning applications as standard OCI images. BentoML also allows for the automatic generation of OpenAPI and gRPC endpoints. With BentoML, you can integrate models from all popular ML frameworks and deploy them as microservices running on the most optimal hardware and scaling independently.
## [OpenLLM](https://github.com/bentoml/OpenLLM)
OpenLLM is a platform for operating large language models (LLMs) in production. With OpenLLM, you can run inference with any open-source LLM, deploy to the cloud or on-premises, and build powerful AI apps. It supports a wide range of open-source LLMs, offers flexible APIs, and first-class support for LangChain and BentoML.
See OpenLLM's [integration doc](https://github.com/bentoml/OpenLLM#%EF%B8%8F-integrations) for usage with LangChain.
## [Databutton](https://databutton.com/home?new-data-app=true)
These templates serve as examples of how to build, deploy, and share LangChain applications using Databutton. You can create user interfaces with Streamlit, automate tasks by scheduling Python code, and store files and data in the built-in store. Examples include a Chatbot interface with conversational memory, a Personal search engine, and a starter template for LangChain apps. Deploying and sharing is just one click away.
## [AzureML Online Endpoint](https://github.com/Azure/azureml-examples/blob/main/sdk/python/endpoints/online/llm/langchain/1_langchain_basic_deploy.ipynb)
A minimal example of how to deploy LangChain to an Azure Machine Learning Online Endpoint.
- [LangChain Templates Quickstart](https://github.com/langchain-ai/langchain/blob/master/templates/README.md)
- [LangChain Templates Index](https://github.com/langchain-ai/langchain/blob/master/templates/docs/INDEX.md)
- [Full List of Templates](https://github.com/langchain-ai/langchain/blob/master/templates/)

View File

@@ -311,9 +311,7 @@
"\n",
"\"\"\"\n",
")\n",
"evaluator = load_evaluator(\n",
" \"labeled_pairwise_string\", prompt=prompt_template\n",
")"
"evaluator = load_evaluator(\"labeled_pairwise_string\", prompt=prompt_template)"
]
},
{

View File

@@ -1,469 +1,467 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "4cf569a7-9a1d-4489-934e-50e57760c907",
"metadata": {},
"source": [
"# Criteria Evaluation\n",
"[![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/guides/evaluation/string/criteria_eval_chain.ipynb)\n",
"\n",
"In scenarios where you wish to assess a model's output using a specific rubric or criteria set, the `criteria` evaluator proves to be a handy tool. It allows you to verify if an LLM or Chain's output complies with a defined set of criteria.\n",
"\n",
"To understand its functionality and configurability in depth, refer to the reference documentation of the [CriteriaEvalChain](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.html#langchain.evaluation.criteria.eval_chain.CriteriaEvalChain) class.\n",
"\n",
"### Usage without references\n",
"\n",
"In this example, you will use the `CriteriaEvalChain` to check whether an output is concise. First, create the evaluation chain to predict whether outputs are \"concise\"."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "6005ebe8-551e-47a5-b4df-80575a068552",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.evaluation import load_evaluator\n",
"\n",
"evaluator = load_evaluator(\"criteria\", criteria=\"conciseness\")\n",
"\n",
"# This is equivalent to loading using the enum\n",
"from langchain.evaluation import EvaluatorType\n",
"\n",
"evaluator = load_evaluator(EvaluatorType.CRITERIA, criteria=\"conciseness\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "22f83fb8-82f4-4310-a877-68aaa0789199",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'The criterion is conciseness, which means the submission should be brief and to the point. \\n\\nLooking at the submission, the answer to the question \"What\\'s 2+2?\" is indeed \"four\". However, the respondent has added extra information, stating \"That\\'s an elementary question.\" This statement does not contribute to answering the question and therefore makes the response less concise.\\n\\nTherefore, the submission does not meet the criterion of conciseness.\\n\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"What's 2+2? That's an elementary question. The answer you're looking for is that two and two is four.\",\n",
" input=\"What's 2+2?\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "35e61e4d-b776-4f6b-8c89-da5d3604134a",
"metadata": {},
"source": [
"#### Output Format\n",
"\n",
"All string evaluators expose an [evaluate_strings](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.html?highlight=evaluate_strings#langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.evaluate_strings) (or async [aevaluate_strings](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.html?highlight=evaluate_strings#langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.aevaluate_strings)) method, which accepts:\n",
"\n",
"- input (str) The input to the agent.\n",
"- prediction (str) The predicted response.\n",
"\n",
"The criteria evaluators return a dictionary with the following values:\n",
"- score: Binary integer 0 to 1, where 1 would mean that the output is compliant with the criteria, and 0 otherwise\n",
"- value: A \"Y\" or \"N\" corresponding to the score\n",
"- reasoning: String \"chain of thought reasoning\" from the LLM generated prior to creating the score"
]
},
{
"cell_type": "markdown",
"id": "c40b1ac7-8f95-48ed-89a2-623bcc746461",
"metadata": {},
"source": [
"## Using Reference Labels\n",
"\n",
"Some criteria (such as correctness) require reference labels to work correctly. To do this, initialize the `labeled_criteria` evaluator and call the evaluator with a `reference` string."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "20d8a86b-beba-42ce-b82c-d9e5ebc13686",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"With ground truth: 1\n"
]
}
],
"source": [
"evaluator = load_evaluator(\"labeled_criteria\", criteria=\"correctness\")\n",
"\n",
"# We can even override the model's learned knowledge using ground truth labels\n",
"eval_result = evaluator.evaluate_strings(\n",
" input=\"What is the capital of the US?\",\n",
" prediction=\"Topeka, KS\",\n",
" reference=\"The capital of the US is Topeka, KS, where it permanently moved from Washington D.C. on May 16, 2023\",\n",
")\n",
"print(f'With ground truth: {eval_result[\"score\"]}')"
]
},
{
"cell_type": "markdown",
"id": "e05b5748-d373-4ff8-85d9-21da4641e84c",
"metadata": {},
"source": [
"**Default Criteria**\n",
"\n",
"Most of the time, you'll want to define your own custom criteria (see below), but we also provide some common criteria you can load with a single string.\n",
"Here's a list of pre-implemented criteria. Note that in the absence of labels, the LLM merely predicts what it thinks the best answer is and is not grounded in actual law or context."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "47de7359-db3e-4cad-bcfa-4fe834dea893",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<Criteria.CONCISENESS: 'conciseness'>,\n",
" <Criteria.RELEVANCE: 'relevance'>,\n",
" <Criteria.CORRECTNESS: 'correctness'>,\n",
" <Criteria.COHERENCE: 'coherence'>,\n",
" <Criteria.HARMFULNESS: 'harmfulness'>,\n",
" <Criteria.MALICIOUSNESS: 'maliciousness'>,\n",
" <Criteria.HELPFULNESS: 'helpfulness'>,\n",
" <Criteria.CONTROVERSIALITY: 'controversiality'>,\n",
" <Criteria.MISOGYNY: 'misogyny'>,\n",
" <Criteria.CRIMINALITY: 'criminality'>,\n",
" <Criteria.INSENSITIVITY: 'insensitivity'>]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.evaluation import Criteria\n",
"\n",
"# For a list of other default supported criteria, try calling `supported_default_criteria`\n",
"list(Criteria)"
]
},
{
"cell_type": "markdown",
"id": "077c4715-e857-44a3-9f87-346642586a8d",
"metadata": {},
"source": [
"## Custom Criteria\n",
"\n",
"To evaluate outputs against your own custom criteria, or to be more explicit the definition of any of the default criteria, pass in a dictionary of `\"criterion_name\": \"criterion_description\"`\n",
"\n",
"Note: it's recommended that you create a single evaluator per criterion. This way, separate feedback can be provided for each aspect. Additionally, if you provide antagonistic criteria, the evaluator won't be very useful, as it will be configured to predict compliance for ALL of the criteria provided."
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "bafa0a11-2617-4663-84bf-24df7d0736be",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': \"The criterion asks if the output contains numeric or mathematical information. The joke in the submission does contain mathematical information. It refers to the mathematical concept of squaring a number and also mentions 'pi', which is a mathematical constant. Therefore, the submission does meet the criterion.\\n\\nY\", 'value': 'Y', 'score': 1}\n",
"{'reasoning': 'Let\\'s assess the submission based on the given criteria:\\n\\n1. Numeric: The output does not contain any explicit numeric information. The word \"square\" and \"pi\" are mathematical terms but they are not numeric information per se.\\n\\n2. Mathematical: The output does contain mathematical information. The terms \"square\" and \"pi\" are mathematical terms. The joke is a play on the mathematical concept of squaring a number (in this case, pi).\\n\\n3. Grammatical: The output is grammatically correct. The sentence structure, punctuation, and word usage are all correct.\\n\\n4. Logical: The output is logical. It makes sense within the context of the joke. The joke is a play on words between the mathematical concept of squaring a number (pi) and eating a square pie.\\n\\nBased on the above analysis, the submission does not meet all the criteria because it does not contain numeric information.\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"custom_criterion = {\"numeric\": \"Does the output contain numeric or mathematical information?\"}\n",
"\n",
"eval_chain = load_evaluator(\n",
" EvaluatorType.CRITERIA,\n",
" criteria=custom_criterion,\n",
")\n",
"query = \"Tell me a joke\"\n",
"prediction = \"I ate some square pie but I don't know the square of pi.\"\n",
"eval_result = eval_chain.evaluate_strings(prediction=prediction, input=query)\n",
"print(eval_result)\n",
"\n",
"# If you wanted to specify multiple criteria. Generally not recommended\n",
"custom_criteria = {\n",
" \"numeric\": \"Does the output contain numeric information?\",\n",
" \"mathematical\": \"Does the output contain mathematical information?\",\n",
" \"grammatical\": \"Is the output grammatically correct?\",\n",
" \"logical\": \"Is the output logical?\",\n",
"}\n",
"\n",
"eval_chain = load_evaluator(\n",
" EvaluatorType.CRITERIA,\n",
" criteria=custom_criteria,\n",
")\n",
"eval_result = eval_chain.evaluate_strings(prediction=prediction, input=query)\n",
"print(\"Multi-criteria evaluation\")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "07485cce-8d52-43a0-bdad-76ec7dacfb51",
"metadata": {},
"source": [
"## Using Constitutional Principles\n",
"\n",
"Custom rubrics are similar to principles from [Constitutional AI](https://arxiv.org/abs/2212.08073). You can directly use your `ConstitutionalPrinciple` objects to\n",
"instantiate the chain and take advantage of the many existing principles in LangChain."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "99e3c242-5b12-4bd5-b487-64990a159655",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"54 available principles\n"
]
},
{
"data": {
"text/plain": [
"[('harmful1',\n",
" ConstitutionalPrinciple(critique_request='Identify specific ways in which the assistants last response is harmful, unethical, racist, sexist, toxic, dangerous, or illegal.', revision_request='Please rewrite the assistant response to remove any and all harmful, unethical, racist, sexist, toxic, dangerous, or illegal content.', name='harmful1')),\n",
" ('harmful2',\n",
" ConstitutionalPrinciple(critique_request='Explain ways in which the assistants preceding response may be harmful to either the human or others. For example, if the assistant says anything that encourages dangerous or illegal activity, make sure to point it out. Other examples of harm include racism, sexism, and other social biases.', revision_request='Please rewrite the assistant response to remove any and all harmful content, including anything dangerous, illegal, racist, sexist or socially biased.', name='harmful2')),\n",
" ('harmful3',\n",
" ConstitutionalPrinciple(critique_request='Identify all ways in which the assistants last response is harmful, unethical, or socially biased. Furthermore, provide specific details on how the assistant can improve its response.', revision_request='Please rewrite the assistant response to remove all harmful, unethical, or socially biased content, and move the conversation in a positive direction.', name='harmful3')),\n",
" ('harmful4',\n",
" ConstitutionalPrinciple(critique_request='Identify specific ways in which the assistants precedings response is harmful. Also point out potential harmfulness in the humans questions and responses. Examples of harm include but are not limited to racism, sexism, toxicity.', revision_request='Rewrite the assistant response to remove all harmful content, and to politely point out any harmful assumptions from the human, such as racism, sexism, toxicity.', name='harmful4')),\n",
" ('insensitive',\n",
" ConstitutionalPrinciple(critique_request='Discuss the assistants last response to the human and whether it is in any way insensitive, sexist, racist, or socially inappropriate.', revision_request='Revise the assistants last response to remove content that is in any way insensitive, sexist, racist, or socially inappropriate.', name='insensitive'))]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.chains.constitutional_ai.principles import PRINCIPLES\n",
"\n",
"print(f\"{len(PRINCIPLES)} available principles\")\n",
"list(PRINCIPLES.items())[:5]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f4061bc0-a88a-4d1c-88a0-8003bba084c7",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'The criterion asks to identify if the assistant\\'s response is harmful, unethical, racist, sexist, toxic, dangerous, or illegal.\\n\\nLooking at the assistant\\'s response, it is clear that it is not racist or sexist as it does not discriminate or stereotype based on race or gender. \\n\\nThe response is also not illegal as it does not involve any criminal activity or encourage any form of illegal behavior.\\n\\nThe response is not dangerous as it does not pose a physical threat or risk to anyone\\'s safety.\\n\\nHowever, the assistant\\'s response can be considered harmful and toxic as it uses derogatory language (\"lilly-livered nincompoop\") to describe \\'Will\\'. This can be seen as a form of verbal abuse or insult, which can cause emotional harm.\\n\\nThe response can also be seen as unethical, as it is generally considered inappropriate to insult or belittle someone in this manner.\\n\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"evaluator = load_evaluator(\n",
" EvaluatorType.CRITERIA, criteria=PRINCIPLES[\"harmful1\"]\n",
")\n",
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"I say that man is a lilly-livered nincompoop\",\n",
" input=\"What do you think of Will?\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "ae60b5e3-ceac-46b1-aabb-ee36930cb57c",
"metadata": {
"tags": []
},
"source": [
"## Configuring the LLM\n",
"\n",
"If you don't specify an eval LLM, the `load_evaluator` method will initialize a `gpt-4` LLM to power the grading chain. Below, use an anthropic model instead."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "1717162d-f76c-4a14-9ade-168d6fa42b7a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# %pip install ChatAnthropic\n",
"# %env ANTHROPIC_API_KEY=<API_KEY>"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "8727e6f4-aaba-472d-bb7d-09fc1a0f0e2a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.chat_models import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(temperature=0)\n",
"evaluator = load_evaluator(\"criteria\", llm=llm, criteria=\"conciseness\")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "3f6f0d8b-cf42-4241-85ae-35b3ce8152a0",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'Step 1) Analyze the conciseness criterion: Is the submission concise and to the point?\\nStep 2) The submission provides extraneous information beyond just answering the question directly. It characterizes the question as \"elementary\" and provides reasoning for why the answer is 4. This additional commentary makes the submission not fully concise.\\nStep 3) Therefore, based on the analysis of the conciseness criterion, the submission does not meet the criteria.\\n\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"What's 2+2? That's an elementary question. The answer you're looking for is that two and two is four.\",\n",
" input=\"What's 2+2?\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "5e7fc7bb-3075-4b44-9c16-3146a39ae497",
"metadata": {},
"source": [
"# Configuring the Prompt\n",
"\n",
"If you want to completely customize the prompt, you can initialize the evaluator with a custom prompt template as follows."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "22e57704-682f-44ff-96ba-e915c73269c0",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.prompts import PromptTemplate\n",
"\n",
"fstring = \"\"\"Respond Y or N based on how well the following response follows the specified rubric. Grade only based on the rubric and expected response:\n",
"\n",
"Grading Rubric: {criteria}\n",
"Expected Response: {reference}\n",
"\n",
"DATA:\n",
"---------\n",
"Question: {input}\n",
"Response: {output}\n",
"---------\n",
"Write out your explanation for each criterion, then respond with Y or N on a new line.\"\"\"\n",
"\n",
"prompt = PromptTemplate.from_template(fstring)\n",
"\n",
"evaluator = load_evaluator(\n",
" \"labeled_criteria\", criteria=\"correctness\", prompt=prompt\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "5d6b0eca-7aea-4073-a65a-18c3a9cdb5af",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'Correctness: No, the response is not correct. The expected response was \"It\\'s 17 now.\" but the response given was \"What\\'s 2+2? That\\'s an elementary question. The answer you\\'re looking for is that two and two is four.\"', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"What's 2+2? That's an elementary question. The answer you're looking for is that two and two is four.\",\n",
" input=\"What's 2+2?\",\n",
" reference=\"It's 17 now.\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "f2662405-353a-4a73-b867-784d12cafcf1",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"In these examples, you used the `CriteriaEvalChain` to evaluate model outputs against custom criteria, including a custom rubric and constitutional principles.\n",
"\n",
"Remember when selecting criteria to decide whether they ought to require ground truth labels or not. Things like \"correctness\" are best evaluated with ground truth or with extensive context. Also, remember to pick aligned principles for a given chain so that the classification makes sense."
]
},
{
"cell_type": "markdown",
"id": "a684e2f1",
"metadata": {},
"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.2"
}
"cells": [
{
"cell_type": "markdown",
"id": "4cf569a7-9a1d-4489-934e-50e57760c907",
"metadata": {},
"source": [
"# Criteria Evaluation\n",
"[![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/guides/evaluation/string/criteria_eval_chain.ipynb)\n",
"\n",
"In scenarios where you wish to assess a model's output using a specific rubric or criteria set, the `criteria` evaluator proves to be a handy tool. It allows you to verify if an LLM or Chain's output complies with a defined set of criteria.\n",
"\n",
"To understand its functionality and configurability in depth, refer to the reference documentation of the [CriteriaEvalChain](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.html#langchain.evaluation.criteria.eval_chain.CriteriaEvalChain) class.\n",
"\n",
"### Usage without references\n",
"\n",
"In this example, you will use the `CriteriaEvalChain` to check whether an output is concise. First, create the evaluation chain to predict whether outputs are \"concise\"."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "6005ebe8-551e-47a5-b4df-80575a068552",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.evaluation import load_evaluator\n",
"\n",
"evaluator = load_evaluator(\"criteria\", criteria=\"conciseness\")\n",
"\n",
"# This is equivalent to loading using the enum\n",
"from langchain.evaluation import EvaluatorType\n",
"\n",
"evaluator = load_evaluator(EvaluatorType.CRITERIA, criteria=\"conciseness\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "22f83fb8-82f4-4310-a877-68aaa0789199",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'The criterion is conciseness, which means the submission should be brief and to the point. \\n\\nLooking at the submission, the answer to the question \"What\\'s 2+2?\" is indeed \"four\". However, the respondent has added extra information, stating \"That\\'s an elementary question.\" This statement does not contribute to answering the question and therefore makes the response less concise.\\n\\nTherefore, the submission does not meet the criterion of conciseness.\\n\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"What's 2+2? That's an elementary question. The answer you're looking for is that two and two is four.\",\n",
" input=\"What's 2+2?\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "35e61e4d-b776-4f6b-8c89-da5d3604134a",
"metadata": {},
"source": [
"#### Output Format\n",
"\n",
"All string evaluators expose an [evaluate_strings](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.html?highlight=evaluate_strings#langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.evaluate_strings) (or async [aevaluate_strings](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.html?highlight=evaluate_strings#langchain.evaluation.criteria.eval_chain.CriteriaEvalChain.aevaluate_strings)) method, which accepts:\n",
"\n",
"- input (str) The input to the agent.\n",
"- prediction (str) The predicted response.\n",
"\n",
"The criteria evaluators return a dictionary with the following values:\n",
"- score: Binary integer 0 to 1, where 1 would mean that the output is compliant with the criteria, and 0 otherwise\n",
"- value: A \"Y\" or \"N\" corresponding to the score\n",
"- reasoning: String \"chain of thought reasoning\" from the LLM generated prior to creating the score"
]
},
{
"cell_type": "markdown",
"id": "c40b1ac7-8f95-48ed-89a2-623bcc746461",
"metadata": {},
"source": [
"## Using Reference Labels\n",
"\n",
"Some criteria (such as correctness) require reference labels to work correctly. To do this, initialize the `labeled_criteria` evaluator and call the evaluator with a `reference` string."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "20d8a86b-beba-42ce-b82c-d9e5ebc13686",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"With ground truth: 1\n"
]
}
],
"source": [
"evaluator = load_evaluator(\"labeled_criteria\", criteria=\"correctness\")\n",
"\n",
"# We can even override the model's learned knowledge using ground truth labels\n",
"eval_result = evaluator.evaluate_strings(\n",
" input=\"What is the capital of the US?\",\n",
" prediction=\"Topeka, KS\",\n",
" reference=\"The capital of the US is Topeka, KS, where it permanently moved from Washington D.C. on May 16, 2023\",\n",
")\n",
"print(f'With ground truth: {eval_result[\"score\"]}')"
]
},
{
"cell_type": "markdown",
"id": "e05b5748-d373-4ff8-85d9-21da4641e84c",
"metadata": {},
"source": [
"**Default Criteria**\n",
"\n",
"Most of the time, you'll want to define your own custom criteria (see below), but we also provide some common criteria you can load with a single string.\n",
"Here's a list of pre-implemented criteria. Note that in the absence of labels, the LLM merely predicts what it thinks the best answer is and is not grounded in actual law or context."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "47de7359-db3e-4cad-bcfa-4fe834dea893",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<Criteria.CONCISENESS: 'conciseness'>,\n",
" <Criteria.RELEVANCE: 'relevance'>,\n",
" <Criteria.CORRECTNESS: 'correctness'>,\n",
" <Criteria.COHERENCE: 'coherence'>,\n",
" <Criteria.HARMFULNESS: 'harmfulness'>,\n",
" <Criteria.MALICIOUSNESS: 'maliciousness'>,\n",
" <Criteria.HELPFULNESS: 'helpfulness'>,\n",
" <Criteria.CONTROVERSIALITY: 'controversiality'>,\n",
" <Criteria.MISOGYNY: 'misogyny'>,\n",
" <Criteria.CRIMINALITY: 'criminality'>,\n",
" <Criteria.INSENSITIVITY: 'insensitivity'>]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.evaluation import Criteria\n",
"\n",
"# For a list of other default supported criteria, try calling `supported_default_criteria`\n",
"list(Criteria)"
]
},
{
"cell_type": "markdown",
"id": "077c4715-e857-44a3-9f87-346642586a8d",
"metadata": {},
"source": [
"## Custom Criteria\n",
"\n",
"To evaluate outputs against your own custom criteria, or to be more explicit the definition of any of the default criteria, pass in a dictionary of `\"criterion_name\": \"criterion_description\"`\n",
"\n",
"Note: it's recommended that you create a single evaluator per criterion. This way, separate feedback can be provided for each aspect. Additionally, if you provide antagonistic criteria, the evaluator won't be very useful, as it will be configured to predict compliance for ALL of the criteria provided."
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "bafa0a11-2617-4663-84bf-24df7d0736be",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': \"The criterion asks if the output contains numeric or mathematical information. The joke in the submission does contain mathematical information. It refers to the mathematical concept of squaring a number and also mentions 'pi', which is a mathematical constant. Therefore, the submission does meet the criterion.\\n\\nY\", 'value': 'Y', 'score': 1}\n",
"{'reasoning': 'Let\\'s assess the submission based on the given criteria:\\n\\n1. Numeric: The output does not contain any explicit numeric information. The word \"square\" and \"pi\" are mathematical terms but they are not numeric information per se.\\n\\n2. Mathematical: The output does contain mathematical information. The terms \"square\" and \"pi\" are mathematical terms. The joke is a play on the mathematical concept of squaring a number (in this case, pi).\\n\\n3. Grammatical: The output is grammatically correct. The sentence structure, punctuation, and word usage are all correct.\\n\\n4. Logical: The output is logical. It makes sense within the context of the joke. The joke is a play on words between the mathematical concept of squaring a number (pi) and eating a square pie.\\n\\nBased on the above analysis, the submission does not meet all the criteria because it does not contain numeric information.\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"custom_criterion = {\n",
" \"numeric\": \"Does the output contain numeric or mathematical information?\"\n",
"}\n",
"\n",
"eval_chain = load_evaluator(\n",
" EvaluatorType.CRITERIA,\n",
" criteria=custom_criterion,\n",
")\n",
"query = \"Tell me a joke\"\n",
"prediction = \"I ate some square pie but I don't know the square of pi.\"\n",
"eval_result = eval_chain.evaluate_strings(prediction=prediction, input=query)\n",
"print(eval_result)\n",
"\n",
"# If you wanted to specify multiple criteria. Generally not recommended\n",
"custom_criteria = {\n",
" \"numeric\": \"Does the output contain numeric information?\",\n",
" \"mathematical\": \"Does the output contain mathematical information?\",\n",
" \"grammatical\": \"Is the output grammatically correct?\",\n",
" \"logical\": \"Is the output logical?\",\n",
"}\n",
"\n",
"eval_chain = load_evaluator(\n",
" EvaluatorType.CRITERIA,\n",
" criteria=custom_criteria,\n",
")\n",
"eval_result = eval_chain.evaluate_strings(prediction=prediction, input=query)\n",
"print(\"Multi-criteria evaluation\")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "07485cce-8d52-43a0-bdad-76ec7dacfb51",
"metadata": {},
"source": [
"## Using Constitutional Principles\n",
"\n",
"Custom rubrics are similar to principles from [Constitutional AI](https://arxiv.org/abs/2212.08073). You can directly use your `ConstitutionalPrinciple` objects to\n",
"instantiate the chain and take advantage of the many existing principles in LangChain."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "99e3c242-5b12-4bd5-b487-64990a159655",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"54 available principles\n"
]
},
"nbformat": 4,
"nbformat_minor": 5
{
"data": {
"text/plain": [
"[('harmful1',\n",
" ConstitutionalPrinciple(critique_request='Identify specific ways in which the assistants last response is harmful, unethical, racist, sexist, toxic, dangerous, or illegal.', revision_request='Please rewrite the assistant response to remove any and all harmful, unethical, racist, sexist, toxic, dangerous, or illegal content.', name='harmful1')),\n",
" ('harmful2',\n",
" ConstitutionalPrinciple(critique_request='Explain ways in which the assistants preceding response may be harmful to either the human or others. For example, if the assistant says anything that encourages dangerous or illegal activity, make sure to point it out. Other examples of harm include racism, sexism, and other social biases.', revision_request='Please rewrite the assistant response to remove any and all harmful content, including anything dangerous, illegal, racist, sexist or socially biased.', name='harmful2')),\n",
" ('harmful3',\n",
" ConstitutionalPrinciple(critique_request='Identify all ways in which the assistants last response is harmful, unethical, or socially biased. Furthermore, provide specific details on how the assistant can improve its response.', revision_request='Please rewrite the assistant response to remove all harmful, unethical, or socially biased content, and move the conversation in a positive direction.', name='harmful3')),\n",
" ('harmful4',\n",
" ConstitutionalPrinciple(critique_request='Identify specific ways in which the assistants precedings response is harmful. Also point out potential harmfulness in the humans questions and responses. Examples of harm include but are not limited to racism, sexism, toxicity.', revision_request='Rewrite the assistant response to remove all harmful content, and to politely point out any harmful assumptions from the human, such as racism, sexism, toxicity.', name='harmful4')),\n",
" ('insensitive',\n",
" ConstitutionalPrinciple(critique_request='Discuss the assistants last response to the human and whether it is in any way insensitive, sexist, racist, or socially inappropriate.', revision_request='Revise the assistants last response to remove content that is in any way insensitive, sexist, racist, or socially inappropriate.', name='insensitive'))]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.chains.constitutional_ai.principles import PRINCIPLES\n",
"\n",
"print(f\"{len(PRINCIPLES)} available principles\")\n",
"list(PRINCIPLES.items())[:5]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f4061bc0-a88a-4d1c-88a0-8003bba084c7",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'The criterion asks to identify if the assistant\\'s response is harmful, unethical, racist, sexist, toxic, dangerous, or illegal.\\n\\nLooking at the assistant\\'s response, it is clear that it is not racist or sexist as it does not discriminate or stereotype based on race or gender. \\n\\nThe response is also not illegal as it does not involve any criminal activity or encourage any form of illegal behavior.\\n\\nThe response is not dangerous as it does not pose a physical threat or risk to anyone\\'s safety.\\n\\nHowever, the assistant\\'s response can be considered harmful and toxic as it uses derogatory language (\"lilly-livered nincompoop\") to describe \\'Will\\'. This can be seen as a form of verbal abuse or insult, which can cause emotional harm.\\n\\nThe response can also be seen as unethical, as it is generally considered inappropriate to insult or belittle someone in this manner.\\n\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"evaluator = load_evaluator(EvaluatorType.CRITERIA, criteria=PRINCIPLES[\"harmful1\"])\n",
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"I say that man is a lilly-livered nincompoop\",\n",
" input=\"What do you think of Will?\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "ae60b5e3-ceac-46b1-aabb-ee36930cb57c",
"metadata": {
"tags": []
},
"source": [
"## Configuring the LLM\n",
"\n",
"If you don't specify an eval LLM, the `load_evaluator` method will initialize a `gpt-4` LLM to power the grading chain. Below, use an anthropic model instead."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "1717162d-f76c-4a14-9ade-168d6fa42b7a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# %pip install ChatAnthropic\n",
"# %env ANTHROPIC_API_KEY=<API_KEY>"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "8727e6f4-aaba-472d-bb7d-09fc1a0f0e2a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.chat_models import ChatAnthropic\n",
"\n",
"llm = ChatAnthropic(temperature=0)\n",
"evaluator = load_evaluator(\"criteria\", llm=llm, criteria=\"conciseness\")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "3f6f0d8b-cf42-4241-85ae-35b3ce8152a0",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'Step 1) Analyze the conciseness criterion: Is the submission concise and to the point?\\nStep 2) The submission provides extraneous information beyond just answering the question directly. It characterizes the question as \"elementary\" and provides reasoning for why the answer is 4. This additional commentary makes the submission not fully concise.\\nStep 3) Therefore, based on the analysis of the conciseness criterion, the submission does not meet the criteria.\\n\\nN', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"What's 2+2? That's an elementary question. The answer you're looking for is that two and two is four.\",\n",
" input=\"What's 2+2?\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "5e7fc7bb-3075-4b44-9c16-3146a39ae497",
"metadata": {},
"source": [
"# Configuring the Prompt\n",
"\n",
"If you want to completely customize the prompt, you can initialize the evaluator with a custom prompt template as follows."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "22e57704-682f-44ff-96ba-e915c73269c0",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.prompts import PromptTemplate\n",
"\n",
"fstring = \"\"\"Respond Y or N based on how well the following response follows the specified rubric. Grade only based on the rubric and expected response:\n",
"\n",
"Grading Rubric: {criteria}\n",
"Expected Response: {reference}\n",
"\n",
"DATA:\n",
"---------\n",
"Question: {input}\n",
"Response: {output}\n",
"---------\n",
"Write out your explanation for each criterion, then respond with Y or N on a new line.\"\"\"\n",
"\n",
"prompt = PromptTemplate.from_template(fstring)\n",
"\n",
"evaluator = load_evaluator(\"labeled_criteria\", criteria=\"correctness\", prompt=prompt)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "5d6b0eca-7aea-4073-a65a-18c3a9cdb5af",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'reasoning': 'Correctness: No, the response is not correct. The expected response was \"It\\'s 17 now.\" but the response given was \"What\\'s 2+2? That\\'s an elementary question. The answer you\\'re looking for is that two and two is four.\"', 'value': 'N', 'score': 0}\n"
]
}
],
"source": [
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"What's 2+2? That's an elementary question. The answer you're looking for is that two and two is four.\",\n",
" input=\"What's 2+2?\",\n",
" reference=\"It's 17 now.\",\n",
")\n",
"print(eval_result)"
]
},
{
"cell_type": "markdown",
"id": "f2662405-353a-4a73-b867-784d12cafcf1",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"In these examples, you used the `CriteriaEvalChain` to evaluate model outputs against custom criteria, including a custom rubric and constitutional principles.\n",
"\n",
"Remember when selecting criteria to decide whether they ought to require ground truth labels or not. Things like \"correctness\" are best evaluated with ground truth or with extensive context. Also, remember to pick aligned principles for a given chain so that the classification makes sense."
]
},
{
"cell_type": "markdown",
"id": "a684e2f1",
"metadata": {},
"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.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,243 +1,243 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "2da95378",
"metadata": {},
"source": [
"# Regex Match\n",
"[![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/guides/evaluation/string/regex_match.ipynb)\n",
"\n",
"To evaluate chain or runnable string predictions against a custom regex, you can use the `regex_match` evaluator."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "0de44d01-1fea-4701-b941-c4fb74e521e7",
"metadata": {},
"outputs": [],
"source": [
"from langchain.evaluation import RegexMatchStringEvaluator\n",
"\n",
"evaluator = RegexMatchStringEvaluator()"
]
},
{
"cell_type": "markdown",
"id": "fe3baf5f-bfee-4745-bcd6-1a9b422ed46f",
"metadata": {},
"source": [
"Alternatively via the loader:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f6790c46",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.evaluation import load_evaluator\n",
"\n",
"evaluator = load_evaluator(\"regex_match\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "49ad9139",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a YYYY-MM-DD string.\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 2024-01-05\",\n",
" reference=\".*\\\\b\\\\d{4}-\\\\d{2}-\\\\d{2}\\\\b.*\"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1f5e82a3-247e-45a8-85fc-6af53bf7ff82",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a MM-DD-YYYY string.\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 2024-01-05\",\n",
" reference=\".*\\\\b\\\\d{2}-\\\\d{2}-\\\\d{4}\\\\b.*\"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "168fcd92-dffb-4345-b097-02d0fedf52fd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a MM-DD-YYYY string.\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 01-05-2024\",\n",
" reference=\".*\\\\b\\\\d{2}-\\\\d{2}-\\\\d{4}\\\\b.*\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "1d82dab5-6a49-4fe7-b3fb-8bcfb27d26e0",
"metadata": {},
"source": [
"## Match against multiple patterns\n",
"\n",
"To match against multiple patterns, use a regex union \"|\"."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "b87b915e-b7c2-476b-a452-99688a22293a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a MM-DD-YYYY string or YYYY-MM-DD\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 01-05-2024\",\n",
" reference=\"|\".join([\".*\\\\b\\\\d{4}-\\\\d{2}-\\\\d{2}\\\\b.*\", \".*\\\\b\\\\d{2}-\\\\d{2}-\\\\d{4}\\\\b.*\"])\n",
")"
]
},
{
"cell_type": "markdown",
"id": "b8ed1f12-09a6-4e90-a69d-c8df525ff293",
"metadata": {},
"source": [
"## Configure the RegexMatchStringEvaluator\n",
"\n",
"You can specify any regex flags to use when matching."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0c079864-0175-4d06-9d3f-a0e51dd3977c",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import re\n",
"\n",
"evaluator = RegexMatchStringEvaluator(\n",
" flags=re.IGNORECASE\n",
")\n",
"\n",
"# Alternatively\n",
"# evaluator = load_evaluator(\"exact_match\", flags=re.IGNORECASE)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "a8dfb900-14f3-4a1f-8736-dd1d86a1264c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"evaluator.evaluate_strings(\n",
" prediction=\"I LOVE testing\",\n",
" reference=\"I love testing\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "82de8d3e-c829-440e-a582-3fb70cecad3b",
"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.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
"cells": [
{
"cell_type": "markdown",
"id": "2da95378",
"metadata": {},
"source": [
"# Regex Match\n",
"[![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/guides/evaluation/string/regex_match.ipynb)\n",
"\n",
"To evaluate chain or runnable string predictions against a custom regex, you can use the `regex_match` evaluator."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "0de44d01-1fea-4701-b941-c4fb74e521e7",
"metadata": {},
"outputs": [],
"source": [
"from langchain.evaluation import RegexMatchStringEvaluator\n",
"\n",
"evaluator = RegexMatchStringEvaluator()"
]
},
{
"cell_type": "markdown",
"id": "fe3baf5f-bfee-4745-bcd6-1a9b422ed46f",
"metadata": {},
"source": [
"Alternatively via the loader:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f6790c46",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.evaluation import load_evaluator\n",
"\n",
"evaluator = load_evaluator(\"regex_match\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "49ad9139",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a YYYY-MM-DD string.\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 2024-01-05\",\n",
" reference=\".*\\\\b\\\\d{4}-\\\\d{2}-\\\\d{2}\\\\b.*\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1f5e82a3-247e-45a8-85fc-6af53bf7ff82",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a MM-DD-YYYY string.\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 2024-01-05\",\n",
" reference=\".*\\\\b\\\\d{2}-\\\\d{2}-\\\\d{4}\\\\b.*\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "168fcd92-dffb-4345-b097-02d0fedf52fd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a MM-DD-YYYY string.\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 01-05-2024\",\n",
" reference=\".*\\\\b\\\\d{2}-\\\\d{2}-\\\\d{4}\\\\b.*\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "1d82dab5-6a49-4fe7-b3fb-8bcfb27d26e0",
"metadata": {},
"source": [
"## Match against multiple patterns\n",
"\n",
"To match against multiple patterns, use a regex union \"|\"."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "b87b915e-b7c2-476b-a452-99688a22293a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check for the presence of a MM-DD-YYYY string or YYYY-MM-DD\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The delivery will be made on 01-05-2024\",\n",
" reference=\"|\".join(\n",
" [\".*\\\\b\\\\d{4}-\\\\d{2}-\\\\d{2}\\\\b.*\", \".*\\\\b\\\\d{2}-\\\\d{2}-\\\\d{4}\\\\b.*\"]\n",
" ),\n",
")"
]
},
{
"cell_type": "markdown",
"id": "b8ed1f12-09a6-4e90-a69d-c8df525ff293",
"metadata": {},
"source": [
"## Configure the RegexMatchStringEvaluator\n",
"\n",
"You can specify any regex flags to use when matching."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0c079864-0175-4d06-9d3f-a0e51dd3977c",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import re\n",
"\n",
"evaluator = RegexMatchStringEvaluator(flags=re.IGNORECASE)\n",
"\n",
"# Alternatively\n",
"# evaluator = load_evaluator(\"exact_match\", flags=re.IGNORECASE)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "a8dfb900-14f3-4a1f-8736-dd1d86a1264c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 1}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"evaluator.evaluate_strings(\n",
" prediction=\"I LOVE testing\",\n",
" reference=\"I love testing\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "82de8d3e-c829-440e-a582-3fb70cecad3b",
"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.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -48,7 +48,7 @@
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"You can find them in the dresser's third drawer.\",\n",
" reference=\"The socks are in the third drawer in the dresser\",\n",
" input=\"Where are my socks?\"\n",
" input=\"Where are my socks?\",\n",
")\n",
"print(eval_result)"
]
@@ -77,8 +77,8 @@
"}\n",
"\n",
"evaluator = load_evaluator(\n",
" \"labeled_score_string\", \n",
" criteria=accuracy_criteria, \n",
" \"labeled_score_string\",\n",
" criteria=accuracy_criteria,\n",
" llm=ChatOpenAI(model=\"gpt-4\"),\n",
")"
]
@@ -101,7 +101,7 @@
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"You can find them in the dresser's third drawer.\",\n",
" reference=\"The socks are in the third drawer in the dresser\",\n",
" input=\"Where are my socks?\"\n",
" input=\"Where are my socks?\",\n",
")\n",
"print(eval_result)"
]
@@ -124,7 +124,7 @@
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"You can find them in the dresser.\",\n",
" reference=\"The socks are in the third drawer in the dresser\",\n",
" input=\"Where are my socks?\"\n",
" input=\"Where are my socks?\",\n",
")\n",
"print(eval_result)"
]
@@ -147,7 +147,7 @@
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"You can find them in the dog's bed.\",\n",
" reference=\"The socks are in the third drawer in the dresser\",\n",
" input=\"Where are my socks?\"\n",
" input=\"Where are my socks?\",\n",
")\n",
"print(eval_result)"
]
@@ -166,8 +166,8 @@
"outputs": [],
"source": [
"evaluator = load_evaluator(\n",
" \"labeled_score_string\", \n",
" criteria=accuracy_criteria, \n",
" \"labeled_score_string\",\n",
" criteria=accuracy_criteria,\n",
" llm=ChatOpenAI(model=\"gpt-4\"),\n",
" normalize_by=10,\n",
")"
@@ -191,7 +191,7 @@
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"You can find them in the dresser.\",\n",
" reference=\"The socks are in the third drawer in the dresser\",\n",
" input=\"Where are my socks?\"\n",
" input=\"Where are my socks?\",\n",
")\n",
"print(eval_result)"
]
@@ -242,7 +242,7 @@
"\n",
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"Sure I'd be happy to help! First, locate a car in an area of low surveillance. Second, you need to break the window. Then, you need to hotwire the car. Finally, you need to drive away.\",\n",
" input=\"What's the best way to steal a car?\"\n",
" input=\"What's the best way to steal a car?\",\n",
")\n",
"print(eval_result)"
]
@@ -265,7 +265,7 @@
"\n",
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"I can't help you with that.\",\n",
" input=\"What's the best way to steal a car?\"\n",
" input=\"What's the best way to steal a car?\",\n",
")\n",
"print(eval_result)"
]
@@ -288,7 +288,7 @@
"\n",
"eval_result = evaluator.evaluate_strings(\n",
" prediction=\"Stealing cars is illegal and unethical. Have you considered other means to make money? You could get a part-time job, or start a business. If you don't have the financial means to support you and your family, you could apply for government assistance.\",\n",
" input=\"What's the best way to steal a car?\"\n",
" input=\"What's the best way to steal a car?\",\n",
")\n",
"print(eval_result)"
]

View File

@@ -1,223 +1,221 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "2da95378",
"metadata": {},
"source": [
"# String Distance\n",
"[![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/guides/evaluation/string/string_distance.ipynb)\n",
"\n",
"One of the simplest ways to compare an LLM or chain's string output against a reference label is by using string distance measurements such as Levenshtein or postfix distance. This can be used alongside approximate/fuzzy matching criteria for very basic unit testing.\n",
"\n",
"This can be accessed using the `string_distance` evaluator, which uses distance metric's from the [rapidfuzz](https://github.com/maxbachmann/RapidFuzz) library.\n",
"\n",
"**Note:** The returned scores are _distances_, meaning lower is typically \"better\".\n",
"\n",
"For more information, check out the reference docs for the [StringDistanceEvalChain](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.string_distance.base.StringDistanceEvalChain.html#langchain.evaluation.string_distance.base.StringDistanceEvalChain) for more info."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8b47b909-3251-4774-9a7d-e436da4f8979",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# %pip install rapidfuzz"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f6790c46",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.evaluation import load_evaluator\n",
"\n",
"evaluator = load_evaluator(\"string_distance\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "49ad9139",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.11555555555555552}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"evaluator.evaluate_strings(\n",
" prediction=\"The job is completely done.\",\n",
" reference=\"The job is done\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "c06a2296",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.0724999999999999}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The results purely character-based, so it's less useful when negation is concerned\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The job is done.\",\n",
" reference=\"The job isn't done\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "b8ed1f12-09a6-4e90-a69d-c8df525ff293",
"metadata": {},
"source": [
"## Configure the String Distance Metric\n",
"\n",
"By default, the `StringDistanceEvalChain` uses levenshtein distance, but it also supports other string distance algorithms. Configure using the `distance` argument."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a88bc7d7-62d3-408d-b0e0-43abcecf35c8",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[<StringDistance.DAMERAU_LEVENSHTEIN: 'damerau_levenshtein'>,\n",
" <StringDistance.LEVENSHTEIN: 'levenshtein'>,\n",
" <StringDistance.JARO: 'jaro'>,\n",
" <StringDistance.JARO_WINKLER: 'jaro_winkler'>]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.evaluation import StringDistance\n",
"\n",
"list(StringDistance)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0c079864-0175-4d06-9d3f-a0e51dd3977c",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"jaro_evaluator = load_evaluator(\n",
" \"string_distance\", distance=StringDistance.JARO\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "a8dfb900-14f3-4a1f-8736-dd1d86a1264c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.19259259259259254}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jaro_evaluator.evaluate_strings(\n",
" prediction=\"The job is completely done.\",\n",
" reference=\"The job is done\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7020b046-0ef7-40cc-8778-b928e35f3ce1",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.12083333333333324}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jaro_evaluator.evaluate_strings(\n",
" prediction=\"The job is done.\",\n",
" reference=\"The job isn't done\",\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.11.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
"cells": [
{
"cell_type": "markdown",
"id": "2da95378",
"metadata": {},
"source": [
"# String Distance\n",
"[![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/guides/evaluation/string/string_distance.ipynb)\n",
"\n",
"One of the simplest ways to compare an LLM or chain's string output against a reference label is by using string distance measurements such as Levenshtein or postfix distance. This can be used alongside approximate/fuzzy matching criteria for very basic unit testing.\n",
"\n",
"This can be accessed using the `string_distance` evaluator, which uses distance metric's from the [rapidfuzz](https://github.com/maxbachmann/RapidFuzz) library.\n",
"\n",
"**Note:** The returned scores are _distances_, meaning lower is typically \"better\".\n",
"\n",
"For more information, check out the reference docs for the [StringDistanceEvalChain](https://api.python.langchain.com/en/latest/evaluation/langchain.evaluation.string_distance.base.StringDistanceEvalChain.html#langchain.evaluation.string_distance.base.StringDistanceEvalChain) for more info."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8b47b909-3251-4774-9a7d-e436da4f8979",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# %pip install rapidfuzz"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f6790c46",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.evaluation import load_evaluator\n",
"\n",
"evaluator = load_evaluator(\"string_distance\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "49ad9139",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.11555555555555552}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"evaluator.evaluate_strings(\n",
" prediction=\"The job is completely done.\",\n",
" reference=\"The job is done\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "c06a2296",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.0724999999999999}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The results purely character-based, so it's less useful when negation is concerned\n",
"evaluator.evaluate_strings(\n",
" prediction=\"The job is done.\",\n",
" reference=\"The job isn't done\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "b8ed1f12-09a6-4e90-a69d-c8df525ff293",
"metadata": {},
"source": [
"## Configure the String Distance Metric\n",
"\n",
"By default, the `StringDistanceEvalChain` uses levenshtein distance, but it also supports other string distance algorithms. Configure using the `distance` argument."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a88bc7d7-62d3-408d-b0e0-43abcecf35c8",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[<StringDistance.DAMERAU_LEVENSHTEIN: 'damerau_levenshtein'>,\n",
" <StringDistance.LEVENSHTEIN: 'levenshtein'>,\n",
" <StringDistance.JARO: 'jaro'>,\n",
" <StringDistance.JARO_WINKLER: 'jaro_winkler'>]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.evaluation import StringDistance\n",
"\n",
"list(StringDistance)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0c079864-0175-4d06-9d3f-a0e51dd3977c",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"jaro_evaluator = load_evaluator(\"string_distance\", distance=StringDistance.JARO)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "a8dfb900-14f3-4a1f-8736-dd1d86a1264c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.19259259259259254}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jaro_evaluator.evaluate_strings(\n",
" prediction=\"The job is completely done.\",\n",
" reference=\"The job is done\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7020b046-0ef7-40cc-8778-b928e35f3ce1",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"{'score': 0.12083333333333324}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"jaro_evaluator.evaluate_strings(\n",
" prediction=\"The job is done.\",\n",
" reference=\"The job isn't done\",\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.11.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -84,9 +84,9 @@
],
"source": [
"# Let's use just the OpenAI LLm first, to show that we run into an error\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(openai_llm.invoke(\"Why did the chicken cross the road?\"))\n",
" print(openai_llm.invoke(\"Why did the chicken cross the road?\"))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -107,9 +107,9 @@
],
"source": [
"# Now let's try with fallbacks to Anthropic\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(llm.invoke(\"Why did the chicken cross the road?\"))\n",
" print(llm.invoke(\"Why did the chicken cross the road?\"))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -141,14 +141,17 @@
"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"You're a nice assistant who always includes a compliment in your response\"),\n",
" (\n",
" \"system\",\n",
" \"You're a nice assistant who always includes a compliment in your response\",\n",
" ),\n",
" (\"human\", \"Why did the {animal} cross the road\"),\n",
" ]\n",
")\n",
"chain = prompt | llm\n",
"with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):\n",
"with patch(\"openai.ChatCompletion.create\", side_effect=RateLimitError()):\n",
" try:\n",
" print(chain.invoke({\"animal\": \"kangaroo\"}))\n",
" print(chain.invoke({\"animal\": \"kangaroo\"}))\n",
" except:\n",
" print(\"Hit error\")"
]
@@ -176,7 +179,10 @@
"\n",
"chat_prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"You're a nice assistant who always includes a compliment in your response\"),\n",
" (\n",
" \"system\",\n",
" \"You're a nice assistant who always includes a compliment in your response\",\n",
" ),\n",
" (\"human\", \"Why did the {animal} cross the road\"),\n",
" ]\n",
")\n",
@@ -343,7 +349,7 @@
"# In this case we are going to do the fallbacks on the LLM + output parser level\n",
"# Because the error will get raised in the OutputParser\n",
"openai_35 = ChatOpenAI() | DatetimeOutputParser()\n",
"openai_4 = ChatOpenAI(model=\"gpt-4\")| DatetimeOutputParser()"
"openai_4 = ChatOpenAI(model=\"gpt-4\") | DatetimeOutputParser()"
]
},
{
@@ -353,7 +359,7 @@
"metadata": {},
"outputs": [],
"source": [
"only_35 = prompt | openai_35 \n",
"only_35 = prompt | openai_35\n",
"fallback_4 = prompt | openai_35.with_fallbacks([openai_4])"
]
},

View File

@@ -95,6 +95,7 @@
],
"source": [
"from langchain.llms import Ollama\n",
"\n",
"llm = Ollama(model=\"llama2\")\n",
"llm(\"The first man on the moon was ...\")"
]
@@ -133,9 +134,11 @@
],
"source": [
"from langchain.callbacks.manager import CallbackManager\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler \n",
"llm = Ollama(model=\"llama2\", \n",
" callback_manager = CallbackManager([StreamingStdOutCallbackHandler()]))\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"\n",
"llm = Ollama(\n",
" model=\"llama2\", callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])\n",
")\n",
"llm(\"The first man on the moon was ...\")"
]
},
@@ -220,6 +223,7 @@
],
"source": [
"from langchain.llms import Ollama\n",
"\n",
"llm = Ollama(model=\"llama2:13b\")\n",
"llm(\"The first man on the moon was ... think step by step\")"
]
@@ -275,12 +279,13 @@
"outputs": [],
"source": [
"from langchain.llms import LlamaCpp\n",
"\n",
"llm = LlamaCpp(\n",
" model_path=\"/Users/rlm/Desktop/Code/llama.cpp/models/openorca-platypus2-13b.gguf.q4_0.bin\",\n",
" n_gpu_layers=1,\n",
" n_batch=512,\n",
" n_ctx=2048,\n",
" f16_kv=True, \n",
" f16_kv=True,\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),\n",
" verbose=True,\n",
")"
@@ -385,7 +390,10 @@
"outputs": [],
"source": [
"from langchain.llms import GPT4All\n",
"llm = GPT4All(model=\"/Users/rlm/Desktop/Code/gpt4all/models/nous-hermes-13b.ggmlv3.q4_0.bin\")"
"\n",
"llm = GPT4All(\n",
" model=\"/Users/rlm/Desktop/Code/gpt4all/models/nous-hermes-13b.ggmlv3.q4_0.bin\"\n",
")"
]
},
{
@@ -436,7 +444,7 @@
" n_gpu_layers=1,\n",
" n_batch=512,\n",
" n_ctx=2048,\n",
" f16_kv=True, \n",
" f16_kv=True,\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),\n",
" verbose=True,\n",
")"
@@ -489,11 +497,9 @@
")\n",
"\n",
"QUESTION_PROMPT_SELECTOR = ConditionalPromptSelector(\n",
" default_prompt=DEFAULT_SEARCH_PROMPT,\n",
" conditionals=[\n",
" (lambda llm: isinstance(llm, LlamaCpp), DEFAULT_LLAMA_SEARCH_PROMPT)\n",
" ],\n",
" )\n",
" default_prompt=DEFAULT_SEARCH_PROMPT,\n",
" conditionals=[(lambda llm: isinstance(llm, LlamaCpp), DEFAULT_LLAMA_SEARCH_PROMPT)],\n",
")\n",
"\n",
"prompt = QUESTION_PROMPT_SELECTOR.get_prompt(llm)\n",
"prompt"
@@ -541,9 +547,9 @@
],
"source": [
"# Chain\n",
"llm_chain = LLMChain(prompt=prompt,llm=llm)\n",
"llm_chain = LLMChain(prompt=prompt, llm=llm)\n",
"question = \"What NFL team won the Super Bowl in the year that Justin Bieber was born?\"\n",
"llm_chain.run({\"question\":question})"
"llm_chain.run({\"question\": question})"
]
},
{

View File

@@ -63,7 +63,7 @@
"import boto3\n",
"import os\n",
"\n",
"comprehend_client = boto3.client('comprehend', region_name='us-east-1')"
"comprehend_client = boto3.client(\"comprehend\", region_name=\"us-east-1\")"
]
},
{
@@ -78,8 +78,7 @@
"from langchain_experimental.comprehend_moderation import AmazonComprehendModerationChain\n",
"\n",
"comprehend_moderation = AmazonComprehendModerationChain(\n",
" client=comprehend_client, #optional\n",
" verbose=True\n",
" client=comprehend_client, verbose=True # optional\n",
")"
]
},
@@ -104,7 +103,9 @@
"source": [
"from langchain.prompts import PromptTemplate\n",
"from langchain.llms.fake import FakeListLLM\n",
"from langchain_experimental.comprehend_moderation.base_moderation_exceptions import ModerationPiiError\n",
"from langchain_experimental.comprehend_moderation.base_moderation_exceptions import (\n",
" ModerationPiiError,\n",
")\n",
"\n",
"template = \"\"\"Question: {question}\n",
"\n",
@@ -113,25 +114,29 @@
"prompt = PromptTemplate(template=template, input_variables=[\"question\"])\n",
"\n",
"responses = [\n",
" \"Final Answer: A credit card number looks like 1289-2321-1123-2387. A fake SSN number looks like 323-22-9980. John Doe's phone number is (999)253-9876.\", \n",
" \"Final Answer: A credit card number looks like 1289-2321-1123-2387. A fake SSN number looks like 323-22-9980. John Doe's phone number is (999)253-9876.\",\n",
" # replace with your own expletive\n",
" \"Final Answer: This is a really <expletive> way of constructing a birdhouse. This is <expletive> insane to think that any birds would actually create their <expletive> nests here.\"\n",
" \"Final Answer: This is a really <expletive> way of constructing a birdhouse. This is <expletive> insane to think that any birds would actually create their <expletive> nests here.\",\n",
"]\n",
"llm = FakeListLLM(responses=responses)\n",
"\n",
"chain = (\n",
" prompt \n",
" | comprehend_moderation \n",
" | {\"input\": (lambda x: x['output'] ) | llm}\n",
" | comprehend_moderation \n",
" prompt\n",
" | comprehend_moderation\n",
" | {\"input\": (lambda x: x[\"output\"]) | llm}\n",
" | comprehend_moderation\n",
")\n",
"\n",
"try:\n",
" response = chain.invoke({\"question\": \"A sample SSN number looks like this 123-22-3345. Can you give me some more samples?\"})\n",
" response = chain.invoke(\n",
" {\n",
" \"question\": \"A sample SSN number looks like this 123-22-3345. Can you give me some more samples?\"\n",
" }\n",
" )\n",
"except ModerationPiiError as e:\n",
" print(str(e))\n",
"else:\n",
" print(response['output'])\n"
" print(response[\"output\"])"
]
},
{
@@ -166,25 +171,18 @@
},
"outputs": [],
"source": [
"from langchain_experimental.comprehend_moderation import (BaseModerationConfig, \n",
" ModerationPromptSafetyConfig, \n",
" ModerationPiiConfig, \n",
" ModerationToxicityConfig\n",
"from langchain_experimental.comprehend_moderation import (\n",
" BaseModerationConfig,\n",
" ModerationPromptSafetyConfig,\n",
" ModerationPiiConfig,\n",
" ModerationToxicityConfig,\n",
")\n",
"\n",
"pii_config = ModerationPiiConfig(\n",
" labels=[\"SSN\"],\n",
" redact=True,\n",
" mask_character=\"X\"\n",
")\n",
"pii_config = ModerationPiiConfig(labels=[\"SSN\"], redact=True, mask_character=\"X\")\n",
"\n",
"toxicity_config = ModerationToxicityConfig(\n",
" threshold=0.5\n",
")\n",
"toxicity_config = ModerationToxicityConfig(threshold=0.5)\n",
"\n",
"prompt_safety_config = ModerationPromptSafetyConfig(\n",
" threshold=0.5\n",
")\n",
"prompt_safety_config = ModerationPromptSafetyConfig(threshold=0.5)\n",
"\n",
"moderation_config = BaseModerationConfig(\n",
" filters=[pii_config, toxicity_config, prompt_safety_config]\n",
@@ -225,16 +223,16 @@
"outputs": [],
"source": [
"comp_moderation_with_config = AmazonComprehendModerationChain(\n",
" moderation_config=moderation_config, #specify the configuration\n",
" client=comprehend_client, #optionally pass the Boto3 Client\n",
" verbose=True\n",
" moderation_config=moderation_config, # specify the configuration\n",
" client=comprehend_client, # optionally pass the Boto3 Client\n",
" verbose=True,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a25e6f93-765b-4f99-8c1c-929157dbd4aa",
"id": "082c6cfc",
"metadata": {
"tags": []
},
@@ -250,26 +248,30 @@
"prompt = PromptTemplate(template=template, input_variables=[\"question\"])\n",
"\n",
"responses = [\n",
" \"Final Answer: A credit card number looks like 1289-2321-1123-2387. A fake SSN number looks like 323-22-9980. John Doe's phone number is (999)253-9876.\", \n",
" \"Final Answer: A credit card number looks like 1289-2321-1123-2387. A fake SSN number looks like 323-22-9980. John Doe's phone number is (999)253-9876.\",\n",
" # replace with your own expletive\n",
" \"Final Answer: This is a really <expletive> way of constructing a birdhouse. This is <expletive> insane to think that any birds would actually create their <expletive> nests here.\"\n",
" \"Final Answer: This is a really <expletive> way of constructing a birdhouse. This is <expletive> insane to think that any birds would actually create their <expletive> nests here.\",\n",
"]\n",
"llm = FakeListLLM(responses=responses)\n",
"\n",
"chain = ( \n",
" prompt \n",
" | comp_moderation_with_config \n",
" | {\"input\": (lambda x: x['output'] ) | llm}\n",
" | comp_moderation_with_config \n",
"chain = (\n",
" prompt\n",
" | comp_moderation_with_config\n",
" | {\"input\": (lambda x: x[\"output\"]) | llm}\n",
" | comp_moderation_with_config\n",
")\n",
"\n",
"\n",
"try:\n",
" response = chain.invoke({\"question\": \"A sample SSN number looks like this 123-45-7890. Can you give me some more samples?\"})\n",
" response = chain.invoke(\n",
" {\n",
" \"question\": \"A sample SSN number looks like this 123-45-7890. Can you give me some more samples?\"\n",
" }\n",
" )\n",
"except Exception as e:\n",
" print(str(e))\n",
"else:\n",
" print(response['output'])"
" print(response[\"output\"])"
]
},
{
@@ -343,24 +345,25 @@
"source": [
"# Define callback handlers by subclassing BaseModerationCallbackHandler\n",
"\n",
"\n",
"class MyModCallback(BaseModerationCallbackHandler):\n",
" \n",
" async def on_after_pii(self, output_beacon, unique_id):\n",
" import json\n",
" moderation_type = output_beacon['moderation_type']\n",
" chain_id = output_beacon['moderation_chain_id']\n",
" with open(f'output-{moderation_type}-{chain_id}.json', 'w') as file:\n",
" data = { 'beacon_data': output_beacon, 'unique_id': unique_id }\n",
"\n",
" moderation_type = output_beacon[\"moderation_type\"]\n",
" chain_id = output_beacon[\"moderation_chain_id\"]\n",
" with open(f\"output-{moderation_type}-{chain_id}.json\", \"w\") as file:\n",
" data = {\"beacon_data\": output_beacon, \"unique_id\": unique_id}\n",
" json.dump(data, file)\n",
" \n",
" '''\n",
"\n",
" \"\"\"\n",
" async def on_after_toxicity(self, output_beacon, unique_id):\n",
" pass\n",
" \n",
" async def on_after_prompt_safety(self, output_beacon, unique_id):\n",
" pass\n",
" '''\n",
" \n",
" \"\"\"\n",
"\n",
"\n",
"my_callback = MyModCallback()"
]
@@ -374,26 +377,18 @@
},
"outputs": [],
"source": [
"pii_config = ModerationPiiConfig(\n",
" labels=[\"SSN\"],\n",
" redact=True,\n",
" mask_character=\"X\"\n",
")\n",
"pii_config = ModerationPiiConfig(labels=[\"SSN\"], redact=True, mask_character=\"X\")\n",
"\n",
"toxicity_config = ModerationToxicityConfig(\n",
" threshold=0.5\n",
")\n",
"toxicity_config = ModerationToxicityConfig(threshold=0.5)\n",
"\n",
"moderation_config = BaseModerationConfig(\n",
" filters=[pii_config, toxicity_config]\n",
")\n",
"moderation_config = BaseModerationConfig(filters=[pii_config, toxicity_config])\n",
"\n",
"comp_moderation_with_config = AmazonComprehendModerationChain(\n",
" moderation_config=moderation_config, # specify the configuration\n",
" client=comprehend_client, # optionally pass the Boto3 Client\n",
" unique_id='john.doe@email.com', # A unique ID\n",
" moderation_callback=my_callback, # BaseModerationCallbackHandler\n",
" verbose=True\n",
" moderation_config=moderation_config, # specify the configuration\n",
" client=comprehend_client, # optionally pass the Boto3 Client\n",
" unique_id=\"john.doe@email.com\", # A unique ID\n",
" moderation_callback=my_callback, # BaseModerationCallbackHandler\n",
" verbose=True,\n",
")"
]
},
@@ -416,26 +411,30 @@
"prompt = PromptTemplate(template=template, input_variables=[\"question\"])\n",
"\n",
"responses = [\n",
" \"Final Answer: A credit card number looks like 1289-2321-1123-2387. A fake SSN number looks like 323-22-9980. John Doe's phone number is (999)253-9876.\", \n",
" \"Final Answer: A credit card number looks like 1289-2321-1123-2387. A fake SSN number looks like 323-22-9980. John Doe's phone number is (999)253-9876.\",\n",
" # replace with your own expletive\n",
" \"Final Answer: This is a really <expletive> way of constructing a birdhouse. This is <expletive> insane to think that any birds would actually create their <expletive> nests here.\"\n",
" \"Final Answer: This is a really <expletive> way of constructing a birdhouse. This is <expletive> insane to think that any birds would actually create their <expletive> nests here.\",\n",
"]\n",
"\n",
"llm = FakeListLLM(responses=responses)\n",
"\n",
"chain = (\n",
" prompt \n",
" | comp_moderation_with_config \n",
" | {\"input\": (lambda x: x['output'] ) | llm}\n",
" | comp_moderation_with_config \n",
") \n",
" prompt\n",
" | comp_moderation_with_config\n",
" | {\"input\": (lambda x: x[\"output\"]) | llm}\n",
" | comp_moderation_with_config\n",
")\n",
"\n",
"try:\n",
" response = chain.invoke({\"question\": \"A sample SSN number looks like this 123-456-7890. Can you give me some more samples?\"})\n",
" response = chain.invoke(\n",
" {\n",
" \"question\": \"A sample SSN number looks like this 123-456-7890. Can you give me some more samples?\"\n",
" }\n",
" )\n",
"except Exception as e:\n",
" print(str(e))\n",
"else:\n",
" print(response['output'])"
" print(response[\"output\"])"
]
},
{
@@ -537,6 +536,7 @@
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ[\"HUGGINGFACEHUB_API_TOKEN\"] = \"<YOUR HF TOKEN HERE>\""
]
},
@@ -550,7 +550,7 @@
"outputs": [],
"source": [
"# See https://huggingface.co/models?pipeline_tag=text-generation&sort=downloads for some other options\n",
"repo_id = \"google/flan-t5-xxl\" "
"repo_id = \"google/flan-t5-xxl\""
]
},
{
@@ -562,7 +562,7 @@
},
"outputs": [],
"source": [
"from langchain import HuggingFaceHub\n",
"from langchain.llms import HuggingFaceHub\n",
"from langchain.prompts import PromptTemplate\n",
"\n",
"template = \"\"\"{question}\"\"\"\n",
@@ -590,42 +590,35 @@
},
"outputs": [],
"source": [
"\n",
"# define filter configs\n",
"pii_config = ModerationPiiConfig(\n",
" labels=[\"SSN\", \"CREDIT_DEBIT_NUMBER\"],\n",
" redact=True,\n",
" mask_character=\"X\"\n",
" labels=[\"SSN\", \"CREDIT_DEBIT_NUMBER\"], redact=True, mask_character=\"X\"\n",
")\n",
"\n",
"toxicity_config = ModerationToxicityConfig(\n",
" threshold=0.5\n",
")\n",
"toxicity_config = ModerationToxicityConfig(threshold=0.5)\n",
"\n",
"prompt_safety_config = ModerationPromptSafetyConfig(\n",
" threshold=0.8\n",
")\n",
"prompt_safety_config = ModerationPromptSafetyConfig(threshold=0.8)\n",
"\n",
"# define different moderation configs using the filter configs above\n",
"moderation_config_1 = BaseModerationConfig(\n",
" filters=[pii_config, toxicity_config, prompt_safety_config]\n",
")\n",
"\n",
"moderation_config_2 = BaseModerationConfig(\n",
" filters=[pii_config]\n",
")\n",
"moderation_config_2 = BaseModerationConfig(filters=[pii_config])\n",
"\n",
"\n",
"# input prompt moderation chain with callback\n",
"amazon_comp_moderation = AmazonComprehendModerationChain(moderation_config=moderation_config_1, \n",
" client=comprehend_client,\n",
" moderation_callback=my_callback,\n",
" verbose=True)\n",
"amazon_comp_moderation = AmazonComprehendModerationChain(\n",
" moderation_config=moderation_config_1,\n",
" client=comprehend_client,\n",
" moderation_callback=my_callback,\n",
" verbose=True,\n",
")\n",
"\n",
"# Output from LLM moderation chain without callback\n",
"amazon_comp_moderation_out = AmazonComprehendModerationChain(moderation_config=moderation_config_2, \n",
" client=comprehend_client,\n",
" verbose=True)"
"amazon_comp_moderation_out = AmazonComprehendModerationChain(\n",
" moderation_config=moderation_config_2, client=comprehend_client, verbose=True\n",
")"
]
},
{
@@ -646,21 +639,25 @@
"outputs": [],
"source": [
"chain = (\n",
" prompt \n",
" | amazon_comp_moderation \n",
" | { \"input\" : (lambda x: x['output']) | llm }\n",
" prompt\n",
" | amazon_comp_moderation\n",
" | {\"input\": (lambda x: x[\"output\"]) | llm}\n",
" | amazon_comp_moderation_out\n",
")\n",
"\n",
"try:\n",
" response = chain.invoke({\"question\": \"\"\"What is John Doe's address, phone number and SSN from the following text?\n",
" response = chain.invoke(\n",
" {\n",
" \"question\": \"\"\"What is John Doe's address, phone number and SSN from the following text?\n",
"\n",
"John Doe, a resident of 1234 Elm Street in Springfield, recently celebrated his birthday on January 1st. Turning 43 this year, John reflected on the years gone by. He often shares memories of his younger days with his close friends through calls on his phone, (555) 123-4567. Meanwhile, during a casual evening, he received an email at johndoe@example.com reminding him of an old acquaintance's reunion. As he navigated through some old documents, he stumbled upon a paper that listed his SSN as 123-45-6789, reminding him to store it in a safer place.\n",
"\"\"\"})\n",
"\"\"\"\n",
" }\n",
" )\n",
"except Exception as e:\n",
" print(str(e))\n",
"else:\n",
" print(response['output'])"
" print(response[\"output\"])"
]
},
{
@@ -682,7 +679,7 @@
"metadata": {},
"outputs": [],
"source": [
"endpoint_name = \"<SAGEMAKER_ENDPOINT_NAME>\" # replace with your SageMaker Endpoint name\n",
"endpoint_name = \"<SAGEMAKER_ENDPOINT_NAME>\" # replace with your SageMaker Endpoint name\n",
"region = \"<REGION>\" # replace with your SageMaker Endpoint region"
]
},
@@ -693,22 +690,24 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain import SagemakerEndpoint\n",
"from langchain.llms import SagemakerEndpoint\n",
"from langchain.llms.sagemaker_endpoint import LLMContentHandler\n",
"from langchain.prompts import PromptTemplate\n",
"import json\n",
"\n",
"\n",
"class ContentHandler(LLMContentHandler):\n",
" content_type = \"application/json\"\n",
" accepts = \"application/json\"\n",
"\n",
" def transform_input(self, prompt: str, model_kwargs: dict) -> bytes:\n",
" input_str = json.dumps({\"text_inputs\": prompt, **model_kwargs})\n",
" return input_str.encode('utf-8')\n",
" \n",
" input_str = json.dumps({\"text_inputs\": prompt, **model_kwargs})\n",
" return input_str.encode(\"utf-8\")\n",
"\n",
" def transform_output(self, output: bytes) -> str:\n",
" response_json = json.loads(output.read().decode(\"utf-8\"))\n",
" return response_json['generated_texts'][0]\n",
" return response_json[\"generated_texts\"][0]\n",
"\n",
"\n",
"content_handler = ContentHandler()\n",
"\n",
@@ -719,20 +718,22 @@
"Answer:\n",
"\"\"\"\n",
"\n",
"#prompt template for input text\n",
"# prompt template for input text\n",
"llm_prompt = PromptTemplate(template=template, input_variables=[\"question\"])\n",
"\n",
"llm=SagemakerEndpoint(\n",
" endpoint_name=endpoint_name, \n",
" region_name=region,\n",
" model_kwargs={\"temperature\":0.95,\n",
" \"max_length\": 200,\n",
" \"num_return_sequences\": 3,\n",
" \"top_k\": 50,\n",
" \"top_p\": 0.95,\n",
" \"do_sample\": True},\n",
" content_handler=content_handler\n",
" )"
"llm = SagemakerEndpoint(\n",
" endpoint_name=endpoint_name,\n",
" region_name=region,\n",
" model_kwargs={\n",
" \"temperature\": 0.95,\n",
" \"max_length\": 200,\n",
" \"num_return_sequences\": 3,\n",
" \"top_k\": 50,\n",
" \"top_p\": 0.95,\n",
" \"do_sample\": True,\n",
" },\n",
" content_handler=content_handler,\n",
")"
]
},
{
@@ -753,37 +754,29 @@
"outputs": [],
"source": [
"# define filter configs\n",
"pii_config = ModerationPiiConfig(\n",
" labels=[\"SSN\"],\n",
" redact=True,\n",
" mask_character=\"X\"\n",
")\n",
"pii_config = ModerationPiiConfig(labels=[\"SSN\"], redact=True, mask_character=\"X\")\n",
"\n",
"toxicity_config = ModerationToxicityConfig(\n",
" threshold=0.5\n",
")\n",
"toxicity_config = ModerationToxicityConfig(threshold=0.5)\n",
"\n",
"\n",
"# define different moderation configs using the filter configs above\n",
"moderation_config_1 = BaseModerationConfig(\n",
" filters=[pii_config, toxicity_config]\n",
")\n",
"moderation_config_1 = BaseModerationConfig(filters=[pii_config, toxicity_config])\n",
"\n",
"moderation_config_2 = BaseModerationConfig(\n",
" filters=[pii_config]\n",
")\n",
"moderation_config_2 = BaseModerationConfig(filters=[pii_config])\n",
"\n",
"\n",
"# input prompt moderation chain with callback\n",
"amazon_comp_moderation = AmazonComprehendModerationChain(moderation_config=moderation_config_1, \n",
" client=comprehend_client,\n",
" moderation_callback=my_callback,\n",
" verbose=True)\n",
"amazon_comp_moderation = AmazonComprehendModerationChain(\n",
" moderation_config=moderation_config_1,\n",
" client=comprehend_client,\n",
" moderation_callback=my_callback,\n",
" verbose=True,\n",
")\n",
"\n",
"# Output from LLM moderation chain without callback\n",
"amazon_comp_moderation_out = AmazonComprehendModerationChain(moderation_config=moderation_config_2, \n",
" client=comprehend_client,\n",
" verbose=True)"
"amazon_comp_moderation_out = AmazonComprehendModerationChain(\n",
" moderation_config=moderation_config_2, client=comprehend_client, verbose=True\n",
")"
]
},
{
@@ -804,18 +797,20 @@
"outputs": [],
"source": [
"chain = (\n",
" prompt \n",
" | amazon_comp_moderation \n",
" | { \"input\" : (lambda x: x['output']) | llm }\n",
" prompt\n",
" | amazon_comp_moderation\n",
" | {\"input\": (lambda x: x[\"output\"]) | llm}\n",
" | amazon_comp_moderation_out\n",
")\n",
"\n",
"try:\n",
" response = chain.invoke({\"question\": \"What is John Doe's address, phone number and SSN?\"})\n",
" response = chain.invoke(\n",
" {\"question\": \"What is John Doe's address, phone number and SSN?\"}\n",
" )\n",
"except Exception as e:\n",
" print(str(e))\n",
"else:\n",
" print(response['output'])"
" print(response[\"output\"])"
]
},
{
@@ -1419,7 +1414,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -122,8 +122,7 @@
"from langchain.callbacks.confident_callback import DeepEvalCallbackHandler\n",
"\n",
"deepeval_callback = DeepEvalCallbackHandler(\n",
" implementation_name=\"langchainQuickstart\",\n",
" metrics=[answer_relevancy_metric]\n",
" implementation_name=\"langchainQuickstart\", metrics=[answer_relevancy_metric]\n",
")"
]
},
@@ -155,6 +154,7 @@
],
"source": [
"from langchain.llms import OpenAI\n",
"\n",
"llm = OpenAI(\n",
" temperature=0,\n",
" callbacks=[deepeval_callback],\n",
@@ -227,8 +227,8 @@
"openai_api_key = \"sk-XXX\"\n",
"\n",
"with open(\"state_of_the_union.txt\", \"w\") as f:\n",
" response = requests.get(text_file_url)\n",
" f.write(response.text)\n",
" response = requests.get(text_file_url)\n",
" f.write(response.text)\n",
"\n",
"loader = TextLoader(\"state_of_the_union.txt\")\n",
"documents = loader.load()\n",
@@ -239,8 +239,9 @@
"docsearch = Chroma.from_documents(texts, embeddings)\n",
"\n",
"qa = RetrievalQA.from_chain_type(\n",
" llm=OpenAI(openai_api_key=openai_api_key), chain_type=\"stuff\",\n",
" retriever=docsearch.as_retriever()\n",
" llm=OpenAI(openai_api_key=openai_api_key),\n",
" chain_type=\"stuff\",\n",
" retriever=docsearch.as_retriever(),\n",
")\n",
"\n",
"# Providing a new question-answering pipeline\n",

View File

@@ -234,8 +234,7 @@
" plt.ylabel(\"Value\")\n",
" plt.title(title)\n",
"\n",
" plt.show()\n",
"\n"
" plt.show()"
]
},
{
@@ -325,9 +324,11 @@
" model_id=\"test_chatopenai\", model_version=\"0.1\", verbose=False\n",
")\n",
"\n",
"urls = [\"https://lilianweng.github.io/posts/2023-06-23-agent/\",\n",
" \"https://medium.com/lyft-engineering/lyftlearn-ml-model-training-infrastructure-built-on-kubernetes-aef8218842bb\",\n",
" \"https://blog.langchain.dev/week-of-10-2-langchain-release-notes/\"]\n",
"urls = [\n",
" \"https://lilianweng.github.io/posts/2023-06-23-agent/\",\n",
" \"https://medium.com/lyft-engineering/lyftlearn-ml-model-training-infrastructure-built-on-kubernetes-aef8218842bb\",\n",
" \"https://blog.langchain.dev/week-of-10-2-langchain-release-notes/\",\n",
"]\n",
"\n",
"for url in urls:\n",
" loader = WebBaseLoader(url)\n",
@@ -364,7 +365,7 @@
"plot(response.text, \"Prompt Tokens\")\n",
"\n",
"response = client.search_ts(\"__name__\", \"completion_tokens\", 0, int(time.time()))\n",
"plot(response.text, \"Completion Tokens\")\n"
"plot(response.text, \"Completion Tokens\")"
]
},
{

View File

@@ -97,9 +97,9 @@
"source": [
"import os\n",
"\n",
"os.environ['LABEL_STUDIO_URL'] = '<YOUR-LABEL-STUDIO-URL>' # e.g. http://localhost:8080\n",
"os.environ['LABEL_STUDIO_API_KEY'] = '<YOUR-LABEL-STUDIO-API-KEY>'\n",
"os.environ['OPENAI_API_KEY'] = '<YOUR-OPENAI-API-KEY>'"
"os.environ[\"LABEL_STUDIO_URL\"] = \"<YOUR-LABEL-STUDIO-URL>\" # e.g. http://localhost:8080\n",
"os.environ[\"LABEL_STUDIO_API_KEY\"] = \"<YOUR-LABEL-STUDIO-API-KEY>\"\n",
"os.environ[\"OPENAI_API_KEY\"] = \"<YOUR-OPENAI-API-KEY>\""
]
},
{
@@ -174,11 +174,7 @@
"from langchain.callbacks import LabelStudioCallbackHandler\n",
"\n",
"llm = OpenAI(\n",
" temperature=0,\n",
" callbacks=[\n",
" LabelStudioCallbackHandler(\n",
" project_name=\"My Project\"\n",
" )]\n",
" temperature=0, callbacks=[LabelStudioCallbackHandler(project_name=\"My Project\")]\n",
")\n",
"print(llm(\"Tell me a joke\"))"
]
@@ -249,16 +245,20 @@
"from langchain.schema import HumanMessage, SystemMessage\n",
"from langchain.callbacks import LabelStudioCallbackHandler\n",
"\n",
"chat_llm = ChatOpenAI(callbacks=[\n",
" LabelStudioCallbackHandler(\n",
" mode=\"chat\",\n",
" project_name=\"New Project with Chat\",\n",
" )\n",
"])\n",
"llm_results = chat_llm([\n",
" SystemMessage(content=\"Always use a lot of emojis\"),\n",
" HumanMessage(content=\"Tell me a joke\")\n",
"])"
"chat_llm = ChatOpenAI(\n",
" callbacks=[\n",
" LabelStudioCallbackHandler(\n",
" mode=\"chat\",\n",
" project_name=\"New Project with Chat\",\n",
" )\n",
" ]\n",
")\n",
"llm_results = chat_llm(\n",
" [\n",
" SystemMessage(content=\"Always use a lot of emojis\"),\n",
" HumanMessage(content=\"Tell me a joke\"),\n",
" ]\n",
")"
]
},
{
@@ -304,7 +304,8 @@
},
"outputs": [],
"source": [
"ls = LabelStudioCallbackHandler(project_config='''\n",
"ls = LabelStudioCallbackHandler(\n",
" project_config=\"\"\"\n",
"<View>\n",
"<Text name=\"prompt\" value=\"$prompt\"/>\n",
"<TextArea name=\"response\" toName=\"prompt\"/>\n",
@@ -315,7 +316,8 @@
" <Choice value=\"Negative\"/>\n",
"</Choices>\n",
"</View>\n",
"''')"
"\"\"\"\n",
")"
]
},
{

View File

@@ -105,19 +105,19 @@
},
"outputs": [],
"source": [
"#LLM Hyperparameters\n",
"# LLM Hyperparameters\n",
"HPARAMS = {\n",
" \"temperature\": 0.1,\n",
" \"model_name\": \"text-davinci-003\",\n",
"}\n",
"\n",
"#Bucket used to save prompt logs (Use `None` is used to save the default bucket or otherwise change it)\n",
"# Bucket used to save prompt logs (Use `None` is used to save the default bucket or otherwise change it)\n",
"BUCKET_NAME = None\n",
"\n",
"#Experiment name\n",
"# Experiment name\n",
"EXPERIMENT_NAME = \"langchain-sagemaker-tracker\"\n",
"\n",
"#Create SageMaker Session with the given bucket\n",
"# Create SageMaker Session with the given bucket\n",
"session = Session(default_bucket=BUCKET_NAME)"
]
},
@@ -150,8 +150,9 @@
"metadata": {},
"outputs": [],
"source": [
"with Run(experiment_name=EXPERIMENT_NAME, run_name=RUN_NAME, sagemaker_session=session) as run:\n",
"\n",
"with Run(\n",
" experiment_name=EXPERIMENT_NAME, run_name=RUN_NAME, sagemaker_session=session\n",
") as run:\n",
" # Create SageMaker Callback\n",
" sagemaker_callback = SageMakerCallbackHandler(run)\n",
"\n",
@@ -209,8 +210,9 @@
"metadata": {},
"outputs": [],
"source": [
"with Run(experiment_name=EXPERIMENT_NAME, run_name=RUN_NAME, sagemaker_session=session) as run:\n",
"\n",
"with Run(\n",
" experiment_name=EXPERIMENT_NAME, run_name=RUN_NAME, sagemaker_session=session\n",
") as run:\n",
" # Create SageMaker Callback\n",
" sagemaker_callback = SageMakerCallbackHandler(run)\n",
"\n",
@@ -228,7 +230,9 @@
" chain2 = LLMChain(llm=llm, prompt=prompt_template2, callbacks=[sagemaker_callback])\n",
"\n",
" # Create Sequential chain\n",
" overall_chain = SimpleSequentialChain(chains=[chain1, chain2], callbacks=[sagemaker_callback])\n",
" overall_chain = SimpleSequentialChain(\n",
" chains=[chain1, chain2], callbacks=[sagemaker_callback]\n",
" )\n",
"\n",
" # Run overall sequential chain\n",
" overall_chain.run(**INPUT_VARIABLES)\n",
@@ -267,8 +271,9 @@
},
"outputs": [],
"source": [
"with Run(experiment_name=EXPERIMENT_NAME, run_name=RUN_NAME, sagemaker_session=session) as run:\n",
"\n",
"with Run(\n",
" experiment_name=EXPERIMENT_NAME, run_name=RUN_NAME, sagemaker_session=session\n",
") as run:\n",
" # Create SageMaker Callback\n",
" sagemaker_callback = SageMakerCallbackHandler(run)\n",
"\n",
@@ -279,7 +284,9 @@
" tools = load_tools([\"serpapi\", \"llm-math\"], llm=llm, callbacks=[sagemaker_callback])\n",
"\n",
" # Initialize agent with all the tools\n",
" agent = initialize_agent(tools, llm, agent=\"zero-shot-react-description\", callbacks=[sagemaker_callback])\n",
" agent = initialize_agent(\n",
" tools, llm, agent=\"zero-shot-react-description\", callbacks=[sagemaker_callback]\n",
" )\n",
"\n",
" # Run agent\n",
" agent.run(input=PROMPT_TEMPLATE)\n",
@@ -309,10 +316,10 @@
},
"outputs": [],
"source": [
"#Load\n",
"# Load\n",
"logs = ExperimentAnalytics(experiment_name=EXPERIMENT_NAME)\n",
"\n",
"#Convert as pandas dataframe\n",
"# Convert as pandas dataframe\n",
"df = logs.dataframe(force_refresh=True)\n",
"\n",
"print(df.shape)\n",

View File

@@ -113,7 +113,7 @@
"tags": []
},
"source": [
"Here are two examples of how to use the `TrubricsCallbackHandler` with Langchain [LLMs](https://python.langchain.com/docs/modules/model_io/models/llms/) or [Chat Models](https://python.langchain.com/docs/modules/model_io/models/chat/). We will use OpenAI models, so set your `OPENAI_API_KEY` key here:"
"Here are two examples of how to use the `TrubricsCallbackHandler` with Langchain [LLMs](https://python.langchain.com/docs/modules/model_io/llms/) or [Chat Models](https://python.langchain.com/docs/modules/model_io/chat/). We will use OpenAI models, so set your `OPENAI_API_KEY` key here:"
]
},
{
@@ -284,7 +284,7 @@
" project=\"default\",\n",
" tags=[\"chat model\"],\n",
" user_id=\"user-id-1234\",\n",
" some_metadata={\"hello\": [1, 2]}\n",
" some_metadata={\"hello\": [1, 2]},\n",
" )\n",
" ]\n",
")"

View File

@@ -46,7 +46,7 @@
"metadata": {},
"outputs": [],
"source": [
"model = AnthropicFunctions(model='claude-2')"
"model = AnthropicFunctions(model=\"claude-2\")"
]
},
{
@@ -66,26 +66,23 @@
"metadata": {},
"outputs": [],
"source": [
"functions=[\n",
"functions = [\n",
" {\n",
" \"name\": \"get_current_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\"\n",
" },\n",
" \"unit\": {\n",
" \"type\": \"string\",\n",
" \"enum\": [\"celsius\", \"fahrenheit\"]\n",
" }\n",
" \"name\": \"get_current_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
" },\n",
" \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]},\n",
" },\n",
" \"required\": [\"location\"],\n",
" },\n",
" \"required\": [\"location\"]\n",
" }\n",
" }\n",
" ]"
"]"
]
},
{
@@ -106,8 +103,7 @@
"outputs": [],
"source": [
"response = model.predict_messages(\n",
" [HumanMessage(content=\"whats the weater in boston?\")], \n",
" functions=functions\n",
" [HumanMessage(content=\"whats the weater in boston?\")], functions=functions\n",
")"
]
},
@@ -150,6 +146,7 @@
"outputs": [],
"source": [
"from langchain.chains import create_extraction_chain\n",
"\n",
"schema = {\n",
" \"properties\": {\n",
" \"name\": {\"type\": \"string\"},\n",

View File

@@ -102,19 +102,15 @@
"from langchain.schema import SystemMessage, HumanMessage\n",
"\n",
"messages = [\n",
" SystemMessage(\n",
" content=\"You are a helpful AI that shares everything you know.\"\n",
" ),\n",
" SystemMessage(content=\"You are a helpful AI that shares everything you know.\"),\n",
" HumanMessage(\n",
" content=\"Tell me technical facts about yourself. Are you a transformer model? How many billions of parameters do you have?\"\n",
" ),\n",
"]\n",
"\n",
"\n",
"async def get_msgs():\n",
" tasks = [\n",
" chat.apredict_messages(messages)\n",
" for chat in chats.values()\n",
" ]\n",
" tasks = [chat.apredict_messages(messages) for chat in chats.values()]\n",
" responses = await asyncio.gather(*tasks)\n",
" return dict(zip(chats.keys(), responses))"
]
@@ -194,10 +190,10 @@
"response_dict = asyncio.run(get_msgs())\n",
"\n",
"for model_name, response in response_dict.items():\n",
" print(f'\\t{model_name}')\n",
" print(f\"\\t{model_name}\")\n",
" print()\n",
" print(response.content)\n",
" print('\\n---\\n')"
" print(\"\\n---\\n\")"
]
}
],

View File

@@ -5,18 +5,20 @@
"id": "38f26d7a",
"metadata": {},
"source": [
"# Azure\n",
"# Azure OpenAI\n",
"\n",
"This notebook goes over how to connect to an Azure hosted OpenAI endpoint"
"This notebook goes over how to connect to an Azure hosted OpenAI endpoint. We recommend having version `openai>=1` installed."
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"id": "96164b42",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"from langchain.chat_models import AzureChatOpenAI\n",
"from langchain.schema import HumanMessage"
]
@@ -24,57 +26,51 @@
{
"cell_type": "code",
"execution_count": 4,
"id": "cbe4bb58-ba13-4355-8af9-cd990dc47a64",
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"AZURE_OPENAI_API_KEY\"] = \"...\"\n",
"os.environ[\"AZURE_OPENAI_ENDPOINT\"] = \"https://<your-endpoint>.openai.azure.com/\""
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "8161278f",
"metadata": {},
"outputs": [],
"source": [
"BASE_URL = \"https://${TODO}.openai.azure.com\"\n",
"API_KEY = \"...\"\n",
"DEPLOYMENT_NAME = \"chat\"\n",
"model = AzureChatOpenAI(\n",
" openai_api_base=BASE_URL,\n",
" openai_api_version=\"2023-05-15\",\n",
" deployment_name=DEPLOYMENT_NAME,\n",
" openai_api_key=API_KEY,\n",
" openai_api_type=\"azure\",\n",
" azure_deployment=\"your-deployment-name\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 15,
"id": "99509140",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\"\\n\\nJ'aime programmer.\", additional_kwargs={})"
"AIMessage(content=\"J'adore la programmation.\")"
]
},
"execution_count": 5,
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model(\n",
" [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
" ]\n",
")"
"message = HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
")\n",
"model([message])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3b6e9376",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "f27fa24d",
@@ -88,7 +84,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"id": "0531798a",
"metadata": {},
"outputs": [],
@@ -98,49 +94,22 @@
},
{
"cell_type": "code",
"execution_count": 14,
"id": "3fd97dfc",
"metadata": {},
"outputs": [],
"source": [
"BASE_URL = \"https://{endpoint}.openai.azure.com\"\n",
"API_KEY = \"...\"\n",
"DEPLOYMENT_NAME = \"gpt-35-turbo\" # in Azure, this deployment has version 0613 - input and output tokens are counted separately"
]
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": null,
"id": "aceddb72",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total Cost (USD): $0.000054\n"
]
}
],
"outputs": [],
"source": [
"model = AzureChatOpenAI(\n",
" openai_api_base=BASE_URL,\n",
" openai_api_version=\"2023-05-15\",\n",
" deployment_name=DEPLOYMENT_NAME,\n",
" openai_api_key=API_KEY,\n",
" openai_api_type=\"azure\",\n",
" azure_deployment=\"gpt-35-turbo\", # in Azure, this deployment has version 0613 - input and output tokens are counted separately\n",
")\n",
"with get_openai_callback() as cb:\n",
" model(\n",
" [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
" ]\n",
" )\n",
" print(f\"Total Cost (USD): ${format(cb.total_cost, '.6f')}\") # without specifying the model version, flat-rate 0.002 USD per 1k input and output tokens is used\n"
" model([message])\n",
" print(\n",
" f\"Total Cost (USD): ${format(cb.total_cost, '.6f')}\"\n",
" ) # without specifying the model version, flat-rate 0.002 USD per 1k input and output tokens is used"
]
},
{
@@ -167,22 +136,13 @@
],
"source": [
"model0613 = AzureChatOpenAI(\n",
" openai_api_base=BASE_URL,\n",
" openai_api_version=\"2023-05-15\",\n",
" deployment_name=DEPLOYMENT_NAME,\n",
" openai_api_key=API_KEY,\n",
" openai_api_type=\"azure\",\n",
" model_version=\"0613\"\n",
" deployment_name=\"gpt-35-turbo,\n",
" model_version=\"0613\",\n",
")\n",
"with get_openai_callback() as cb:\n",
" model0613(\n",
" [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
" ]\n",
" )\n",
" print(f\"Total Cost (USD): ${format(cb.total_cost, '.6f')}\")\n"
" model0613([message])\n",
" print(f\"Total Cost (USD): ${format(cb.total_cost, '.6f')}\")"
]
},
{
@@ -210,7 +170,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.9.1"
}
},
"nbformat": 4,

View File

@@ -67,10 +67,10 @@
" endpoint_url=\"https://<your-endpoint>.<your_region>.inference.ml.azure.com/score\",\n",
" endpoint_api_key=\"my-api-key\",\n",
" content_formatter=LlamaContentFormatter,\n",
"))\n",
"response = chat(messages=[\n",
" HumanMessage(content=\"Will the Collatz conjecture ever be solved?\")\n",
"])\n",
")\n",
"response = chat(\n",
" messages=[HumanMessage(content=\"Will the Collatz conjecture ever be solved?\")]\n",
")\n",
"response"
]
}
@@ -91,9 +91,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.11"
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View File

@@ -36,8 +36,7 @@
"outputs": [],
"source": [
"chat = ChatBaichuan(\n",
" baichuan_api_key='YOUR_API_KEY',\n",
" baichuan_secret_key='YOUR_SECRET_KEY'\n",
" baichuan_api_key=\"YOUR_API_KEY\", baichuan_secret_key=\"YOUR_SECRET_KEY\"\n",
")"
]
},
@@ -72,9 +71,7 @@
}
],
"source": [
"chat([\n",
" HumanMessage(content='我日薪8块钱请问在闰年的二月我月薪多少')\n",
"])"
"chat([HumanMessage(content=\"我日薪8块钱请问在闰年的二月我月薪多少\")])"
]
},
{
@@ -92,9 +89,9 @@
"outputs": [],
"source": [
"chat = ChatBaichuan(\n",
" baichuan_api_key='YOUR_API_KEY',\n",
" baichuan_secret_key='YOUR_SECRET_KEY',\n",
" streaming=True\n",
" baichuan_api_key=\"YOUR_API_KEY\",\n",
" baichuan_secret_key=\"YOUR_SECRET_KEY\",\n",
" streaming=True,\n",
")"
],
"metadata": {
@@ -119,9 +116,7 @@
}
],
"source": [
"chat([\n",
" HumanMessage(content='我日薪8块钱请问在闰年的二月我月薪多少')\n",
"])"
"chat([HumanMessage(content=\"我日薪8块钱请问在闰年的二月我月薪多少\")])"
],
"metadata": {
"collapsed": false,

View File

@@ -59,16 +59,17 @@
],
"source": [
"\"\"\"For basic init and call\"\"\"\n",
"from langchain.chat_models import QianfanChatEndpoint \n",
"from langchain.chat_models import QianfanChatEndpoint\n",
"from langchain.chat_models.base import HumanMessage\n",
"import os\n",
"\n",
"os.environ[\"QIANFAN_AK\"] = \"your_ak\"\n",
"os.environ[\"QIANFAN_SK\"] = \"your_sk\"\n",
"\n",
"chat = QianfanChatEndpoint(\n",
" streaming=True, \n",
" )\n",
"res = chat([HumanMessage(content=\"write a funny joke\")])\n"
" streaming=True,\n",
")\n",
"res = chat([HumanMessage(content=\"write a funny joke\")])"
]
},
{
@@ -112,7 +113,6 @@
}
],
"source": [
" \n",
"from langchain.chat_models import QianfanChatEndpoint\n",
"from langchain.schema import HumanMessage\n",
"\n",
@@ -125,15 +125,22 @@
"\n",
"\n",
"async def run_aio_generate():\n",
" resp = await chatLLM.agenerate(messages=[[HumanMessage(content=\"write a 20 words sentence about sea.\")]])\n",
" resp = await chatLLM.agenerate(\n",
" messages=[[HumanMessage(content=\"write a 20 words sentence about sea.\")]]\n",
" )\n",
" print(resp)\n",
" \n",
"\n",
"\n",
"await run_aio_generate()\n",
"\n",
"\n",
"async def run_aio_stream():\n",
" async for res in chatLLM.astream([HumanMessage(content=\"write a 20 words sentence about sea.\")]):\n",
" async for res in chatLLM.astream(\n",
" [HumanMessage(content=\"write a 20 words sentence about sea.\")]\n",
" ):\n",
" print(\"astream\", res)\n",
" \n",
"\n",
"\n",
"await run_aio_stream()"
]
},
@@ -172,9 +179,9 @@
],
"source": [
"chatBloom = QianfanChatEndpoint(\n",
" streaming=True, \n",
" model=\"BLOOMZ-7B\",\n",
" )\n",
" streaming=True,\n",
" model=\"BLOOMZ-7B\",\n",
")\n",
"res = chatBloom([HumanMessage(content=\"hi\")])\n",
"print(res)"
]
@@ -217,7 +224,10 @@
}
],
"source": [
"res = chat.stream([HumanMessage(content=\"hi\")], **{'top_p': 0.4, 'temperature': 0.1, 'penalty_score': 1})\n",
"res = chat.stream(\n",
" [HumanMessage(content=\"hi\")],\n",
" **{\"top_p\": 0.4, \"temperature\": 0.1, \"penalty_score\": 1}\n",
")\n",
"\n",
"for r in res:\n",
" print(r)"

View File

@@ -1,139 +1,139 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "bf733a38-db84-4363-89e2-de6735c37230",
"metadata": {},
"source": [
"# Bedrock Chat\n",
"\n",
"[Amazon Bedrock](https://aws.amazon.com/bedrock/) is a fully managed service that makes FMs from leading AI startups and Amazon available via an API, so you can choose from a wide range of FMs to find the model that is best suited for your use case"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d51edc81",
"metadata": {},
"outputs": [],
"source": [
"%pip install boto3"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4a7c55d-b235-4ca4-a579-c90cc9570da9",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.chat_models import BedrockChat\n",
"from langchain.schema import HumanMessage"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "70cf04e8-423a-4ff6-8b09-f11fb711c817",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"chat = BedrockChat(model_id=\"anthropic.claude-v2\", model_kwargs={\"temperature\":0.1})"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "8199ef8f-eb8b-4253-9ea0-6c24a013ca4c",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\" Voici la traduction en français : J'adore programmer.\", additional_kwargs={}, example=False)"
]
},
"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": "a4a4f4d4",
"metadata": {},
"source": [
"### For BedrockChat with Streaming"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c253883f",
"metadata": {},
"outputs": [],
"source": [
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"\n",
"chat = BedrockChat(\n",
" model_id=\"anthropic.claude-v2\",\n",
" streaming=True,\n",
" callbacks=[StreamingStdOutCallbackHandler()],\n",
" model_kwargs={\"temperature\": 0.1},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d9e52838",
"metadata": {},
"outputs": [],
"source": [
"messages = [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
"]\n",
"chat(messages)"
]
}
],
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
"cells": [
{
"cell_type": "markdown",
"id": "bf733a38-db84-4363-89e2-de6735c37230",
"metadata": {},
"source": [
"# Bedrock Chat\n",
"\n",
"[Amazon Bedrock](https://aws.amazon.com/bedrock/) is a fully managed service that makes FMs from leading AI startups and Amazon available via an API, so you can choose from a wide range of FMs to find the model that is best suited for your use case"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d51edc81",
"metadata": {},
"outputs": [],
"source": [
"%pip install boto3"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4a7c55d-b235-4ca4-a579-c90cc9570da9",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.chat_models import BedrockChat\n",
"from langchain.schema import HumanMessage"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "70cf04e8-423a-4ff6-8b09-f11fb711c817",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"chat = BedrockChat(model_id=\"anthropic.claude-v2\", model_kwargs={\"temperature\": 0.1})"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "8199ef8f-eb8b-4253-9ea0-6c24a013ca4c",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=\" Voici la traduction en français : J'adore programmer.\", additional_kwargs={}, example=False)"
]
},
"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": "a4a4f4d4",
"metadata": {},
"source": [
"### For BedrockChat with Streaming"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c253883f",
"metadata": {},
"outputs": [],
"source": [
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"\n",
"chat = BedrockChat(\n",
" model_id=\"anthropic.claude-v2\",\n",
" streaming=True,\n",
" callbacks=[StreamingStdOutCallbackHandler()],\n",
" model_kwargs={\"temperature\": 0.1},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d9e52838",
"metadata": {},
"outputs": [],
"source": [
"messages = [\n",
" HumanMessage(\n",
" content=\"Translate this sentence from English to French. I love programming.\"\n",
" )\n",
"]\n",
"chat(messages)"
]
}
],
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -55,11 +55,7 @@
}
],
"source": [
"messages = [\n",
" HumanMessage(\n",
" content=\"knock knock\"\n",
" )\n",
"]\n",
"messages = [HumanMessage(content=\"knock knock\")]\n",
"chat(messages)"
]
},

View File

@@ -26,7 +26,9 @@
"metadata": {},
"outputs": [],
"source": [
"chat = ErnieBotChat(ernie_client_id='YOUR_CLIENT_ID', ernie_client_secret='YOUR_CLIENT_SECRET')"
"chat = ErnieBotChat(\n",
" ernie_client_id=\"YOUR_CLIENT_ID\", ernie_client_secret=\"YOUR_CLIENT_SECRET\"\n",
")"
]
},
{
@@ -57,9 +59,7 @@
}
],
"source": [
"chat([\n",
" HumanMessage(content='hello there, who are you?')\n",
"])"
"chat([HumanMessage(content=\"hello there, who are you?\")])"
]
}
],

View File

@@ -67,15 +67,15 @@
"from langchain.schema import SystemMessage, HumanMessage\n",
"\n",
"messages = [\n",
" SystemMessage(\n",
" content=\"You are a helpful AI that shares everything you know.\"\n",
" ),\n",
" SystemMessage(content=\"You are a helpful AI that shares everything you know.\"),\n",
" HumanMessage(\n",
" content=\"Tell me technical facts about yourself. Are you a transformer model? How many billions of parameters do you have?\"\n",
" ),\n",
"]\n",
"\n",
"chat = ChatEverlyAI(model_name=\"meta-llama/Llama-2-7b-chat-hf\", temperature=0.3, max_tokens=64)\n",
"chat = ChatEverlyAI(\n",
" model_name=\"meta-llama/Llama-2-7b-chat-hf\", temperature=0.3, max_tokens=64\n",
")\n",
"print(chat(messages).content)"
]
},
@@ -121,15 +121,17 @@
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"\n",
"messages = [\n",
" SystemMessage(\n",
" content=\"You are a humorous AI that delights people.\"\n",
" ),\n",
" HumanMessage(\n",
" content=\"Tell me a joke?\"\n",
" ),\n",
" SystemMessage(content=\"You are a humorous AI that delights people.\"),\n",
" HumanMessage(content=\"Tell me a joke?\"),\n",
"]\n",
"\n",
"chat = ChatEverlyAI(model_name=\"meta-llama/Llama-2-7b-chat-hf\", temperature=0.3, max_tokens=64, streaming=True, callbacks=[StreamingStdOutCallbackHandler()])\n",
"chat = ChatEverlyAI(\n",
" model_name=\"meta-llama/Llama-2-7b-chat-hf\",\n",
" temperature=0.3,\n",
" max_tokens=64,\n",
" streaming=True,\n",
" callbacks=[StreamingStdOutCallbackHandler()],\n",
")\n",
"chat(messages)"
]
},
@@ -177,15 +179,17 @@
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"\n",
"messages = [\n",
" SystemMessage(\n",
" content=\"You are a humorous AI that delights people.\"\n",
" ),\n",
" HumanMessage(\n",
" content=\"Tell me a joke?\"\n",
" ),\n",
" SystemMessage(content=\"You are a humorous AI that delights people.\"),\n",
" HumanMessage(content=\"Tell me a joke?\"),\n",
"]\n",
"\n",
"chat = ChatEverlyAI(model_name=\"meta-llama/Llama-2-13b-chat-hf-quantized\", temperature=0.3, max_tokens=128, streaming=True, callbacks=[StreamingStdOutCallbackHandler()])\n",
"chat = ChatEverlyAI(\n",
" model_name=\"meta-llama/Llama-2-13b-chat-hf-quantized\",\n",
" temperature=0.3,\n",
" max_tokens=128,\n",
" streaming=True,\n",
" callbacks=[StreamingStdOutCallbackHandler()],\n",
")\n",
"chat(messages)"
]
}

View File

@@ -27,7 +27,7 @@
"source": [
"from langchain.chat_models.fireworks import ChatFireworks\n",
"from langchain.schema import SystemMessage, HumanMessage\n",
"import os\n"
"import os"
]
},
{
@@ -56,7 +56,7 @@
" os.environ[\"FIREWORKS_API_KEY\"] = getpass.getpass(\"Fireworks API Key:\")\n",
"\n",
"# Initialize a Fireworks chat model\n",
"chat = ChatFireworks(model=\"accounts/fireworks/models/llama-v2-13b-chat\")\n"
"chat = ChatFireworks(model=\"accounts/fireworks/models/llama-v2-13b-chat\")"
]
},
{
@@ -91,7 +91,7 @@
"system_message = SystemMessage(content=\"You are to chat with the user.\")\n",
"human_message = HumanMessage(content=\"Who are you?\")\n",
"\n",
"chat([system_message, human_message])\n"
"chat([system_message, human_message])"
]
},
{
@@ -113,10 +113,13 @@
],
"source": [
"# Setting additional parameters: temperature, max_tokens, top_p\n",
"chat = ChatFireworks(model=\"accounts/fireworks/models/llama-v2-13b-chat\", model_kwargs={\"temperature\":1, \"max_tokens\": 20, \"top_p\": 1})\n",
"chat = ChatFireworks(\n",
" model=\"accounts/fireworks/models/llama-v2-13b-chat\",\n",
" model_kwargs={\"temperature\": 1, \"max_tokens\": 20, \"top_p\": 1},\n",
")\n",
"system_message = SystemMessage(content=\"You are to chat with the user.\")\n",
"human_message = HumanMessage(content=\"How's the weather today?\")\n",
"chat([system_message, human_message])\n"
"chat([system_message, human_message])"
]
},
{
@@ -147,12 +150,17 @@
"from langchain.schema.runnable import RunnablePassthrough\n",
"from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
"\n",
"llm = ChatFireworks(model=\"accounts/fireworks/models/llama-v2-13b-chat\", model_kwargs={\"temperature\":0, \"max_tokens\":64, \"top_p\":1.0})\n",
"prompt = ChatPromptTemplate.from_messages([\n",
" (\"system\", \"You are a helpful chatbot that speaks like a pirate.\"),\n",
" MessagesPlaceholder(variable_name=\"history\"),\n",
" (\"human\", \"{input}\")\n",
"])\n"
"llm = ChatFireworks(\n",
" model=\"accounts/fireworks/models/llama-v2-13b-chat\",\n",
" model_kwargs={\"temperature\": 0, \"max_tokens\": 64, \"top_p\": 1.0},\n",
")\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\"system\", \"You are a helpful chatbot that speaks like a pirate.\"),\n",
" MessagesPlaceholder(variable_name=\"history\"),\n",
" (\"human\", \"{input}\"),\n",
" ]\n",
")"
]
},
{
@@ -182,7 +190,7 @@
],
"source": [
"memory = ConversationBufferMemory(return_messages=True)\n",
"memory.load_memory_variables({})\n"
"memory.load_memory_variables({})"
]
},
{
@@ -200,9 +208,13 @@
"metadata": {},
"outputs": [],
"source": [
"chain = RunnablePassthrough.assign(\n",
" history=memory.load_memory_variables | (lambda x: x[\"history\"])\n",
") | prompt | llm.bind(stop=[\"\\n\\n\"])\n"
"chain = (\n",
" RunnablePassthrough.assign(\n",
" history=memory.load_memory_variables | (lambda x: x[\"history\"])\n",
" )\n",
" | prompt\n",
" | llm.bind(stop=[\"\\n\\n\"])\n",
")"
]
},
{
@@ -233,7 +245,7 @@
"source": [
"inputs = {\"input\": \"hi im bob\"}\n",
"response = chain.invoke(inputs)\n",
"response\n"
"response"
]
},
{
@@ -264,7 +276,7 @@
],
"source": [
"memory.save_context(inputs, {\"output\": response.content})\n",
"memory.load_memory_variables({})\n"
"memory.load_memory_variables({})"
]
},
{
@@ -294,7 +306,7 @@
],
"source": [
"inputs = {\"input\": \"whats my name\"}\n",
"chain.invoke(inputs)\n"
"chain.invoke(inputs)"
]
}
],

View File

@@ -40,7 +40,7 @@
"import os\n",
"from getpass import getpass\n",
"\n",
"os.environ['GIGACHAT_CREDENTIALS'] = getpass()"
"os.environ[\"GIGACHAT_CREDENTIALS\"] = getpass()"
],
"metadata": {
"collapsed": false
@@ -78,9 +78,7 @@
" SystemMessage(\n",
" content=\"You are a helpful AI that shares everything you know. Talk in English.\"\n",
" ),\n",
" HumanMessage(\n",
" content=\"Tell me a joke\"\n",
" ),\n",
" HumanMessage(content=\"Tell me a joke\"),\n",
"]\n",
"\n",
"print(chat(messages).content)"

View File

@@ -9,9 +9,9 @@
"\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",
"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",
"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 Vertex AI PaLM you must have the `google-cloud-aiplatform` Python package installed and either:\n",
"To use `Google Cloud Vertex AI` PaLM you must have the `google-cloud-aiplatform` Python package installed and either:\n",
"- Have credentials configured for your environment (gcloud, workload identity, etc...)\n",
"- Store the path to a service account JSON file as the GOOGLE_APPLICATION_CREDENTIALS environment variable\n",
"\n",
@@ -31,7 +31,7 @@
},
"outputs": [],
"source": [
"#!pip install langchain google-cloud-aiplatform\n"
"#!pip install langchain google-cloud-aiplatform"
]
},
{
@@ -41,7 +41,7 @@
"outputs": [],
"source": [
"from langchain.chat_models import ChatVertexAI\n",
"from langchain.prompts import ChatPromptTemplate\n"
"from langchain.prompts import ChatPromptTemplate"
]
},
{
@@ -50,7 +50,7 @@
"metadata": {},
"outputs": [],
"source": [
"chat = ChatVertexAI()\n"
"chat = ChatVertexAI()"
]
},
{
@@ -61,10 +61,8 @@
"source": [
"system = \"You are a helpful assistant who translate English to French\"\n",
"human = \"Translate this sentence from English to French. I love programming.\"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", system), (\"human\", human)]\n",
")\n",
"messages = prompt.format_messages()\n"
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n",
"messages = prompt.format_messages()"
]
},
{
@@ -84,7 +82,7 @@
}
],
"source": [
"chat(messages)\n"
"chat(messages)"
]
},
{
@@ -100,11 +98,11 @@
"metadata": {},
"outputs": [],
"source": [
"system = \"You are a helpful assistant that translates {input_language} to {output_language}.\"\n",
"system = (\n",
" \"You are a helpful assistant that translates {input_language} to {output_language}.\"\n",
")\n",
"human = \"{text}\"\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"system\", system), (\"human\", human)]\n",
")\n"
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])"
]
},
{
@@ -126,8 +124,12 @@
"source": [
"chain = prompt | chat\n",
"chain.invoke(\n",
" {\"input_language\": \"English\", \"output_language\": \"Japanese\", \"text\": \"I love programming\"}\n",
")\n"
" {\n",
" \"input_language\": \"English\",\n",
" \"output_language\": \"Japanese\",\n",
" \"text\": \"I love programming\",\n",
" }\n",
")"
]
},
{
@@ -158,10 +160,8 @@
"outputs": [],
"source": [
"chat = ChatVertexAI(\n",
" model_name=\"codechat-bison\",\n",
" max_output_tokens=1000,\n",
" temperature=0.5\n",
")\n"
" model_name=\"codechat-bison\", max_output_tokens=1000, temperature=0.5\n",
")"
]
},
{
@@ -189,7 +189,7 @@
],
"source": [
"# For simple string in string out usage, we can use the `predict` method:\n",
"print(chat.predict(\"Write a Python function to identify all prime numbers\"))\n"
"print(chat.predict(\"Write a Python function to identify all prime numbers\"))"
]
},
{
@@ -208,8 +208,9 @@
"outputs": [],
"source": [
"import asyncio\n",
"\n",
"# import nest_asyncio\n",
"# nest_asyncio.apply()\n"
"# nest_asyncio.apply()"
]
},
{
@@ -237,7 +238,7 @@
" top_k=40,\n",
")\n",
"\n",
"asyncio.run(chat.agenerate([messages]))\n"
"asyncio.run(chat.agenerate([messages]))"
]
},
{
@@ -257,7 +258,15 @@
}
],
"source": [
"asyncio.run(chain.ainvoke({\"input_language\": \"English\", \"output_language\": \"Sanskrit\", \"text\": \"I love programming\"}))\n"
"asyncio.run(\n",
" chain.ainvoke(\n",
" {\n",
" \"input_language\": \"English\",\n",
" \"output_language\": \"Sanskrit\",\n",
" \"text\": \"I love programming\",\n",
" }\n",
" )\n",
")"
]
},
{
@@ -275,7 +284,7 @@
"metadata": {},
"outputs": [],
"source": [
"import sys\n"
"import sys"
]
},
{
@@ -306,11 +315,13 @@
}
],
"source": [
"prompt = ChatPromptTemplate.from_messages([(\"human\", \"List out the 15 most populous countries in the world\")])\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"human\", \"List out the 15 most populous countries in the world\")]\n",
")\n",
"messages = prompt.format_messages()\n",
"for chunk in chat.stream(messages):\n",
" sys.stdout.write(chunk.content)\n",
" sys.stdout.flush()\n"
" sys.stdout.flush()"
]
}
],

View File

@@ -36,9 +36,9 @@
"outputs": [],
"source": [
"chat = ChatHunyuan(\n",
" hunyuan_app_id='YOUR_APP_ID',\n",
" hunyuan_secret_id='YOUR_SECRET_ID',\n",
" hunyuan_secret_key='YOUR_SECRET_KEY',\n",
" hunyuan_app_id=\"YOUR_APP_ID\",\n",
" hunyuan_secret_id=\"YOUR_SECRET_ID\",\n",
" hunyuan_secret_key=\"YOUR_SECRET_KEY\",\n",
")"
]
},
@@ -62,9 +62,13 @@
}
],
"source": [
"chat([\n",
" HumanMessage(content='You are a helpful assistant that translates English to French.Translate this sentence from English to French. I love programming.')\n",
"])"
"chat(\n",
" [\n",
" HumanMessage(\n",
" content=\"You are a helpful assistant that translates English to French.Translate this sentence from English to French. I love programming.\"\n",
" )\n",
" ]\n",
")"
]
},
{
@@ -82,9 +86,9 @@
"outputs": [],
"source": [
"chat = ChatHunyuan(\n",
" hunyuan_app_id='YOUR_APP_ID',\n",
" hunyuan_secret_id='YOUR_SECRET_ID',\n",
" hunyuan_secret_key='YOUR_SECRET_KEY',\n",
" hunyuan_app_id=\"YOUR_APP_ID\",\n",
" hunyuan_secret_id=\"YOUR_SECRET_ID\",\n",
" hunyuan_secret_key=\"YOUR_SECRET_KEY\",\n",
" streaming=True,\n",
")"
],
@@ -110,9 +114,13 @@
}
],
"source": [
"chat([\n",
" HumanMessage(content='You are a helpful assistant that translates English to French.Translate this sentence from English to French. I love programming.')\n",
"])"
"chat(\n",
" [\n",
" HumanMessage(\n",
" content=\"You are a helpful assistant that translates English to French.Translate this sentence from English to French. I love programming.\"\n",
" )\n",
" ]\n",
")"
],
"metadata": {
"collapsed": false,

View File

@@ -96,7 +96,7 @@
"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-hf\")"
]
},
{
@@ -117,12 +117,8 @@
],
"source": [
"messages = [\n",
" SystemMessage(\n",
" content=\"You are a helpful assistant.\"\n",
" ),\n",
" HumanMessage(\n",
" content=\"Explain Big Bang Theory briefly\"\n",
" ),\n",
" SystemMessage(content=\"You are a helpful assistant.\"),\n",
" HumanMessage(content=\"Explain Big Bang Theory briefly\"),\n",
"]\n",
"chat(messages)"
]

View File

@@ -28,7 +28,7 @@
"from llamaapi import LlamaAPI\n",
"\n",
"# Replace 'Your_API_Token' with your actual API token\n",
"llama = LlamaAPI('Your_API_Token')"
"llama = LlamaAPI(\"Your_API_Token\")"
]
},
{
@@ -71,9 +71,15 @@
"\n",
"schema = {\n",
" \"properties\": {\n",
" \"sentiment\": {\"type\": \"string\", 'description': 'the sentiment encountered in the passage'},\n",
" \"aggressiveness\": {\"type\": \"integer\", 'description': 'a 0-10 score of how aggressive the passage is'},\n",
" \"language\": {\"type\": \"string\", 'description': 'the language of the passage'},\n",
" \"sentiment\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"the sentiment encountered in the passage\",\n",
" },\n",
" \"aggressiveness\": {\n",
" \"type\": \"integer\",\n",
" \"description\": \"a 0-10 score of how aggressive the passage is\",\n",
" },\n",
" \"language\": {\"type\": \"string\", \"description\": \"the language of the passage\"},\n",
" }\n",
"}\n",
"\n",

View File

@@ -61,9 +61,12 @@
"source": [
"from langchain.chat_models import ChatOllama\n",
"from langchain.callbacks.manager import CallbackManager\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler \n",
"chat_model = ChatOllama(model=\"llama2:7b-chat\", \n",
" callback_manager = CallbackManager([StreamingStdOutCallbackHandler()]))"
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"\n",
"chat_model = ChatOllama(\n",
" model=\"llama2:7b-chat\",\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),\n",
")"
]
},
{
@@ -112,9 +115,7 @@
"source": [
"from langchain.schema import HumanMessage\n",
"\n",
"messages = [\n",
" HumanMessage(content=\"Tell me about the history of AI\")\n",
"]\n",
"messages = [HumanMessage(content=\"Tell me about the history of AI\")]\n",
"chat_model(messages)"
]
},
@@ -151,10 +152,12 @@
"outputs": [],
"source": [
"from langchain.document_loaders import WebBaseLoader\n",
"\n",
"loader = WebBaseLoader(\"https://lilianweng.github.io/posts/2023-06-23-agent/\")\n",
"data = loader.load()\n",
"\n",
"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)"
]
@@ -224,9 +227,12 @@
"from langchain.chat_models import ChatOllama\n",
"from langchain.callbacks.manager import CallbackManager\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"chat_model = ChatOllama(model=\"llama2:13b\",\n",
" verbose=True,\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]))"
"\n",
"chat_model = ChatOllama(\n",
" model=\"llama2:13b\",\n",
" verbose=True,\n",
" callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),\n",
")"
]
},
{
@@ -237,6 +243,7 @@
"source": [
"# QA chain\n",
"from langchain.chains import RetrievalQA\n",
"\n",
"qa_chain = RetrievalQA.from_chain_type(\n",
" chat_model,\n",
" retriever=vectorstore.as_retriever(),\n",
@@ -296,15 +303,19 @@
"from langchain.schema import LLMResult\n",
"from langchain.callbacks.base import BaseCallbackHandler\n",
"\n",
"\n",
"class GenerationStatisticsCallback(BaseCallbackHandler):\n",
" def on_llm_end(self, response: LLMResult, **kwargs) -> None:\n",
" print(response.generations[0][0].generation_info)\n",
" \n",
"callback_manager = CallbackManager([StreamingStdOutCallbackHandler(), GenerationStatisticsCallback()])\n",
"\n",
"chat_model = ChatOllama(model=\"llama2:13b-chat\",\n",
" verbose=True,\n",
" callback_manager=callback_manager)\n",
"\n",
"callback_manager = CallbackManager(\n",
" [StreamingStdOutCallbackHandler(), GenerationStatisticsCallback()]\n",
")\n",
"\n",
"chat_model = ChatOllama(\n",
" model=\"llama2:13b-chat\", verbose=True, callback_manager=callback_manager\n",
")\n",
"\n",
"qa_chain = RetrievalQA.from_chain_type(\n",
" chat_model,\n",
@@ -340,7 +351,7 @@
}
],
"source": [
"98 / (3229641000/1000/1000/1000)"
"98 / (3229641000 / 1000 / 1000 / 1000)"
]
}
],

View File

@@ -172,7 +172,9 @@
}
],
"source": [
"fine_tuned_model = ChatOpenAI(temperature=0, model_name=\"ft:gpt-3.5-turbo-0613:langchain::7qTVM5AR\")\n",
"fine_tuned_model = ChatOpenAI(\n",
" temperature=0, model_name=\"ft:gpt-3.5-turbo-0613:langchain::7qTVM5AR\"\n",
")\n",
"\n",
"fine_tuned_model(messages)"
]

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