From 705431aeccc1a34d7510d02a4c9ca1e95888a878 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Sun, 26 Mar 2023 19:49:46 -0700 Subject: [PATCH] big docs refactor (#1978) Co-authored-by: Ankush Gola --- docs/ecosystem/atlas.md | 2 +- docs/ecosystem/chroma.md | 2 +- docs/ecosystem/cohere.md | 2 +- docs/ecosystem/deeplake.md | 2 +- docs/ecosystem/google_search.md | 4 +- docs/ecosystem/google_serper.md | 4 +- docs/ecosystem/huggingface.md | 6 +- docs/ecosystem/milvus.md | 2 +- docs/ecosystem/openai.md | 6 +- docs/ecosystem/opensearch.md | 2 +- docs/ecosystem/pgvector.md | 2 +- docs/ecosystem/pinecone.md | 2 +- docs/ecosystem/promptlayer.md | 2 +- docs/ecosystem/qdrant.md | 2 +- docs/ecosystem/runhouse.md | 4 +- docs/ecosystem/searx.md | 2 +- docs/ecosystem/serpapi.md | 4 +- docs/ecosystem/weaviate.md | 2 +- docs/ecosystem/wolfram_alpha.md | 4 +- docs/getting_started/getting_started.md | 221 ++++- docs/glossary.md | 4 +- docs/index.rst | 77 +- docs/{use_cases => }/model_laboratory.ipynb | 0 docs/modules/agents.rst | 46 +- docs/modules/agents/agent_executors.rst | 17 + .../examples/agent_vectorstore.ipynb | 24 +- .../examples/async_agent.ipynb | 4 +- .../examples/chatgpt_clone.ipynb | 2 +- .../examples/intermediate_steps.ipynb | 2 +- .../examples/max_iterations.ipynb | 2 +- .../examples/sharedmemory_for_tools.ipynb | 8 +- docs/modules/agents/agents.rst | 35 + .../{agents.md => agents/agent_types.md} | 5 +- .../{examples => agents}/custom_agent.ipynb | 0 .../examples/chat_conversation_agent.ipynb | 0 .../examples/conversational_agent.ipynb | 0 .../examples}/mrkl.ipynb | 0 .../examples}/mrkl_chat.ipynb | 0 .../examples}/react.ipynb | 0 .../examples}/self_ask_with_search.ipynb | 0 .../agents/examples/load_from_hub.ipynb | 131 --- .../agents/examples/serialization.ipynb | 154 --- docs/modules/agents/implementations/natbot.py | 87 -- docs/modules/agents/key_concepts.md | 16 - docs/modules/agents/toolkits.rst | 18 + .../examples}/csv.ipynb | 0 .../examples}/json.ipynb | 0 .../examples}/openai_openapi.yml | 0 .../examples}/openapi.ipynb | 0 .../examples}/pandas.ipynb | 0 .../examples}/python.ipynb | 2 +- .../examples}/sql_database.ipynb | 0 .../examples}/titanic.csv | 0 .../examples}/vectorstore.ipynb | 6 +- docs/modules/agents/tools.rst | 38 + .../{examples => tools}/custom_tools.ipynb | 0 .../tools}/examples/bash.ipynb | 0 .../tools}/examples/bing_search.ipynb | 0 .../examples/chatgpt_plugins.ipynb | 19 +- .../tools}/examples/google_search.ipynb | 0 .../tools}/examples/google_serper.ipynb | 0 .../{ => tools}/examples/human_tools.ipynb | 0 .../tools}/examples/ifttt.ipynb | 8 +- .../tools}/examples/python.ipynb | 0 .../tools}/examples/requests.ipynb | 0 .../{ => tools}/examples/search_tools.ipynb | 0 .../tools}/examples/searx_search.ipynb | 14 +- .../tools}/examples/serpapi.ipynb | 0 .../tools}/examples/wolfram_alpha.ipynb | 0 .../tools}/examples/zapier.ipynb | 4 +- .../{tools.md => tools/getting_started.md} | 6 +- .../multi_input_tool.ipynb | 0 docs/modules/chains.rst | 7 +- .../chains/{ => generic}/async_chain.ipynb | 0 docs/modules/chains/generic/from_hub.ipynb | 8 +- .../chains/generic/transformation.ipynb | 4 +- docs/modules/chains/generic_how_to.rst | 33 - docs/modules/chains/how_to_guides.rst | 38 +- .../index_examples}/analyze_document.ipynb | 4 +- .../index_examples}/chat_vector_db.ipynb | 2 +- .../index_examples}/graph_qa.ipynb | 0 .../index_examples}/hyde.ipynb | 7 +- .../index_examples}/qa_with_sources.ipynb | 2 +- .../index_examples}/question_answering.ipynb | 2 +- .../index_examples}/summarize.ipynb | 2 +- .../index_examples}/vector_db_qa.ipynb | 2 +- .../vector_db_qa_with_sources.ipynb | 2 +- .../vector_db_text_generation.ipynb | 0 docs/modules/chains/key_concepts.md | 20 - docs/modules/chains/utility_how_to.rst | 65 -- docs/modules/chat/examples/agent.ipynb | 208 ---- .../chat/examples/chat_vector_db.ipynb | 376 -------- docs/modules/chat/examples/memory.ipynb | 192 ---- docs/modules/chat/examples/vector_db_qa.ipynb | 169 ---- .../examples/vector_db_qa_with_sources.ipynb | 206 ---- docs/modules/chat/key_concepts.md | 29 - .../document_loaders/how_to_guides.rst | 87 -- docs/modules/document_loaders/key_concepts.md | 12 - docs/modules/indexes.rst | 44 +- docs/modules/indexes/combine_docs.md | 51 - .../{ => indexes}/document_loaders.rst | 19 +- .../document_loaders/examples/CoNLL-U.ipynb | 0 .../examples/airbyte_json.ipynb | 0 .../document_loaders/examples/azlyrics.ipynb | 0 .../examples/blackboard.ipynb | 0 .../examples/college_confidential.ipynb | 0 .../document_loaders/examples/copypaste.ipynb | 0 .../document_loaders/examples/csv.ipynb | 0 .../examples/directory_loader.ipynb | 0 .../document_loaders/examples/email.ipynb | 0 .../document_loaders/examples/evernote.ipynb | 0 .../examples/example_data/conllu.conllu | 0 .../examples/example_data/facebook_chat.json | 0 .../examples/example_data/fake-content.html | 0 .../examples/example_data/fake-email.eml | 0 .../example_data/fake-power-point.pptx | Bin .../examples/example_data/fake.docx | Bin .../example_data/layout-parser-paper.pdf | Bin .../examples/example_data/mlb_teams_2012.csv | 0 .../examples/example_data/notebook.ipynb | 0 .../examples/example_data/telegram.json | 0 .../examples/example_data/testing.enex | 0 .../examples/facebook_chat.ipynb | 0 .../document_loaders/examples/figma.ipynb | 0 .../examples/gcs_directory.ipynb | 0 .../document_loaders/examples/gcs_file.ipynb | 0 .../document_loaders/examples/gitbook.ipynb | 0 .../examples/googledrive.ipynb | 0 .../document_loaders/examples/gutenberg.ipynb | 0 .../document_loaders/examples/hn.ipynb | 0 .../document_loaders/examples/html.ipynb | 0 .../document_loaders/examples/ifixit.ipynb | 0 .../document_loaders/examples/image.ipynb | 0 .../document_loaders/examples/imsdb.ipynb | 0 .../document_loaders/examples/markdown.ipynb | 0 .../document_loaders/examples/notebook.ipynb | 0 .../document_loaders/examples/notion.ipynb | 0 .../document_loaders/examples/obsidian.ipynb | 0 .../document_loaders/examples/pdf.ipynb | 0 .../examples/powerpoint.ipynb | 0 .../examples/readthedocs_documentation.ipynb | 0 .../document_loaders/examples/roam.ipynb | 0 .../examples/s3_directory.ipynb | 0 .../document_loaders/examples/s3_file.ipynb | 0 .../document_loaders/examples/srt.ipynb | 0 .../document_loaders/examples/telegram.ipynb | 0 .../examples/unstructured_file.ipynb | 16 +- .../document_loaders/examples/url.ipynb | 0 .../document_loaders/examples/web_base.ipynb | 0 .../examples/word_document.ipynb | 0 .../document_loaders/examples/youtube.ipynb | 0 .../modules/indexes/examples/embeddings.ipynb | 778 --------------- .../indexes/examples/textsplitter.ipynb | 826 ---------------- docs/modules/indexes/getting_started.ipynb | 2 +- docs/modules/indexes/how_to_guides.rst | 124 --- docs/modules/indexes/key_concepts.md | 27 - docs/modules/indexes/retrievers.rst | 19 + .../examples}/chatgpt-plugin-retriever.ipynb | 0 .../examples}/vectorstore-retriever.ipynb | 2 +- docs/modules/indexes/text_splitters.rst | 41 + .../examples/character_text_splitter.ipynb | 118 +++ .../huggingface_length_function.ipynb | 102 ++ .../text_splitters/examples/latex.ipynb | 115 +++ .../text_splitters/examples/markdown.ipynb | 110 +++ .../text_splitters/examples/nltk.ipynb | 116 +++ .../text_splitters/examples/python.ipynb | 108 +++ .../examples/recursive_text_splitter.ipynb | 101 ++ .../text_splitters/examples/spacy.ipynb | 138 +++ .../text_splitters/examples/tiktoken.ipynb | 90 ++ .../examples/tiktoken_splitter.ipynb | 102 ++ .../text_splitters/getting_started.ipynb | 103 ++ docs/modules/indexes/vectorstores.rst | 27 + .../examples}/atlas.ipynb | 14 +- .../examples}/chroma.ipynb | 2 +- .../examples}/deeplake.ipynb | 9 +- .../examples}/elasticsearch.ipynb | 2 +- .../examples}/faiss.ipynb | 2 +- .../examples}/milvus.ipynb | 2 +- .../examples}/opensearch.ipynb | 129 ++- .../examples}/pgvector.ipynb | 12 +- .../examples}/pinecone.ipynb | 2 +- .../examples}/qdrant.ipynb | 2 +- .../examples}/redis.ipynb | 76 +- .../examples}/weaviate.ipynb | 2 +- .../getting_started.ipynb} | 2 +- docs/modules/llms/generic_how_to.rst | 24 - docs/modules/llms/how_to_guides.rst | 21 - docs/modules/llms/integrations.rst | 50 - docs/modules/llms/key_concepts.md | 19 - docs/modules/memory.rst | 7 +- .../memory/examples/adding_memory.ipynb | 2 +- .../adding_memory_chain_multiple_inputs.ipynb | 2 +- .../memory/examples/agent_with_memory.ipynb | 2 +- .../conversational_customization.ipynb | 2 +- .../memory/examples/custom_memory.ipynb | 2 +- .../memory/examples/multiple_memory.ipynb | 2 +- docs/modules/memory/how_to_guides.rst | 31 - docs/modules/memory/key_concepts.md | 19 - docs/modules/models.rst | 40 + docs/modules/{ => models}/chat.rst | 16 +- .../chat/examples/few_shot_examples.ipynb | 2 +- .../chat/examples/streaming.ipynb | 2 +- .../{ => models}/chat/getting_started.ipynb | 0 .../{ => models}/chat/how_to_guides.rst | 0 docs/modules/models/chat/integrations.rst | 10 + .../chat/integrations/azure_chat_openai.ipynb | 94 ++ .../models/chat/integrations/openai.ipynb | 154 +++ .../promptlayer_chatopenai.ipynb | 0 docs/modules/{ => models}/llms.rst | 14 +- .../llms/examples}/async_llm.ipynb | 2 +- .../llms/examples/custom_llm.ipynb | 4 +- .../{ => models}/llms/examples/fake_llm.ipynb | 16 +- .../{ => models}/llms/examples/llm.json | 0 .../{ => models}/llms/examples/llm.yaml | 0 .../llms/examples/llm_caching.ipynb | 20 +- .../llms/examples/llm_serialization.ipynb | 4 +- .../llms/examples}/streaming_llm.ipynb | 4 +- .../llms/examples/token_usage_tracking.ipynb | 4 +- .../{ => models}/llms/getting_started.ipynb | 0 docs/modules/models/llms/how_to_guides.rst | 10 + docs/modules/models/llms/integrations.rst | 10 + .../{ => models}/llms/integrations/ai21.ipynb | 0 .../llms/integrations/aleph_alpha.ipynb | 0 .../llms/integrations/anthropic_example.ipynb | 0 .../integrations/azure_openai_example.ipynb | 0 .../llms/integrations/banana.ipynb | 0 .../integrations/cerebriumai_example.ipynb | 0 .../llms/integrations/cohere.ipynb | 0 .../llms/integrations/deepinfra_example.ipynb | 0 .../integrations/forefrontai_example.ipynb | 0 .../llms/integrations/gooseai_example.ipynb | 0 .../llms/integrations/huggingface_hub.ipynb | 0 .../llms/integrations/manifest.ipynb | 4 +- .../llms/integrations/modal.ipynb | 0 .../llms/integrations/openai.ipynb | 0 .../llms/integrations/petals_example.ipynb | 0 .../integrations/promptlayer_openai.ipynb | 0 .../llms/integrations/sagemaker.ipynb | 0 .../integrations/self_hosted_examples.ipynb | 0 .../llms/integrations/stochasticai.ipynb | 0 .../llms/integrations/writer.ipynb | 0 docs/modules/models/text_embedding.rst | 22 + .../text_embedding/examples/azureopenai.ipynb | 103 ++ .../text_embedding/examples/cohere.ipynb | 98 ++ .../models/text_embedding/examples/fake.ipynb | 80 ++ .../examples/huggingfacehub.ipynb | 97 ++ .../examples/instruct_embeddings.ipynb | 98 ++ .../text_embedding/examples/openai.ipynb | 156 +++ .../examples/sagemaker-endpoint.ipynb | 127 +++ .../text_embedding/examples/self-hosted.ipynb | 195 ++++ .../examples/tensorflowhub.ipynb | 118 +++ docs/modules/prompts.rst | 51 +- .../prompts/chat_prompt_template.ipynb | 128 +++ docs/modules/prompts/example_selectors.rst | 29 + .../examples/custom_example_selector.md | 4 +- .../examples/length_based.ipynb | 211 +++++ .../example_selectors/examples/mmr.ipynb | 162 ++++ .../examples/ngram_overlap.ipynb | 280 ++++++ .../examples/similarity.ipynb | 184 ++++ .../prompts/examples/example_selectors.ipynb | 711 -------------- .../prompts/examples/output_parsers.ipynb | 764 --------------- .../prompts/examples/prompt_management.ipynb | 886 ------------------ docs/modules/prompts/how_to_guides.rst | 35 - docs/modules/prompts/key_concepts.md | 75 -- docs/modules/prompts/output_parsers.rst | 32 + .../examples/comma_separated.ipynb | 127 +++ .../examples/output_fixing_parser.ipynb | 153 +++ .../output_parsers/examples/pydantic.ipynb | 163 ++++ .../output_parsers/examples/retry.ipynb | 227 +++++ .../output_parsers/examples/structured.ipynb | 209 +++++ .../output_parsers/getting_started.ipynb | 163 ++++ .../prompts/output_parsers/how_to_guides.rst | 8 + docs/modules/prompts/prompt_templates.rst | 30 + .../examples/custom_prompt_template.ipynb | 4 +- .../examples/example_prompt.json | 0 .../examples/examples.json | 0 .../examples/examples.yaml | 0 .../examples/few_shot_examples.ipynb | 2 +- .../examples/few_shot_prompt.json | 0 .../examples/few_shot_prompt.yaml | 0 .../few_shot_prompt_example_prompt.json | 0 .../examples/few_shot_prompt_examples_in.json | 0 .../few_shot_prompt_yaml_examples.yaml | 0 .../examples/partial.ipynb | 2 +- .../examples/prompt_serialization.ipynb | 4 +- .../examples/simple_prompt.json | 0 .../examples/simple_prompt.yaml | 0 .../simple_prompt_with_template_file.json | 0 .../examples/simple_template.txt | 0 .../{ => prompt_templates}/getting_started.md | 4 +- .../prompt_templates/how_to_guides.rst | 13 + docs/modules/utils.rst | 26 - docs/modules/utils/how_to_guides.rst | 30 - docs/modules/utils/key_concepts.md | 35 - docs/use_cases/agents.md | 12 - docs/use_cases/apis.md | 24 + docs/use_cases/chatbots.md | 10 +- docs/use_cases/combine_docs.md | 96 -- docs/use_cases/evaluation.rst | 4 + docs/use_cases/extraction.md | 6 +- docs/use_cases/generate_examples.ipynb | 157 ---- docs/use_cases/personal_assistants.md | 19 + docs/use_cases/question_answering.md | 9 +- docs/use_cases/summarization.md | 8 +- docs/use_cases/tabular.md | 14 +- tests/unit_tests/prompts/test_loading.py | 2 +- 306 files changed, 5689 insertions(+), 7029 deletions(-) rename docs/{use_cases => }/model_laboratory.ipynb (100%) create mode 100644 docs/modules/agents/agent_executors.rst rename docs/modules/agents/{ => agent_executors}/examples/agent_vectorstore.ipynb (96%) rename docs/modules/agents/{ => agent_executors}/examples/async_agent.ipynb (99%) rename docs/modules/{memory => agents/agent_executors}/examples/chatgpt_clone.ipynb (99%) rename docs/modules/agents/{ => agent_executors}/examples/intermediate_steps.ipynb (99%) rename docs/modules/agents/{ => agent_executors}/examples/max_iterations.ipynb (99%) rename docs/modules/agents/{ => agent_executors}/examples/sharedmemory_for_tools.ipynb (99%) create mode 100644 docs/modules/agents/agents.rst rename docs/modules/agents/{agents.md => agents/agent_types.md} (91%) rename docs/modules/agents/{examples => agents}/custom_agent.ipynb (100%) rename docs/modules/agents/{ => agents}/examples/chat_conversation_agent.ipynb (100%) rename docs/modules/{memory => agents/agents}/examples/conversational_agent.ipynb (100%) rename docs/modules/agents/{implementations => agents/examples}/mrkl.ipynb (100%) rename docs/modules/agents/{implementations => agents/examples}/mrkl_chat.ipynb (100%) rename docs/modules/agents/{implementations => agents/examples}/react.ipynb (100%) rename docs/modules/agents/{implementations => agents/examples}/self_ask_with_search.ipynb (100%) delete mode 100644 docs/modules/agents/examples/load_from_hub.ipynb delete mode 100644 docs/modules/agents/examples/serialization.ipynb delete mode 100644 docs/modules/agents/implementations/natbot.py delete mode 100644 docs/modules/agents/key_concepts.md create mode 100644 docs/modules/agents/toolkits.rst rename docs/modules/agents/{agent_toolkits => toolkits/examples}/csv.ipynb (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/json.ipynb (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/openai_openapi.yml (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/openapi.ipynb (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/pandas.ipynb (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/python.ipynb (99%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/sql_database.ipynb (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/titanic.csv (100%) rename docs/modules/agents/{agent_toolkits => toolkits/examples}/vectorstore.ipynb (99%) create mode 100644 docs/modules/agents/tools.rst rename docs/modules/agents/{examples => tools}/custom_tools.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/bash.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/bing_search.ipynb (100%) rename docs/modules/agents/{ => tools}/examples/chatgpt_plugins.ipynb (90%) rename docs/modules/{utils => agents/tools}/examples/google_search.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/google_serper.ipynb (100%) rename docs/modules/agents/{ => tools}/examples/human_tools.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/ifttt.ipynb (96%) rename docs/modules/{utils => agents/tools}/examples/python.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/requests.ipynb (100%) rename docs/modules/agents/{ => tools}/examples/search_tools.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/searx_search.ipynb (99%) rename docs/modules/{utils => agents/tools}/examples/serpapi.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/wolfram_alpha.ipynb (100%) rename docs/modules/{utils => agents/tools}/examples/zapier.ipynb (99%) rename docs/modules/agents/{tools.md => tools/getting_started.md} (97%) rename docs/modules/agents/{examples => tools}/multi_input_tool.ipynb (100%) rename docs/modules/chains/{ => generic}/async_chain.ipynb (100%) delete mode 100644 docs/modules/chains/generic_how_to.rst rename docs/modules/{indexes/chain_examples => chains/index_examples}/analyze_document.ipynb (98%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/chat_vector_db.ipynb (99%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/graph_qa.ipynb (100%) rename docs/modules/{indexes/examples => chains/index_examples}/hyde.ipynb (97%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/qa_with_sources.ipynb (99%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/question_answering.ipynb (99%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/summarize.ipynb (99%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/vector_db_qa.ipynb (99%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/vector_db_qa_with_sources.ipynb (99%) rename docs/modules/{indexes/chain_examples => chains/index_examples}/vector_db_text_generation.ipynb (100%) delete mode 100644 docs/modules/chains/key_concepts.md delete mode 100644 docs/modules/chains/utility_how_to.rst delete mode 100644 docs/modules/chat/examples/agent.ipynb delete mode 100644 docs/modules/chat/examples/chat_vector_db.ipynb delete mode 100644 docs/modules/chat/examples/memory.ipynb delete mode 100644 docs/modules/chat/examples/vector_db_qa.ipynb delete mode 100644 docs/modules/chat/examples/vector_db_qa_with_sources.ipynb delete mode 100644 docs/modules/chat/key_concepts.md delete mode 100644 docs/modules/document_loaders/how_to_guides.rst delete mode 100644 docs/modules/document_loaders/key_concepts.md delete mode 100644 docs/modules/indexes/combine_docs.md rename docs/modules/{ => indexes}/document_loaders.rst (60%) rename docs/modules/{ => indexes}/document_loaders/examples/CoNLL-U.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/airbyte_json.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/azlyrics.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/blackboard.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/college_confidential.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/copypaste.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/csv.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/directory_loader.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/email.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/evernote.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/conllu.conllu (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/facebook_chat.json (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/fake-content.html (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/fake-email.eml (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/fake-power-point.pptx (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/fake.docx (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/layout-parser-paper.pdf (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/mlb_teams_2012.csv (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/notebook.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/telegram.json (100%) rename docs/modules/{ => indexes}/document_loaders/examples/example_data/testing.enex (100%) rename docs/modules/{ => indexes}/document_loaders/examples/facebook_chat.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/figma.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/gcs_directory.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/gcs_file.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/gitbook.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/googledrive.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/gutenberg.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/hn.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/html.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/ifixit.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/image.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/imsdb.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/markdown.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/notebook.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/notion.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/obsidian.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/pdf.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/powerpoint.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/readthedocs_documentation.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/roam.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/s3_directory.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/s3_file.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/srt.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/telegram.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/unstructured_file.ipynb (96%) rename docs/modules/{ => indexes}/document_loaders/examples/url.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/web_base.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/word_document.ipynb (100%) rename docs/modules/{ => indexes}/document_loaders/examples/youtube.ipynb (100%) delete mode 100644 docs/modules/indexes/examples/embeddings.ipynb delete mode 100644 docs/modules/indexes/examples/textsplitter.ipynb delete mode 100644 docs/modules/indexes/how_to_guides.rst delete mode 100644 docs/modules/indexes/key_concepts.md create mode 100644 docs/modules/indexes/retrievers.rst rename docs/modules/indexes/{retriever_examples => retrievers/examples}/chatgpt-plugin-retriever.ipynb (100%) rename docs/modules/indexes/{retriever_examples => retrievers/examples}/vectorstore-retriever.ipynb (97%) create mode 100644 docs/modules/indexes/text_splitters.rst create mode 100644 docs/modules/indexes/text_splitters/examples/character_text_splitter.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/huggingface_length_function.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/latex.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/markdown.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/nltk.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/python.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/recursive_text_splitter.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/spacy.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/tiktoken.ipynb create mode 100644 docs/modules/indexes/text_splitters/examples/tiktoken_splitter.ipynb create mode 100644 docs/modules/indexes/text_splitters/getting_started.ipynb create mode 100644 docs/modules/indexes/vectorstores.rst rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/atlas.ipynb (97%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/chroma.ipynb (99%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/deeplake.ipynb (97%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/elasticsearch.ipynb (98%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/faiss.ipynb (99%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/milvus.ipynb (97%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/opensearch.ipynb (91%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/pgvector.ipynb (97%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/pinecone.ipynb (97%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/qdrant.ipynb (97%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/redis.ipynb (84%) rename docs/modules/indexes/{vectorstore_examples => vectorstores/examples}/weaviate.ipynb (98%) rename docs/modules/indexes/{examples/vectorstores.ipynb => vectorstores/getting_started.ipynb} (99%) delete mode 100644 docs/modules/llms/generic_how_to.rst delete mode 100644 docs/modules/llms/how_to_guides.rst delete mode 100644 docs/modules/llms/integrations.rst delete mode 100644 docs/modules/llms/key_concepts.md delete mode 100644 docs/modules/memory/key_concepts.md create mode 100644 docs/modules/models.rst rename docs/modules/{ => models}/chat.rst (65%) rename docs/modules/{ => models}/chat/examples/few_shot_examples.ipynb (99%) rename docs/modules/{ => models}/chat/examples/streaming.ipynb (98%) rename docs/modules/{ => models}/chat/getting_started.ipynb (100%) rename docs/modules/{ => models}/chat/how_to_guides.rst (100%) create mode 100644 docs/modules/models/chat/integrations.rst create mode 100644 docs/modules/models/chat/integrations/azure_chat_openai.ipynb create mode 100644 docs/modules/models/chat/integrations/openai.ipynb rename docs/modules/{chat/examples => models/chat/integrations}/promptlayer_chatopenai.ipynb (100%) rename docs/modules/{ => models}/llms.rst (57%) rename docs/modules/{llms => models/llms/examples}/async_llm.ipynb (98%) rename docs/modules/{ => models}/llms/examples/custom_llm.ipynb (98%) rename docs/modules/{ => models}/llms/examples/fake_llm.ipynb (87%) rename docs/modules/{ => models}/llms/examples/llm.json (100%) rename docs/modules/{ => models}/llms/examples/llm.yaml (100%) rename docs/modules/{ => models}/llms/examples/llm_caching.ipynb (98%) rename docs/modules/{ => models}/llms/examples/llm_serialization.ipynb (98%) rename docs/modules/{llms => models/llms/examples}/streaming_llm.ipynb (99%) rename docs/modules/{ => models}/llms/examples/token_usage_tracking.ipynb (98%) rename docs/modules/{ => models}/llms/getting_started.ipynb (100%) create mode 100644 docs/modules/models/llms/how_to_guides.rst create mode 100644 docs/modules/models/llms/integrations.rst rename docs/modules/{ => models}/llms/integrations/ai21.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/aleph_alpha.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/anthropic_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/azure_openai_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/banana.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/cerebriumai_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/cohere.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/deepinfra_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/forefrontai_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/gooseai_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/huggingface_hub.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/manifest.ipynb (98%) rename docs/modules/{ => models}/llms/integrations/modal.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/openai.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/petals_example.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/promptlayer_openai.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/sagemaker.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/self_hosted_examples.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/stochasticai.ipynb (100%) rename docs/modules/{ => models}/llms/integrations/writer.ipynb (100%) create mode 100644 docs/modules/models/text_embedding.rst create mode 100644 docs/modules/models/text_embedding/examples/azureopenai.ipynb create mode 100644 docs/modules/models/text_embedding/examples/cohere.ipynb create mode 100644 docs/modules/models/text_embedding/examples/fake.ipynb create mode 100644 docs/modules/models/text_embedding/examples/huggingfacehub.ipynb create mode 100644 docs/modules/models/text_embedding/examples/instruct_embeddings.ipynb create mode 100644 docs/modules/models/text_embedding/examples/openai.ipynb create mode 100644 docs/modules/models/text_embedding/examples/sagemaker-endpoint.ipynb create mode 100644 docs/modules/models/text_embedding/examples/self-hosted.ipynb create mode 100644 docs/modules/models/text_embedding/examples/tensorflowhub.ipynb create mode 100644 docs/modules/prompts/chat_prompt_template.ipynb create mode 100644 docs/modules/prompts/example_selectors.rst rename docs/modules/prompts/{ => example_selectors}/examples/custom_example_selector.md (94%) create mode 100644 docs/modules/prompts/example_selectors/examples/length_based.ipynb create mode 100644 docs/modules/prompts/example_selectors/examples/mmr.ipynb create mode 100644 docs/modules/prompts/example_selectors/examples/ngram_overlap.ipynb create mode 100644 docs/modules/prompts/example_selectors/examples/similarity.ipynb delete mode 100644 docs/modules/prompts/examples/example_selectors.ipynb delete mode 100644 docs/modules/prompts/examples/output_parsers.ipynb delete mode 100644 docs/modules/prompts/examples/prompt_management.ipynb delete mode 100644 docs/modules/prompts/how_to_guides.rst delete mode 100644 docs/modules/prompts/key_concepts.md create mode 100644 docs/modules/prompts/output_parsers.rst create mode 100644 docs/modules/prompts/output_parsers/examples/comma_separated.ipynb create mode 100644 docs/modules/prompts/output_parsers/examples/output_fixing_parser.ipynb create mode 100644 docs/modules/prompts/output_parsers/examples/pydantic.ipynb create mode 100644 docs/modules/prompts/output_parsers/examples/retry.ipynb create mode 100644 docs/modules/prompts/output_parsers/examples/structured.ipynb create mode 100644 docs/modules/prompts/output_parsers/getting_started.ipynb create mode 100644 docs/modules/prompts/output_parsers/how_to_guides.rst create mode 100644 docs/modules/prompts/prompt_templates.rst rename docs/modules/prompts/{ => prompt_templates}/examples/custom_prompt_template.ipynb (98%) rename docs/modules/prompts/{ => prompt_templates}/examples/example_prompt.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/examples.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/examples.yaml (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/few_shot_examples.ipynb (99%) rename docs/modules/prompts/{ => prompt_templates}/examples/few_shot_prompt.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/few_shot_prompt.yaml (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/few_shot_prompt_example_prompt.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/few_shot_prompt_examples_in.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/few_shot_prompt_yaml_examples.yaml (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/partial.ipynb (99%) rename docs/modules/prompts/{ => prompt_templates}/examples/prompt_serialization.ipynb (99%) rename docs/modules/prompts/{ => prompt_templates}/examples/simple_prompt.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/simple_prompt.yaml (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/simple_prompt_with_template_file.json (100%) rename docs/modules/prompts/{ => prompt_templates}/examples/simple_template.txt (100%) rename docs/modules/prompts/{ => prompt_templates}/getting_started.md (97%) create mode 100644 docs/modules/prompts/prompt_templates/how_to_guides.rst delete mode 100644 docs/modules/utils.rst delete mode 100644 docs/modules/utils/how_to_guides.rst delete mode 100644 docs/modules/utils/key_concepts.md delete mode 100644 docs/use_cases/agents.md create mode 100644 docs/use_cases/apis.md delete mode 100644 docs/use_cases/combine_docs.md delete mode 100644 docs/use_cases/generate_examples.ipynb create mode 100644 docs/use_cases/personal_assistants.md diff --git a/docs/ecosystem/atlas.md b/docs/ecosystem/atlas.md index 9bb7e04f..76619810 100644 --- a/docs/ecosystem/atlas.md +++ b/docs/ecosystem/atlas.md @@ -24,4 +24,4 @@ To import this vectorstore: from langchain.vectorstores import AtlasDB ``` -For a more detailed walkthrough of the AtlasDB wrapper, see [this notebook](../modules/indexes/vectorstore_examples/atlas.ipynb) +For a more detailed walkthrough of the AtlasDB wrapper, see [this notebook](../modules/indexes/vectorstores/examples/atlas.ipynb) diff --git a/docs/ecosystem/chroma.md b/docs/ecosystem/chroma.md index a8d46be5..1004a0e7 100644 --- a/docs/ecosystem/chroma.md +++ b/docs/ecosystem/chroma.md @@ -17,4 +17,4 @@ To import this vectorstore: from langchain.vectorstores import Chroma ``` -For a more detailed walkthrough of the Chroma wrapper, see [this notebook](../modules/indexes/examples/vectorstores.ipynb) +For a more detailed walkthrough of the Chroma wrapper, see [this notebook](../modules/indexes/vectorstores/getting_started.ipynb) diff --git a/docs/ecosystem/cohere.md b/docs/ecosystem/cohere.md index fc696893..082c58ae 100644 --- a/docs/ecosystem/cohere.md +++ b/docs/ecosystem/cohere.md @@ -22,4 +22,4 @@ There exists an Cohere Embeddings wrapper, which you can access with ```python from langchain.embeddings import CohereEmbeddings ``` -For a more detailed walkthrough of this, see [this notebook](../modules/indexes/examples/embeddings.ipynb) +For a more detailed walkthrough of this, see [this notebook](../modules/models/text_embedding/examples/embeddings.ipynb) diff --git a/docs/ecosystem/deeplake.md b/docs/ecosystem/deeplake.md index ca51051d..4f4e2151 100644 --- a/docs/ecosystem/deeplake.md +++ b/docs/ecosystem/deeplake.md @@ -22,4 +22,4 @@ from langchain.vectorstores import DeepLake ``` -For a more detailed walkthrough of the Deep Lake wrapper, see [this notebook](../modules/indexes/vectorstore_examples/deeplake.ipynb) +For a more detailed walkthrough of the Deep Lake wrapper, see [this notebook](../modules/indexes/vectorstores/examples/deeplake.ipynb) diff --git a/docs/ecosystem/google_search.md b/docs/ecosystem/google_search.md index dcf90162..b56eb84b 100644 --- a/docs/ecosystem/google_search.md +++ b/docs/ecosystem/google_search.md @@ -18,7 +18,7 @@ There exists a GoogleSearchAPIWrapper utility which wraps this API. To import th from langchain.utilities import GoogleSearchAPIWrapper ``` -For a more detailed walkthrough of this wrapper, see [this notebook](../modules/utils/examples/google_search.ipynb). +For a more detailed walkthrough of this wrapper, see [this notebook](../modules/agents/tools/examples/google_search.ipynb). ### Tool @@ -29,4 +29,4 @@ from langchain.agents import load_tools tools = load_tools(["google-search"]) ``` -For more information on this, see [this page](../modules/agents/tools.md) +For more information on this, see [this page](../modules/agents/tools/getting_started.md) diff --git a/docs/ecosystem/google_serper.md b/docs/ecosystem/google_serper.md index 57d0d0da..446c346b 100644 --- a/docs/ecosystem/google_serper.md +++ b/docs/ecosystem/google_serper.md @@ -58,7 +58,7 @@ So the final answer is: El Palmar, Spain 'El Palmar, Spain' ``` -For a more detailed walkthrough of this wrapper, see [this notebook](../modules/utils/examples/google_serper.ipynb). +For a more detailed walkthrough of this wrapper, see [this notebook](../modules/agents/tools/examples/google_serper.ipynb). ### Tool @@ -69,4 +69,4 @@ from langchain.agents import load_tools tools = load_tools(["google-serper"]) ``` -For more information on this, see [this page](../modules/agents/tools.md) +For more information on this, see [this page](../modules/agents/tools/getting_started.md) diff --git a/docs/ecosystem/huggingface.md b/docs/ecosystem/huggingface.md index dccceea3..ed5abaac 100644 --- a/docs/ecosystem/huggingface.md +++ b/docs/ecosystem/huggingface.md @@ -30,7 +30,7 @@ To use a the wrapper for a model hosted on Hugging Face Hub: ```python from langchain.llms import HuggingFaceHub ``` -For a more detailed walkthrough of the Hugging Face Hub wrapper, see [this notebook](../modules/llms/integrations/huggingface_hub.ipynb) +For a more detailed walkthrough of the Hugging Face Hub wrapper, see [this notebook](../modules/models/llms/integrations/huggingface_hub.ipynb) ### Embeddings @@ -47,7 +47,7 @@ To use a the wrapper for a model hosted on Hugging Face Hub: ```python from langchain.embeddings import HuggingFaceHubEmbeddings ``` -For a more detailed walkthrough of this, see [this notebook](../modules/indexes/examples/embeddings.ipynb) +For a more detailed walkthrough of this, see [this notebook](../modules/models/text_embedding/examples/embeddings.ipynb) ### Tokenizer @@ -59,7 +59,7 @@ You can also use it to count tokens when splitting documents with from langchain.text_splitter import CharacterTextSplitter CharacterTextSplitter.from_huggingface_tokenizer(...) ``` -For a more detailed walkthrough of this, see [this notebook](../modules/indexes/examples/textsplitter.ipynb) +For a more detailed walkthrough of this, see [this notebook](../modules/indexes/text_splitters/examples/textsplitter.ipynb) ### Datasets diff --git a/docs/ecosystem/milvus.md b/docs/ecosystem/milvus.md index 14a7f187..0b9c78ba 100644 --- a/docs/ecosystem/milvus.md +++ b/docs/ecosystem/milvus.md @@ -17,4 +17,4 @@ To import this vectorstore: from langchain.vectorstores import Milvus ``` -For a more detailed walkthrough of the Miluvs wrapper, see [this notebook](../modules/indexes/vectorstore_examples/milvus.ipynb) +For a more detailed walkthrough of the Miluvs wrapper, see [this notebook](../modules/indexes/vectorstores/examples/milvus.ipynb) diff --git a/docs/ecosystem/openai.md b/docs/ecosystem/openai.md index 2d4fa583..e37afc2a 100644 --- a/docs/ecosystem/openai.md +++ b/docs/ecosystem/openai.md @@ -21,7 +21,7 @@ If you are using a model hosted on Azure, you should use different wrapper for t ```python from langchain.llms import AzureOpenAI ``` -For a more detailed walkthrough of the Azure wrapper, see [this notebook](../modules/llms/integrations/azure_openai_example.ipynb) +For a more detailed walkthrough of the Azure wrapper, see [this notebook](../modules/models/llms/integrations/azure_openai_example.ipynb) @@ -31,7 +31,7 @@ There exists an OpenAI Embeddings wrapper, which you can access with ```python from langchain.embeddings import OpenAIEmbeddings ``` -For a more detailed walkthrough of this, see [this notebook](../modules/indexes/examples/embeddings.ipynb) +For a more detailed walkthrough of this, see [this notebook](../modules/models/text_embedding/examples/embeddings.ipynb) ### Tokenizer @@ -44,7 +44,7 @@ You can also use it to count tokens when splitting documents with from langchain.text_splitter import CharacterTextSplitter CharacterTextSplitter.from_tiktoken_encoder(...) ``` -For a more detailed walkthrough of this, see [this notebook](../modules/indexes/examples/textsplitter.ipynb) +For a more detailed walkthrough of this, see [this notebook](../modules/indexes/text_splitters/examples/textsplitter.ipynb) ### Moderation You can also access the OpenAI content moderation endpoint with diff --git a/docs/ecosystem/opensearch.md b/docs/ecosystem/opensearch.md index f1376fe7..881c1b67 100644 --- a/docs/ecosystem/opensearch.md +++ b/docs/ecosystem/opensearch.md @@ -18,4 +18,4 @@ To import this vectorstore: from langchain.vectorstores import OpenSearchVectorSearch ``` -For a more detailed walkthrough of the OpenSearch wrapper, see [this notebook](../modules/indexes/vectorstore_examples/opensearch.ipynb) +For a more detailed walkthrough of the OpenSearch wrapper, see [this notebook](../modules/indexes/vectorstores/examples/opensearch.ipynb) diff --git a/docs/ecosystem/pgvector.md b/docs/ecosystem/pgvector.md index 600b7879..3dcf1cb8 100644 --- a/docs/ecosystem/pgvector.md +++ b/docs/ecosystem/pgvector.md @@ -26,4 +26,4 @@ from langchain.vectorstores.pgvector import PGVector ### Usage -For a more detailed walkthrough of the PGVector Wrapper, see [this notebook](../modules/indexes/vectorstore_examples/pgvector.ipynb) +For a more detailed walkthrough of the PGVector Wrapper, see [this notebook](../modules/indexes/vectorstores/examples/pgvector.ipynb) diff --git a/docs/ecosystem/pinecone.md b/docs/ecosystem/pinecone.md index a758c475..b638c020 100644 --- a/docs/ecosystem/pinecone.md +++ b/docs/ecosystem/pinecone.md @@ -17,4 +17,4 @@ To import this vectorstore: from langchain.vectorstores import Pinecone ``` -For a more detailed walkthrough of the Pinecone wrapper, see [this notebook](../modules/indexes/vectorstore_examples/pinecone.ipynb) +For a more detailed walkthrough of the Pinecone wrapper, see [this notebook](../modules/indexes/vectorstores/examples/pinecone.ipynb) diff --git a/docs/ecosystem/promptlayer.md b/docs/ecosystem/promptlayer.md index fb2bef16..e013792d 100644 --- a/docs/ecosystem/promptlayer.md +++ b/docs/ecosystem/promptlayer.md @@ -46,4 +46,4 @@ This LLM is identical to the [OpenAI LLM](./openai), except that - you can add `return_pl_id` when instantializing to return a PromptLayer request id to use [while tracking requests](https://magniv.notion.site/Track-4deee1b1f7a34c1680d085f82567dab9). -PromptLayer also provides native wrappers for [`PromptLayerChatOpenAI`](../modules/chat/examples/promptlayer_chat_openai.ipynb) and `PromptLayerOpenAIChat` +PromptLayer also provides native wrappers for [`PromptLayerChatOpenAI`](../modules/models/chat/examples/promptlayer_chat_openai.ipynb) and `PromptLayerOpenAIChat` diff --git a/docs/ecosystem/qdrant.md b/docs/ecosystem/qdrant.md index 0c89c7c4..510b5e51 100644 --- a/docs/ecosystem/qdrant.md +++ b/docs/ecosystem/qdrant.md @@ -17,4 +17,4 @@ To import this vectorstore: from langchain.vectorstores import Qdrant ``` -For a more detailed walkthrough of the Qdrant wrapper, see [this notebook](../modules/indexes/vectorstore_examples/qdrant.ipynb) +For a more detailed walkthrough of the Qdrant wrapper, see [this notebook](../modules/indexes/vectorstores/examples/qdrant.ipynb) diff --git a/docs/ecosystem/runhouse.md b/docs/ecosystem/runhouse.md index 4f62ceb8..78f9683e 100644 --- a/docs/ecosystem/runhouse.md +++ b/docs/ecosystem/runhouse.md @@ -15,7 +15,7 @@ custom LLMs, you can use the `SelfHostedPipeline` parent class. from langchain.llms import SelfHostedPipeline, SelfHostedHuggingFaceLLM ``` -For a more detailed walkthrough of the Self-hosted LLMs, see [this notebook](../modules/llms/integrations/self_hosted_examples.ipynb) +For a more detailed walkthrough of the Self-hosted LLMs, see [this notebook](../modules/models/llms/integrations/self_hosted_examples.ipynb) ## Self-hosted Embeddings There are several ways to use self-hosted embeddings with LangChain via Runhouse. @@ -26,6 +26,6 @@ the `SelfHostedEmbedding` class. from langchain.llms import SelfHostedPipeline, SelfHostedHuggingFaceLLM ``` -For a more detailed walkthrough of the Self-hosted Embeddings, see [this notebook](../modules/indexes/examples/embeddings.ipynb) +For a more detailed walkthrough of the Self-hosted Embeddings, see [this notebook](../modules/models/text_embedding/examples/embeddings.ipynb) ## \ No newline at end of file diff --git a/docs/ecosystem/searx.md b/docs/ecosystem/searx.md index e0bb86bd..54939d06 100644 --- a/docs/ecosystem/searx.md +++ b/docs/ecosystem/searx.md @@ -55,4 +55,4 @@ from langchain.agents import load_tools tools = load_tools(["searx-search"], searx_host="http://localhost:8888") ``` -For more information on tools, see [this page](../modules/agents/tools.md) +For more information on tools, see [this page](../modules/agents/tools/getting_started.md) diff --git a/docs/ecosystem/serpapi.md b/docs/ecosystem/serpapi.md index f78dd773..b71be11e 100644 --- a/docs/ecosystem/serpapi.md +++ b/docs/ecosystem/serpapi.md @@ -17,7 +17,7 @@ There exists a SerpAPI utility which wraps this API. To import this utility: from langchain.utilities import SerpAPIWrapper ``` -For a more detailed walkthrough of this wrapper, see [this notebook](../modules/utils/examples/serpapi.ipynb). +For a more detailed walkthrough of this wrapper, see [this notebook](../modules/agents/tools/examples/serpapi.ipynb). ### Tool @@ -28,4 +28,4 @@ from langchain.agents import load_tools tools = load_tools(["serpapi"]) ``` -For more information on this, see [this page](../modules/agents/tools.md) +For more information on this, see [this page](../modules/agents/tools/getting_started.md) diff --git a/docs/ecosystem/weaviate.md b/docs/ecosystem/weaviate.md index 3fab349a..cfc9e971 100644 --- a/docs/ecosystem/weaviate.md +++ b/docs/ecosystem/weaviate.md @@ -30,4 +30,4 @@ To import this vectorstore: from langchain.vectorstores import Weaviate ``` -For a more detailed walkthrough of the Weaviate wrapper, see [this notebook](../modules/indexes/examples/vectorstores.ipynb) +For a more detailed walkthrough of the Weaviate wrapper, see [this notebook](../modules/indexes/vectorstores/getting_started.ipynb) diff --git a/docs/ecosystem/wolfram_alpha.md b/docs/ecosystem/wolfram_alpha.md index 2c6f844c..47427113 100644 --- a/docs/ecosystem/wolfram_alpha.md +++ b/docs/ecosystem/wolfram_alpha.md @@ -20,7 +20,7 @@ There exists a WolframAlphaAPIWrapper utility which wraps this API. To import th from langchain.utilities.wolfram_alpha import WolframAlphaAPIWrapper ``` -For a more detailed walkthrough of this wrapper, see [this notebook](../modules/utils/examples/wolfram_alpha.ipynb). +For a more detailed walkthrough of this wrapper, see [this notebook](../modules/agents/tools/examples/wolfram_alpha.ipynb). ### Tool @@ -31,4 +31,4 @@ from langchain.agents import load_tools tools = load_tools(["wolfram-alpha"]) ``` -For more information on this, see [this page](../modules/agents/tools.md) +For more information on this, see [this page](../modules/agents/tools/getting_started.md) diff --git a/docs/getting_started/getting_started.md b/docs/getting_started/getting_started.md index 4086c524..582239f8 100644 --- a/docs/getting_started/getting_started.md +++ b/docs/getting_started/getting_started.md @@ -36,7 +36,7 @@ os.environ["OPENAI_API_KEY"] = "..." ``` -## Building a Language Model Application +## Building a Language Model Application: LLMs Now that we have installed LangChain and set up our environment, we can start building our language model application. @@ -160,7 +160,7 @@ This is one of the simpler types of chains, but understanding how it works will ````` -`````{dropdown} Agents: Dynamically call chains based on user input +`````{dropdown} Agents: Dynamically Call Chains Based on User Input So far the chains we've looked at run in a predetermined order. @@ -238,7 +238,7 @@ Final Answer: Jason Sudeikis, Olivia Wilde's boyfriend, is 47 years old and his ````` -`````{dropdown} Memory: Add state to chains and agents +`````{dropdown} Memory: Add State to Chains and Agents So far, all the chains and agents we've gone through have been stateless. But often, you may want a chain or agent to have some concept of "memory" so that it may remember information about its previous interactions. The clearest and simple example of this is when designing a chatbot - you want it to remember previous messages so it can use context from that to have a better conversation. This would be a type of "short-term memory". On the more complex side, you could imagine a chain/agent remembering key pieces of information over time - this would be a form of "long-term memory". For more concrete ideas on the latter, see this [awesome paper](https://memprompt.com/). @@ -287,4 +287,217 @@ AI: > Finished chain. " That's great! What would you like to talk about?" -``` \ No newline at end of file +``` +````` + +## Building a Language Model Application: Chat Models + +Similarly, you can use chat models instead of LLMs. Chat models are a variation on language models. While chat models use language models under the hood, the interface they expose is a bit different: rather than expose a "text in, text out" API, they expose an interface where "chat messages" are the inputs and outputs. + +Chat model APIs are fairly new, so we are still figuring out the correct abstractions. + + +`````{dropdown} Get Message Completions from a Chat Model +You can get chat completions by passing one or more messages to the chat model. The response will be a message. The types of messages currently supported in LangChain are `AIMessage`, `HumanMessage`, `SystemMessage`, and `ChatMessage` -- `ChatMessage` takes in an arbitrary role parameter. Most of the time, you'll just be dealing with `HumanMessage`, `AIMessage`, and `SystemMessage`. + +```python +from langchain.chat_models import ChatOpenAI +from langchain.schema import ( + AIMessage, + HumanMessage, + SystemMessage +) + +chat = ChatOpenAI(temperature=0) +``` + +You can get completions by passing in a single message. + +```python +chat([HumanMessage(content="Translate this sentence from English to French. I love programming.")]) +# -> AIMessage(content="J'aime programmer.", additional_kwargs={}) +``` + +You can also pass in multiple messages for OpenAI's gpt-3.5-turbo and gpt-4 models. + +```python +messages = [ + SystemMessage(content="You are a helpful assistant that translates English to French."), + HumanMessage(content="Translate this sentence from English to French. I love programming.") +] +chat(messages) +# -> AIMessage(content="J'aime programmer.", additional_kwargs={}) +``` + +You can go one step further and generate completions for multiple sets of messages using `generate`. This returns an `LLMResult` with an additional `message` parameter: +```python +batch_messages = [ + [ + SystemMessage(content="You are a helpful assistant that translates English to French."), + HumanMessage(content="Translate this sentence from English to French. I love programming.") + ], + [ + SystemMessage(content="You are a helpful assistant that translates English to French."), + HumanMessage(content="Translate this sentence from English to French. I love artificial intelligence.") + ], +] +result = chat.generate(batch_messages) +result +# -> LLMResult(generations=[[ChatGeneration(text="J'aime programmer.", generation_info=None, message=AIMessage(content="J'aime programmer.", additional_kwargs={}))], [ChatGeneration(text="J'aime l'intelligence artificielle.", generation_info=None, message=AIMessage(content="J'aime l'intelligence artificielle.", additional_kwargs={}))]], llm_output={'token_usage': {'prompt_tokens': 71, 'completion_tokens': 18, 'total_tokens': 89}}) +``` + +You can recover things like token usage from this LLMResult: +``` +result.llm_output['token_usage'] +# -> {'prompt_tokens': 71, 'completion_tokens': 18, 'total_tokens': 89} +``` +````` + +`````{dropdown} Chat Prompt Templates +Similar to LLMs, you can make use of templating by using a `MessagePromptTemplate`. You can build a `ChatPromptTemplate` from one or more `MessagePromptTemplate`s. You can use `ChatPromptTemplate`'s `format_prompt` -- this returns a `PromptValue`, which you can convert to a string or `Message` object, depending on whether you want to use the formatted value as input to an llm or chat model. + +For convience, there is a `from_template` method exposed on the template. If you were to use this template, this is what it would look like: + +```python +from langchain.prompts.chat import ( + ChatPromptTemplate, + SystemMessagePromptTemplate, + AIMessagePromptTemplate, + HumanMessagePromptTemplate, +) + +template="You are a helpful assistant that translates {input_language} to {output_language}." +system_message_prompt = SystemMessagePromptTemplate.from_template(template) +human_template="{text}" +human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) + +chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt]) + +# get a chat completion from the formatted messages +chat(chat_prompt.format_prompt(input_language="English", output_language="French", text="I love programming.").to_messages()) +# -> AIMessage(content="J'aime programmer.", additional_kwargs={}) +``` +````` + +`````{dropdown} Chains with Chat Models +The `LLMChain` discussed in the above section can be used with chat models as well: + +```python +from langchain.chat_models import ChatOpenAI +from langchain import PromptTemplate, LLMChain +from langchain.prompts.chat import ( + ChatPromptTemplate, + SystemMessagePromptTemplate, + AIMessagePromptTemplate, + HumanMessagePromptTemplate, +) + +chat = ChatOpenAI(temperature=0) + +template="You are a helpful assistant that translates {input_language} to {output_language}." +system_message_prompt = SystemMessagePromptTemplate.from_template(template) +human_template="{text}" +human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) +chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt]) + +chain = LLMChain(llm=chat, prompt=chat_prompt) +chain.run(input_language="English", output_language="French", text="I love programming.") +# -> "J'aime programmer." +``` +````` + +`````{dropdown} Agents with Chat Models +Agents can also be used with chat models, you can initialize one using `"chat-zero-shot-react-description"` as the agent type. + +```python +from langchain.agents import load_tools +from langchain.agents import initialize_agent +from langchain.chat_models import ChatOpenAI +from langchain.llms import OpenAI + +# First, let's load the language model we're going to use to control the agent. +chat = ChatOpenAI(temperature=0) + +# Next, let's load some tools to use. Note that the `llm-math` tool uses an LLM, so we need to pass that in. +llm = OpenAI(temperature=0) +tools = load_tools(["serpapi", "llm-math"], llm=llm) + + +# Finally, let's initialize an agent with the tools, the language model, and the type of agent we want to use. +agent = initialize_agent(tools, chat, agent="chat-zero-shot-react-description", verbose=True) + +# Now let's test it out! +agent.run("Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?") +``` + +```pycon + +> Entering new AgentExecutor chain... +Thought: I need to use a search engine to find Olivia Wilde's boyfriend and a calculator to raise his age to the 0.23 power. +Action: +{ + "action": "Search", + "action_input": "Olivia Wilde boyfriend" +} + +Observation: Sudeikis and Wilde's relationship ended in November 2020. Wilde was publicly served with court documents regarding child custody while she was presenting Don't Worry Darling at CinemaCon 2022. In January 2021, Wilde began dating singer Harry Styles after meeting during the filming of Don't Worry Darling. +Thought:I need to use a search engine to find Harry Styles' current age. +Action: +{ + "action": "Search", + "action_input": "Harry Styles age" +} + +Observation: 29 years +Thought:Now I need to calculate 29 raised to the 0.23 power. +Action: +{ + "action": "Calculator", + "action_input": "29^0.23" +} + +Observation: Answer: 2.169459462491557 + +Thought:I now know the final answer. +Final Answer: 2.169459462491557 + +> Finished chain. +'2.169459462491557' +``` +````` + +`````{dropdown} Memory: Add State to Chains and Agents +You can use Memory with chains and agents initialized with chat models. The main difference between this and Memory for LLMs is that rather than trying to condense all previous messages into a string, we can keep them as their own unique memory object. + +```python +from langchain.prompts import ( + ChatPromptTemplate, + MessagesPlaceholder, + SystemMessagePromptTemplate, + HumanMessagePromptTemplate +) +from langchain.chains import ConversationChain +from langchain.chat_models import ChatOpenAI +from langchain.memory import ConversationBufferMemory + +prompt = ChatPromptTemplate.from_messages([ + SystemMessagePromptTemplate.from_template("The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know."), + MessagesPlaceholder(variable_name="history"), + HumanMessagePromptTemplate.from_template("{input}") +]) + +llm = ChatOpenAI(temperature=0) +memory = ConversationBufferMemory(return_messages=True) +conversation = ConversationChain(memory=memory, prompt=prompt, llm=llm) + +conversation.predict(input="Hi there!") +# -> 'Hello! How can I assist you today?' + + +conversation.predict(input="I'm doing well! Just having a conversation with an AI.") +# -> "That sounds like fun! I'm happy to chat with you. Is there anything specific you'd like to talk about?" + +conversation.predict(input="Tell me about yourself.") +# -> "Sure! I am an AI language model created by OpenAI. I was trained on a large dataset of text from the internet, which allows me to understand and generate human-like language. I can answer questions, provide information, and even have conversations like this one. Is there anything else you'd like to know about me?" +``` +````` diff --git a/docs/glossary.md b/docs/glossary.md index ffd36298..959d0cbf 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -32,7 +32,7 @@ This induces the to model to think about what action to take, then take it. Resources: - [Paper](https://arxiv.org/pdf/2210.03629.pdf) -- [LangChain Example](./modules/agents/implementations/react.ipynb) +- [LangChain Example](modules/agents/agents/examples/react.ipynb) ## Self-ask @@ -42,7 +42,7 @@ In this method, the model explicitly asks itself follow-up questions, which are Resources: - [Paper](https://ofir.io/self-ask.pdf) -- [LangChain Example](./modules/agents/implementations/self_ask_with_search.ipynb) +- [LangChain Example](modules/agents/agents/examples/self_ask_with_search.ipynb) ## Prompt Chaining diff --git a/docs/index.rst b/docs/index.rst index 4f7c4d8c..c2faca7f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,28 +1,14 @@ Welcome to LangChain ========================== -Large language models (LLMs) are emerging as a transformative technology, enabling -developers to build applications that they previously could not. -But using these LLMs in isolation is often not enough to -create a truly powerful app - the real power comes when you are able to -combine them with other sources of computation or knowledge. +LangChain is a framework for developing applications powered by language models. We believe that the most powerful and differentiated applications will not only call out to a language model via an API, but will also: -This library is aimed at assisting in the development of those types of applications. Common examples of these types of applications include: +- *Be data-aware*: connect a language model to other sources of data +- *Be agentic*: Allow a language model to interact with its environment -**❓ Question Answering over specific documents** +The LangChain framework is designed with above objectives in mind. -- `Documentation <./use_cases/question_answering.html>`_ -- End-to-end Example: `Question Answering over Notion Database `_ - -**💬 Chatbots** - -- `Documentation <./use_cases/chatbots.html>`_ -- End-to-end Example: `Chat-LangChain `_ - -**🤖 Agents** - -- `Documentation <./use_cases/agents.html>`_ -- End-to-end Example: `GPT+WolframAlpha `_ +This is the Python specific portion of the documentation. For a purely conceptual guide to LangChain, see `here `_. For the JavaScript documentation, see `here `_. Getting Started ---------------- @@ -46,25 +32,18 @@ There are several main modules that LangChain provides support for. For each module we provide some examples to get started, how-to guides, reference docs, and conceptual guides. These modules are, in increasing order of complexity: +- `Models <./modules/models.html>`_: The various model types and model integrations LangChain supports. - `Prompts <./modules/prompts.html>`_: This includes prompt management, prompt optimization, and prompt serialization. -- `LLMs <./modules/llms.html>`_: This includes a generic interface for all LLMs, and common utilities for working with LLMs. - -- `Document Loaders <./modules/document_loaders.html>`_: This includes a standard interface for loading documents, as well as specific integrations to all types of text data sources. +- `Memory <./modules/memory.html>`_: Memory is the concept of persisting state between calls of a chain/agent. LangChain provides a standard interface for memory, a collection of memory implementations, and examples of chains/agents that use memory. -- `Utils <./modules/utils.html>`_: Language models are often more powerful when interacting with other sources of knowledge or computation. This can include Python REPLs, embeddings, search engines, and more. LangChain provides a large collection of common utils to use in your application. +- `Indexes <./modules/indexes.html>`_: Language models are often more powerful when combined with your own text data - this module covers best practices for doing exactly that. - `Chains <./modules/chains.html>`_: Chains go beyond just a single LLM call, and are sequences of calls (whether to an LLM or a different utility). LangChain provides a standard interface for chains, lots of integrations with other tools, and end-to-end chains for common applications. -- `Indexes <./modules/indexes.html>`_: Language models are often more powerful when combined with your own text data - this module covers best practices for doing exactly that. - - `Agents <./modules/agents.html>`_: Agents involve an LLM making decisions about which Actions to take, taking that Action, seeing an Observation, and repeating that until done. LangChain provides a standard interface for agents, a selection of agents to choose from, and examples of end to end agents. -- `Memory <./modules/memory.html>`_: Memory is the concept of persisting state between calls of a chain/agent. LangChain provides a standard interface for memory, a collection of memory implementations, and examples of chains/agents that use memory. - -- `Chat <./modules/chat.html>`_: Chat models are a variation on Language Models that expose a different API - rather than working with raw text, they work with messages. LangChain provides a standard interface for working with them and doing all the same things as above. - .. toctree:: :maxdepth: 1 @@ -72,39 +51,33 @@ These modules are, in increasing order of complexity: :name: modules :hidden: - ./modules/prompts.md - ./modules/llms.md - ./modules/document_loaders.md - ./modules/utils.md + ./modules/models.rst + ./modules/prompts.rst ./modules/indexes.md + ./modules/memory.md ./modules/chains.md ./modules/agents.md - ./modules/memory.md - ./modules/chat.md Use Cases ---------- The above modules can be used in a variety of ways. LangChain also provides guidance and assistance in this. Below are some of the common use cases LangChain supports. -- `Agents <./use_cases/agents.html>`_: Agents are systems that use a language model to interact with other tools. These can be used to do more grounded question/answering, interact with APIs, or even take actions. - -- `Chatbots <./use_cases/chatbots.html>`_: Since language models are good at producing text, that makes them ideal for creating chatbots. - -- `Data Augmented Generation <./use_cases/combine_docs.html>`_: Data Augmented Generation involves specific types of chains that first interact with an external datasource to fetch data to use in the generation step. Examples of this include summarization of long pieces of text and question/answering over specific data sources. +- `Personal Assistants <./use_cases/personal_assistants.html>`_: The main LangChain use case. Personal assistants need to take actions, remember interactions, and have knowledge about your data. -- `Question Answering <./use_cases/question_answering.html>`_: Answering questions over specific documents, only utilizing the information in those documents to construct an answer. A type of Data Augmented Generation. +- `Question Answering <./use_cases/question_answering.html>`_: The second big LangChain use case. Answering questions over specific documents, only utilizing the information in those documents to construct an answer. -- `Summarization <./use_cases/summarization.html>`_: Summarizing longer documents into shorter, more condensed chunks of information. A type of Data Augmented Generation. +- `Chatbots <./use_cases/chatbots.html>`_: Since language models are good at producing text, that makes them ideal for creating chatbots. - `Querying Tabular Data <./use_cases/tabular.html>`_: If you want to understand how to use LLMs to query data that is stored in a tabular format (csvs, SQL, dataframes, etc) you should read this page. -- `Evaluation <./use_cases/evaluation.html>`_: Generative models are notoriously hard to evaluate with traditional metrics. One new way of evaluating them is using language models themselves to do the evaluation. LangChain provides some prompts/chains for assisting in this. +- `Interacting with APIs <./use_cases/apis.html>`_: Enabling LLMs to interact with APIs is extremely powerful in order to give them more up-to-date information and allow them to take actions. -- `Generate similar examples <./use_cases/generate_examples.html>`_: Generating similar examples to a given input. This is a common use case for many applications, and LangChain provides some prompts/chains for assisting in this. +- `Extraction <./use_cases/extraction.html>`_: Extract structured information from text. -- `Compare models <./use_cases/model_laboratory.html>`_: Experimenting with different prompts, models, and chains is a big part of developing the best possible application. The ModelLaboratory makes it easy to do so. +- `Summarization <./use_cases/summarization.html>`_: Summarizing longer documents into shorter, more condensed chunks of information. A type of Data Augmented Generation. +- `Evaluation <./use_cases/evaluation.html>`_: Generative models are notoriously hard to evaluate with traditional metrics. One new way of evaluating them is using language models themselves to do the evaluation. LangChain provides some prompts/chains for assisting in this. .. toctree:: @@ -114,15 +87,12 @@ The above modules can be used in a variety of ways. LangChain also provides guid :hidden: ./use_cases/agents.md - ./use_cases/chatbots.md - ./use_cases/generate_examples.ipynb - ./use_cases/combine_docs.md ./use_cases/question_answering.md - ./use_cases/summarization.md + ./use_cases/chatbots.md ./use_cases/tabular.rst + ./use_cases/summarization.md ./use_cases/extraction.md ./use_cases/evaluation.rst - ./use_cases/model_laboratory.ipynb Reference Docs @@ -173,10 +143,12 @@ Additional collection of resources we think may be useful as you develop your ap - `Deployments <./deployments.html>`_: A collection of instructions, code snippets, and template repositories for deploying LangChain apps. -- `Discord `_: Join us on our Discord to discuss all things LangChain! - - `Tracing <./tracing.html>`_: A guide on using tracing in LangChain to visualize the execution of chains and agents. +- `Model Laboratory <./model_laboratory.html>`_: Experimenting with different prompts, models, and chains is a big part of developing the best possible application. The ModelLaboratory makes it easy to do so. + +- `Discord `_: Join us on our Discord to discuss all things LangChain! + - `Production Support `_: As you move your LangChains into production, we'd love to offer more comprehensive support. Please fill out this form and we'll set up a dedicated support Slack channel. @@ -191,5 +163,6 @@ Additional collection of resources we think may be useful as you develop your ap ./gallery.rst ./deployments.md ./tracing.md + ./use_cases/model_laboratory.ipynb Discord Production Support diff --git a/docs/use_cases/model_laboratory.ipynb b/docs/model_laboratory.ipynb similarity index 100% rename from docs/use_cases/model_laboratory.ipynb rename to docs/model_laboratory.ipynb diff --git a/docs/modules/agents.rst b/docs/modules/agents.rst index fea87524..cd097c55 100644 --- a/docs/modules/agents.rst +++ b/docs/modules/agents.rst @@ -1,30 +1,52 @@ Agents ========================== +.. note:: + `Conceptual Guide `_ + + Some applications will require not just a predetermined chain of calls to LLMs/other tools, but potentially an unknown chain that depends on the user's input. In these types of chains, there is a “agent” which has access to a suite of tools. Depending on the user input, the agent can then decide which, if any, of these tools to call. -The following sections of documentation are provided: +In this section of documentation, we first start with a Getting Started notebook to over over how to use all things related to agents in an end-to-end manner. + +.. toctree:: + :maxdepth: 1 + :hidden: + + ./agents/getting_started.ipynb + -- `Getting Started <./agents/getting_started.html>`_: A notebook to help you get started working with agents as quickly as possible. +We then split the documentation into the following sections: -- `Key Concepts <./agents/key_concepts.html>`_: A conceptual guide going over the various concepts related to agents. +**Tools** -- `How-To Guides <./agents/how_to_guides.html>`_: A collection of how-to guides. These highlight how to integrate various types of tools, how to work with different types of agents, and how to customize agents. +An overview of the various tools LangChain supports. -- `Reference <../reference/modules/agents.html>`_: API reference documentation for all Agent classes. +**Agents** +An overview of the different agent types. + + +**Toolkits** + +An overview of toolkits, and examples of the different ones LangChain supports. + + +**Agent Executor** + +An overview of the Agent Executor class and examples of how to use it. + +Go Deeper +--------- .. toctree:: :maxdepth: 1 - :caption: Agents - :name: Agents - :hidden: - ./agents/getting_started.ipynb - ./agents/key_concepts.md - ./agents/how_to_guides.rst - Reference<../reference/modules/agents.rst> + ./agents/tools.rst + ./agents/agents.rst + ./agents/agent_toolkits.rst + ./agents/agent_executors.rst diff --git a/docs/modules/agents/agent_executors.rst b/docs/modules/agents/agent_executors.rst new file mode 100644 index 00000000..bb4eb447 --- /dev/null +++ b/docs/modules/agents/agent_executors.rst @@ -0,0 +1,17 @@ +Agent Executors +=============== + +.. note:: + `Conceptual Guide `_ + +Agent executors take an agent and tools and use the agent to decide which tools to call and in what order. + +In this part of the documentation we cover other related functionality to agent executors + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./agent_executors/examples/* + diff --git a/docs/modules/agents/examples/agent_vectorstore.ipynb b/docs/modules/agents/agent_executors/examples/agent_vectorstore.ipynb similarity index 96% rename from docs/modules/agents/examples/agent_vectorstore.ipynb rename to docs/modules/agents/agent_executors/examples/agent_vectorstore.ipynb index 5f776e54..c127cef1 100644 --- a/docs/modules/agents/examples/agent_vectorstore.ipynb +++ b/docs/modules/agents/agent_executors/examples/agent_vectorstore.ipynb @@ -5,7 +5,7 @@ "id": "68b24990", "metadata": {}, "source": [ - "# Agents and Vectorstores\n", + "# How to combine agents and vectorstores\n", "\n", "This notebook covers how to combine agents and vectorstores. The use case for this is that you've ingested your data into a vectorstore and want to interact with it in an agentic manner.\n", "\n", @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 16, "id": "2e87c10a", "metadata": {}, "outputs": [], @@ -37,7 +37,23 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 17, + "id": "0b7b772b", + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "relevant_parts = []\n", + "for p in Path(\".\").absolute().parts:\n", + " relevant_parts.append(p)\n", + " if relevant_parts[-3:] == [\"langchain\", \"docs\", \"modules\"]:\n", + " break\n", + "doc_path = str(Path(*relevant_parts) / \"state_of_the_union.txt\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, "id": "f2675861", "metadata": {}, "outputs": [ @@ -52,7 +68,7 @@ ], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader(doc_path)\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "texts = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/agents/examples/async_agent.ipynb b/docs/modules/agents/agent_executors/examples/async_agent.ipynb similarity index 99% rename from docs/modules/agents/examples/async_agent.ipynb rename to docs/modules/agents/agent_executors/examples/async_agent.ipynb index 854f2c86..216ddcd3 100644 --- a/docs/modules/agents/examples/async_agent.ipynb +++ b/docs/modules/agents/agent_executors/examples/async_agent.ipynb @@ -5,7 +5,7 @@ "id": "6fb92deb-d89e-439b-855d-c7f2607d794b", "metadata": {}, "source": [ - "# Async API for Agent\n", + "# How to use the async API for Agents\n", "\n", "LangChain provides async support for Agents by leveraging the [asyncio](https://docs.python.org/3/library/asyncio.html) library.\n", "\n", @@ -403,7 +403,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/memory/examples/chatgpt_clone.ipynb b/docs/modules/agents/agent_executors/examples/chatgpt_clone.ipynb similarity index 99% rename from docs/modules/memory/examples/chatgpt_clone.ipynb rename to docs/modules/agents/agent_executors/examples/chatgpt_clone.ipynb index e92d32d6..f9d7ff3e 100644 --- a/docs/modules/memory/examples/chatgpt_clone.ipynb +++ b/docs/modules/agents/agent_executors/examples/chatgpt_clone.ipynb @@ -5,7 +5,7 @@ "id": "b253f4d5", "metadata": {}, "source": [ - "# ChatGPT Clone\n", + "# How to create ChatGPT Clone\n", "\n", "This chain replicates ChatGPT by combining (1) a specific prompt, and (2) the concept of memory.\n", "\n", diff --git a/docs/modules/agents/examples/intermediate_steps.ipynb b/docs/modules/agents/agent_executors/examples/intermediate_steps.ipynb similarity index 99% rename from docs/modules/agents/examples/intermediate_steps.ipynb rename to docs/modules/agents/agent_executors/examples/intermediate_steps.ipynb index 9c411836..4f2995bb 100644 --- a/docs/modules/agents/examples/intermediate_steps.ipynb +++ b/docs/modules/agents/agent_executors/examples/intermediate_steps.ipynb @@ -5,7 +5,7 @@ "id": "5436020b", "metadata": {}, "source": [ - "# Intermediate Steps\n", + "# How to access intermediate steps\n", "\n", "In order to get more visibility into what an agent is doing, we can also return intermediate steps. This comes in the form of an extra key in the return value, which is a list of (action, observation) tuples." ] diff --git a/docs/modules/agents/examples/max_iterations.ipynb b/docs/modules/agents/agent_executors/examples/max_iterations.ipynb similarity index 99% rename from docs/modules/agents/examples/max_iterations.ipynb rename to docs/modules/agents/agent_executors/examples/max_iterations.ipynb index 9be01142..51abf824 100644 --- a/docs/modules/agents/examples/max_iterations.ipynb +++ b/docs/modules/agents/agent_executors/examples/max_iterations.ipynb @@ -5,7 +5,7 @@ "id": "75c041b7", "metadata": {}, "source": [ - "# Max Iterations\n", + "# How to cap the max number of iterations\n", "\n", "This notebook walks through how to cap an agent at taking a certain number of steps. This can be useful to ensure that they do not go haywire and take too many steps." ] diff --git a/docs/modules/agents/examples/sharedmemory_for_tools.ipynb b/docs/modules/agents/agent_executors/examples/sharedmemory_for_tools.ipynb similarity index 99% rename from docs/modules/agents/examples/sharedmemory_for_tools.ipynb rename to docs/modules/agents/agent_executors/examples/sharedmemory_for_tools.ipynb index f83cafbf..62d75c65 100644 --- a/docs/modules/agents/examples/sharedmemory_for_tools.ipynb +++ b/docs/modules/agents/agent_executors/examples/sharedmemory_for_tools.ipynb @@ -1,12 +1,11 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "id": "fa6802ac", "metadata": {}, "source": [ - "# Adding SharedMemory to an Agent and its Tools\n", + "# How to add SharedMemory to an Agent and its Tools\n", "\n", "This notebook goes over adding memory to **both** of an Agent and its tools. Before going through this notebook, please walk through the following notebooks, as this will build on top of both of them:\n", "\n", @@ -260,7 +259,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "id": "4ebd8326", "metadata": {}, @@ -292,7 +290,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "id": "cc3d0aa4", "metadata": {}, @@ -493,7 +490,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "id": "d07415da", "metadata": {}, @@ -544,7 +540,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/agents/agents.rst b/docs/modules/agents/agents.rst new file mode 100644 index 00000000..e9567557 --- /dev/null +++ b/docs/modules/agents/agents.rst @@ -0,0 +1,35 @@ +Agents +============= + +.. note:: + `Conceptual Guide `_ + + +In this part of the documentation we cover the different types of agents, disregarding which specific tools they are used with. + +For a high level overview of the different types of agents, see the below documentation. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./agents/agent_types.md + +For documentation on how to create a custom agent, see the below. + +We also have documentation for an in-depth dive into each agent type. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./agents/custom_agent.ipynb + +We also have documentation for an in-depth dive into each agent type. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./agents/examples/* + diff --git a/docs/modules/agents/agents.md b/docs/modules/agents/agents/agent_types.md similarity index 91% rename from docs/modules/agents/agents.md rename to docs/modules/agents/agents/agent_types.md index a1e8aa94..9dd3764b 100644 --- a/docs/modules/agents/agents.md +++ b/docs/modules/agents/agents/agent_types.md @@ -1,12 +1,9 @@ -# Agents +# Agent Types Agents use an LLM to determine which actions to take and in what order. An action can either be using a tool and observing its output, or returning a response to the user. -For a list of easily loadable tools, see [here](tools.md). Here are the agents available in LangChain. -For a tutorial on how to load agents, see [here](getting_started.ipynb). - ## `zero-shot-react-description` This agent uses the ReAct framework to determine which tool to use diff --git a/docs/modules/agents/examples/custom_agent.ipynb b/docs/modules/agents/agents/custom_agent.ipynb similarity index 100% rename from docs/modules/agents/examples/custom_agent.ipynb rename to docs/modules/agents/agents/custom_agent.ipynb diff --git a/docs/modules/agents/examples/chat_conversation_agent.ipynb b/docs/modules/agents/agents/examples/chat_conversation_agent.ipynb similarity index 100% rename from docs/modules/agents/examples/chat_conversation_agent.ipynb rename to docs/modules/agents/agents/examples/chat_conversation_agent.ipynb diff --git a/docs/modules/memory/examples/conversational_agent.ipynb b/docs/modules/agents/agents/examples/conversational_agent.ipynb similarity index 100% rename from docs/modules/memory/examples/conversational_agent.ipynb rename to docs/modules/agents/agents/examples/conversational_agent.ipynb diff --git a/docs/modules/agents/implementations/mrkl.ipynb b/docs/modules/agents/agents/examples/mrkl.ipynb similarity index 100% rename from docs/modules/agents/implementations/mrkl.ipynb rename to docs/modules/agents/agents/examples/mrkl.ipynb diff --git a/docs/modules/agents/implementations/mrkl_chat.ipynb b/docs/modules/agents/agents/examples/mrkl_chat.ipynb similarity index 100% rename from docs/modules/agents/implementations/mrkl_chat.ipynb rename to docs/modules/agents/agents/examples/mrkl_chat.ipynb diff --git a/docs/modules/agents/implementations/react.ipynb b/docs/modules/agents/agents/examples/react.ipynb similarity index 100% rename from docs/modules/agents/implementations/react.ipynb rename to docs/modules/agents/agents/examples/react.ipynb diff --git a/docs/modules/agents/implementations/self_ask_with_search.ipynb b/docs/modules/agents/agents/examples/self_ask_with_search.ipynb similarity index 100% rename from docs/modules/agents/implementations/self_ask_with_search.ipynb rename to docs/modules/agents/agents/examples/self_ask_with_search.ipynb diff --git a/docs/modules/agents/examples/load_from_hub.ipynb b/docs/modules/agents/examples/load_from_hub.ipynb deleted file mode 100644 index 9e17d7bb..00000000 --- a/docs/modules/agents/examples/load_from_hub.ipynb +++ /dev/null @@ -1,131 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "991b1cc1", - "metadata": {}, - "source": [ - "# Loading from LangChainHub\n", - "\n", - "This notebook covers how to load agents from [LangChainHub](https://github.com/hwchase17/langchain-hub)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "bd4450a2", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "No `_type` key found, defaulting to `prompt`.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n", - "\u001B[32;1m\u001B[1;3m Yes.\n", - "Follow up: Who is the reigning men's U.S. Open champion?\u001B[0m\n", - "Intermediate answer: \u001B[36;1m\u001B[1;3m2016 · SUI · Stan Wawrinka ; 2017 · ESP · Rafael Nadal ; 2018 · SRB · Novak Djokovic ; 2019 · ESP · Rafael Nadal.\u001B[0m\n", - "\u001B[32;1m\u001B[1;3mSo the reigning men's U.S. Open champion is Rafael Nadal.\n", - "Follow up: What is Rafael Nadal's hometown?\u001B[0m\n", - "Intermediate answer: \u001B[36;1m\u001B[1;3mIn 2016, he once again showed his deep ties to Mallorca and opened the Rafa Nadal Academy in his hometown of Manacor.\u001B[0m\n", - "\u001B[32;1m\u001B[1;3mSo the final answer is: Manacor, Mallorca, Spain.\u001B[0m\n", - "\n", - "\u001B[1m> Finished chain.\u001B[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'Manacor, Mallorca, Spain.'" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from langchain import OpenAI, SerpAPIWrapper\n", - "from langchain.agents import initialize_agent, Tool\n", - "\n", - "llm = OpenAI(temperature=0)\n", - "search = SerpAPIWrapper()\n", - "tools = [\n", - " Tool(\n", - " name=\"Intermediate Answer\",\n", - " func=search.run,\n", - " description=\"useful for when you need to ask with search\"\n", - " )\n", - "]\n", - "\n", - "self_ask_with_search = initialize_agent(tools, llm, agent_path=\"lc://agents/self-ask-with-search/agent.json\", verbose=True)\n", - "self_ask_with_search.run(\"What is the hometown of the reigning men's U.S. Open champion?\")" - ] - }, - { - "cell_type": "markdown", - "id": "3aede965", - "metadata": {}, - "source": [ - "# Pinning Dependencies\n", - "\n", - "Specific versions of LangChainHub agents can be pinned with the `lc@://` syntax." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "e679f7b6", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "No `_type` key found, defaulting to `prompt`.\n" - ] - } - ], - "source": [ - "self_ask_with_search = initialize_agent(tools, llm, agent_path=\"lc@2826ef9e8acdf88465e1e5fc8a7bf59e0f9d0a85://agents/self-ask-with-search/agent.json\", verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9d3d6697", - "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 -} diff --git a/docs/modules/agents/examples/serialization.ipynb b/docs/modules/agents/examples/serialization.ipynb deleted file mode 100644 index 4eebace8..00000000 --- a/docs/modules/agents/examples/serialization.ipynb +++ /dev/null @@ -1,154 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "bfe18e28", - "metadata": {}, - "source": [ - "# Serialization\n", - "\n", - "This notebook goes over how to serialize agents. For this notebook, it is important to understand the distinction we draw between `agents` and `tools`. An agent is the LLM powered decision maker that decides which actions to take and in which order. Tools are various instruments (functions) an agent has access to, through which an agent can interact with the outside world. When people generally use agents, they primarily talk about using an agent WITH tools. However, when we talk about serialization of agents, we are talking about the agent by itself. We plan to add support for serializing an agent WITH tools sometime in the future.\n", - "\n", - "Let's start by creating an agent with tools as we normally do:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "eb729f16", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.agents import load_tools\n", - "from langchain.agents import initialize_agent\n", - "from langchain.llms import OpenAI\n", - "\n", - "llm = OpenAI(temperature=0)\n", - "tools = load_tools([\"serpapi\", \"llm-math\"], llm=llm)\n", - "agent = initialize_agent(tools, llm, agent=\"zero-shot-react-description\", verbose=True)" - ] - }, - { - "cell_type": "markdown", - "id": "0578f566", - "metadata": {}, - "source": [ - "Let's now serialize the agent. To be explicit that we are serializing ONLY the agent, we will call the `save_agent` method." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "dc544de6", - "metadata": {}, - "outputs": [], - "source": [ - "agent.save_agent('agent.json')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "62dd45bf", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\r\n", - " \"llm_chain\": {\r\n", - " \"memory\": null,\r\n", - " \"verbose\": false,\r\n", - " \"prompt\": {\r\n", - " \"input_variables\": [\r\n", - " \"input\",\r\n", - " \"agent_scratchpad\"\r\n", - " ],\r\n", - " \"output_parser\": null,\r\n", - " \"template\": \"Answer the following questions as best you can. You have access to the following tools:\\n\\nSearch: A search engine. Useful for when you need to answer questions about current events. Input should be a search query.\\nCalculator: Useful for when you need to answer questions about math.\\n\\nUse the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [Search, Calculator]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\\n\\nBegin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}\",\r\n", - " \"template_format\": \"f-string\",\r\n", - " \"validate_template\": true,\r\n", - " \"_type\": \"prompt\"\r\n", - " },\r\n", - " \"llm\": {\r\n", - " \"model_name\": \"text-davinci-003\",\r\n", - " \"temperature\": 0.0,\r\n", - " \"max_tokens\": 256,\r\n", - " \"top_p\": 1,\r\n", - " \"frequency_penalty\": 0,\r\n", - " \"presence_penalty\": 0,\r\n", - " \"n\": 1,\r\n", - " \"best_of\": 1,\r\n", - " \"request_timeout\": null,\r\n", - " \"logit_bias\": {},\r\n", - " \"_type\": \"openai\"\r\n", - " },\r\n", - " \"output_key\": \"text\",\r\n", - " \"_type\": \"llm_chain\"\r\n", - " },\r\n", - " \"allowed_tools\": [\r\n", - " \"Search\",\r\n", - " \"Calculator\"\r\n", - " ],\r\n", - " \"return_values\": [\r\n", - " \"output\"\r\n", - " ],\r\n", - " \"_type\": \"zero-shot-react-description\"\r\n", - "}" - ] - } - ], - "source": [ - "!cat agent.json" - ] - }, - { - "cell_type": "markdown", - "id": "0eb72510", - "metadata": {}, - "source": [ - "We can now load the agent back in" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "eb660b76", - "metadata": {}, - "outputs": [], - "source": [ - "agent = initialize_agent(tools, llm, agent_path=\"agent.json\", verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aa624ea5", - "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 -} diff --git a/docs/modules/agents/implementations/natbot.py b/docs/modules/agents/implementations/natbot.py deleted file mode 100644 index 3eff76a0..00000000 --- a/docs/modules/agents/implementations/natbot.py +++ /dev/null @@ -1,87 +0,0 @@ -"""Run NatBot.""" -import time - -from langchain.chains.natbot.base import NatBotChain -from langchain.chains.natbot.crawler import Crawler - - -def run_cmd(cmd: str, _crawler: Crawler) -> None: - """Run command.""" - cmd = cmd.split("\n")[0] - - if cmd.startswith("SCROLL UP"): - _crawler.scroll("up") - elif cmd.startswith("SCROLL DOWN"): - _crawler.scroll("down") - elif cmd.startswith("CLICK"): - commasplit = cmd.split(",") - id = commasplit[0].split(" ")[1] - _crawler.click(id) - elif cmd.startswith("TYPE"): - spacesplit = cmd.split(" ") - id = spacesplit[1] - text_pieces = spacesplit[2:] - text = " ".join(text_pieces) - # Strip leading and trailing double quotes - text = text[1:-1] - - if cmd.startswith("TYPESUBMIT"): - text += "\n" - _crawler.type(id, text) - - time.sleep(2) - - -if __name__ == "__main__": - objective = "Make a reservation for 2 at 7pm at bistro vida in menlo park" - print("\nWelcome to natbot! What is your objective?") - i = input() - if len(i) > 0: - objective = i - quiet = False - nat_bot_chain = NatBotChain.from_default(objective) - _crawler = Crawler() - _crawler.go_to_page("google.com") - try: - while True: - browser_content = "\n".join(_crawler.crawl()) - llm_command = nat_bot_chain.execute(_crawler.page.url, browser_content) - if not quiet: - print("URL: " + _crawler.page.url) - print("Objective: " + objective) - print("----------------\n" + browser_content + "\n----------------\n") - if len(llm_command) > 0: - print("Suggested command: " + llm_command) - - command = input() - if command == "r" or command == "": - run_cmd(llm_command, _crawler) - elif command == "g": - url = input("URL:") - _crawler.go_to_page(url) - elif command == "u": - _crawler.scroll("up") - time.sleep(1) - elif command == "d": - _crawler.scroll("down") - time.sleep(1) - elif command == "c": - id = input("id:") - _crawler.click(id) - time.sleep(1) - elif command == "t": - id = input("id:") - text = input("text:") - _crawler.type(id, text) - time.sleep(1) - elif command == "o": - objective = input("Objective:") - else: - print( - "(g) to visit url\n(u) scroll up\n(d) scroll down\n(c) to click" - "\n(t) to type\n(h) to view commands again" - "\n(r/enter) to run suggested command\n(o) change objective" - ) - except KeyboardInterrupt: - print("\n[!] Ctrl+C detected, exiting gracefully.") - exit(0) diff --git a/docs/modules/agents/key_concepts.md b/docs/modules/agents/key_concepts.md deleted file mode 100644 index d53dc675..00000000 --- a/docs/modules/agents/key_concepts.md +++ /dev/null @@ -1,16 +0,0 @@ -# Key Concepts - -## Agents -Agents use an LLM to determine which actions to take and in what order. -For more detailed information on agents, and different types of agents in LangChain, see [this documentation](agents.md). - -## Tools -Tools are functions that agents can use to interact with the world. -These tools can be generic utilities (e.g. search), other chains, or even other agents. -For more detailed information on tools, and different types of tools in LangChain, see [this documentation](tools.md). - -## ToolKits -Toolkits are groups of tools that are best used together. -They allow you to logically group and initialize a set of tools that share a particular resource (such as a database connection or json object). -They can be used to construct an agent for a specific use-case. -For more detailed information on toolkits and their use cases, see [this documentation](how_to_guides.rst#agent-toolkits) (the "Agent Toolkits" section). \ No newline at end of file diff --git a/docs/modules/agents/toolkits.rst b/docs/modules/agents/toolkits.rst new file mode 100644 index 00000000..bf8fc0ad --- /dev/null +++ b/docs/modules/agents/toolkits.rst @@ -0,0 +1,18 @@ +Toolkits +============== + +.. note:: + `Conceptual Guide `_ + + +This section of documentation covers agents with toolkits - eg an agent applied to a particular use case. + +See below for a full list of agent toolkits + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./toolkits/examples/* + diff --git a/docs/modules/agents/agent_toolkits/csv.ipynb b/docs/modules/agents/toolkits/examples/csv.ipynb similarity index 100% rename from docs/modules/agents/agent_toolkits/csv.ipynb rename to docs/modules/agents/toolkits/examples/csv.ipynb diff --git a/docs/modules/agents/agent_toolkits/json.ipynb b/docs/modules/agents/toolkits/examples/json.ipynb similarity index 100% rename from docs/modules/agents/agent_toolkits/json.ipynb rename to docs/modules/agents/toolkits/examples/json.ipynb diff --git a/docs/modules/agents/agent_toolkits/openai_openapi.yml b/docs/modules/agents/toolkits/examples/openai_openapi.yml similarity index 100% rename from docs/modules/agents/agent_toolkits/openai_openapi.yml rename to docs/modules/agents/toolkits/examples/openai_openapi.yml diff --git a/docs/modules/agents/agent_toolkits/openapi.ipynb b/docs/modules/agents/toolkits/examples/openapi.ipynb similarity index 100% rename from docs/modules/agents/agent_toolkits/openapi.ipynb rename to docs/modules/agents/toolkits/examples/openapi.ipynb diff --git a/docs/modules/agents/agent_toolkits/pandas.ipynb b/docs/modules/agents/toolkits/examples/pandas.ipynb similarity index 100% rename from docs/modules/agents/agent_toolkits/pandas.ipynb rename to docs/modules/agents/toolkits/examples/pandas.ipynb diff --git a/docs/modules/agents/agent_toolkits/python.ipynb b/docs/modules/agents/toolkits/examples/python.ipynb similarity index 99% rename from docs/modules/agents/agent_toolkits/python.ipynb rename to docs/modules/agents/toolkits/examples/python.ipynb index 782e41f7..08128ea2 100644 --- a/docs/modules/agents/agent_toolkits/python.ipynb +++ b/docs/modules/agents/toolkits/examples/python.ipynb @@ -5,7 +5,7 @@ "id": "82a4c2cc-20ea-4b20-a565-63e905dee8ff", "metadata": {}, "source": [ - "## Python Agent\n", + "# Python Agent\n", "\n", "This notebook showcases an agent designed to write and execute python code to answer a question." ] diff --git a/docs/modules/agents/agent_toolkits/sql_database.ipynb b/docs/modules/agents/toolkits/examples/sql_database.ipynb similarity index 100% rename from docs/modules/agents/agent_toolkits/sql_database.ipynb rename to docs/modules/agents/toolkits/examples/sql_database.ipynb diff --git a/docs/modules/agents/agent_toolkits/titanic.csv b/docs/modules/agents/toolkits/examples/titanic.csv similarity index 100% rename from docs/modules/agents/agent_toolkits/titanic.csv rename to docs/modules/agents/toolkits/examples/titanic.csv diff --git a/docs/modules/agents/agent_toolkits/vectorstore.ipynb b/docs/modules/agents/toolkits/examples/vectorstore.ipynb similarity index 99% rename from docs/modules/agents/agent_toolkits/vectorstore.ipynb rename to docs/modules/agents/toolkits/examples/vectorstore.ipynb index 0e6a9505..046cae1f 100644 --- a/docs/modules/agents/agent_toolkits/vectorstore.ipynb +++ b/docs/modules/agents/toolkits/examples/vectorstore.ipynb @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "345bb078-4ec1-4e3a-827b-cd238c49054d", "metadata": { "tags": [] @@ -53,7 +53,7 @@ ], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "texts = text_splitter.split_documents(documents)\n", @@ -409,7 +409,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/agents/tools.rst b/docs/modules/agents/tools.rst new file mode 100644 index 00000000..8a0d46e1 --- /dev/null +++ b/docs/modules/agents/tools.rst @@ -0,0 +1,38 @@ +Tools +============= + +.. note:: + `Conceptual Guide `_ + + + +Tools are ways that an agent can use to interact with the outside world. + +For an overview of what a tool is, how to use them, and a full list of examples, please see the getting started documentation + +.. toctree:: + :maxdepth: 1 + :glob: + + ./tools/getting_started.md + +Next, we have some examples of customizing and generically working with tools + +.. toctree:: + :maxdepth: 1 + :glob: + + ./tools/custom_tools.ipynb + ./tools/multi_input_tool.ipynb + + +In this documentation we cover generic tooling functionality (eg how to create your own) +as well as examples of tools and how to use them. + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./tools/examples/* + diff --git a/docs/modules/agents/examples/custom_tools.ipynb b/docs/modules/agents/tools/custom_tools.ipynb similarity index 100% rename from docs/modules/agents/examples/custom_tools.ipynb rename to docs/modules/agents/tools/custom_tools.ipynb diff --git a/docs/modules/utils/examples/bash.ipynb b/docs/modules/agents/tools/examples/bash.ipynb similarity index 100% rename from docs/modules/utils/examples/bash.ipynb rename to docs/modules/agents/tools/examples/bash.ipynb diff --git a/docs/modules/utils/examples/bing_search.ipynb b/docs/modules/agents/tools/examples/bing_search.ipynb similarity index 100% rename from docs/modules/utils/examples/bing_search.ipynb rename to docs/modules/agents/tools/examples/bing_search.ipynb diff --git a/docs/modules/agents/examples/chatgpt_plugins.ipynb b/docs/modules/agents/tools/examples/chatgpt_plugins.ipynb similarity index 90% rename from docs/modules/agents/examples/chatgpt_plugins.ipynb rename to docs/modules/agents/tools/examples/chatgpt_plugins.ipynb index 2bb14b0e..d407e66b 100644 --- a/docs/modules/agents/examples/chatgpt_plugins.ipynb +++ b/docs/modules/agents/tools/examples/chatgpt_plugins.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "id": "d41405b5", "metadata": {}, "outputs": [], @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "id": "d9e61df5", "metadata": {}, "outputs": [], @@ -38,9 +38,11 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "edc0ea0e", - "metadata": {}, + "metadata": { + "scrolled": false + }, "outputs": [ { "name": "stdout", @@ -58,8 +60,8 @@ "Thought:\u001b[32;1m\u001b[1;3mI need to use the Klarna Shopping API to search for t shirts.\n", "Action: requests_get\n", "Action Input: https://www.klarna.com/us/shopping/public/openai/v0/products?q=t%20shirts\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3m{\"products\":[{\"name\":\"Lacoste Men's Pack of Plain T-Shirts\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3202043025/Clothing/Lacoste-Men-s-Pack-of-Plain-T-Shirts/?source=openai\",\"price\":\"$28.99\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White,Black\"]},{\"name\":\"Hanes Men's Ultimate 6pk. Crewneck T-Shirts\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3201808270/Clothing/Hanes-Men-s-Ultimate-6pk.-Crewneck-T-Shirts/?source=openai\",\"price\":\"$13.40\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White\"]},{\"name\":\"Nike Boy's Jordan Stretch T-shirts\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl359/3201863202/Children-s-Clothing/Nike-Boy-s-Jordan-Stretch-T-shirts/?source=openai\",\"price\":\"$14.99\",\"attributes\":[\"Color:White,Green\",\"Model:Boy\",\"Pattern:Solid Color\",\"Size (Small-Large):S,XL,L,M\"]},{\"name\":\"Polo Classic Fit Cotton V-Neck T-Shirts 3-Pack\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3203028500/Clothing/Polo-Classic-Fit-Cotton-V-Neck-T-Shirts-3-Pack/?source=openai\",\"price\":\"$29.95\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White,Blue,Black\"]},{\"name\":\"adidas Comfort T-shirts Men's 3-pack\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3202640533/Clothing/adidas-Comfort-T-shirts-Men-s-3-pack/?source=openai\",\"price\":\"$14.99\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White,Black\",\"Pattern:Solid Color\"]}]}\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3mThe available t shirts on Klarna are Lacoste Men's Pack of Plain T-Shirts, Hanes Men's Ultimate 6pk. Crewneck T-Shirts, Nike Boy's Jordan Stretch T-shirts, Polo Classic Fit Cotton V-Neck T-Shirts 3-Pack, and adidas Comfort T-shirts Men's 3-pack.\n", + "Observation: \u001b[36;1m\u001b[1;3m{\"products\":[{\"name\":\"Lacoste Men's Pack of Plain T-Shirts\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3202043025/Clothing/Lacoste-Men-s-Pack-of-Plain-T-Shirts/?source=openai\",\"price\":\"$28.02\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White,Black\"]},{\"name\":\"Hanes Men's Ultimate 6pk. Crewneck T-Shirts\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3201808270/Clothing/Hanes-Men-s-Ultimate-6pk.-Crewneck-T-Shirts/?source=openai\",\"price\":\"$13.82\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White\"]},{\"name\":\"Nike Boy's Jordan Stretch T-shirts\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl359/3201863202/Children-s-Clothing/Nike-Boy-s-Jordan-Stretch-T-shirts/?source=openai\",\"price\":\"$14.99\",\"attributes\":[\"Color:White,Green\",\"Model:Boy\",\"Pattern:Solid Color\",\"Size (Small-Large):S,XL,L,M\"]},{\"name\":\"Polo Classic Fit Cotton V-Neck T-Shirts 3-Pack\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3203028500/Clothing/Polo-Classic-Fit-Cotton-V-Neck-T-Shirts-3-Pack/?source=openai\",\"price\":\"$29.95\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White,Blue,Black\"]},{\"name\":\"adidas Comfort T-shirts Men's 3-pack\",\"url\":\"https://www.klarna.com/us/shopping/pl/cl10001/3202640533/Clothing/adidas-Comfort-T-shirts-Men-s-3-pack/?source=openai\",\"price\":\"$14.99\",\"attributes\":[\"Material:Cotton\",\"Target Group:Man\",\"Color:White,Black\",\"Pattern:Solid Color\",\"Neckline:Round\"]}]}\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3mThese are the available t shirts on Klarna: Lacoste Men's Pack of Plain T-Shirts, Hanes Men's Ultimate 6pk. Crewneck T-Shirts, Nike Boy's Jordan Stretch T-shirts, Polo Classic Fit Cotton V-Neck T-Shirts 3-Pack, and adidas Comfort T-shirts Men's 3-pack.\n", "Final Answer: The available t shirts on Klarna are Lacoste Men's Pack of Plain T-Shirts, Hanes Men's Ultimate 6pk. Crewneck T-Shirts, Nike Boy's Jordan Stretch T-shirts, Polo Classic Fit Cotton V-Neck T-Shirts 3-Pack, and adidas Comfort T-shirts Men's 3-pack.\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" @@ -71,18 +73,17 @@ "\"The available t shirts on Klarna are Lacoste Men's Pack of Plain T-Shirts, Hanes Men's Ultimate 6pk. Crewneck T-Shirts, Nike Boy's Jordan Stretch T-shirts, Polo Classic Fit Cotton V-Neck T-Shirts 3-Pack, and adidas Comfort T-shirts Men's 3-pack.\"" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "llm = ChatOpenAI(temperature=0)\n", + "llm = ChatOpenAI(temperature=0,)\n", "tools = load_tools([\"requests\"] )\n", "tools += [tool]\n", "\n", "agent_chain = initialize_agent(tools, llm, agent=\"zero-shot-react-description\", verbose=True)\n", - "\n", "agent_chain.run(\"what t shirts are available in klarna?\")" ] }, diff --git a/docs/modules/utils/examples/google_search.ipynb b/docs/modules/agents/tools/examples/google_search.ipynb similarity index 100% rename from docs/modules/utils/examples/google_search.ipynb rename to docs/modules/agents/tools/examples/google_search.ipynb diff --git a/docs/modules/utils/examples/google_serper.ipynb b/docs/modules/agents/tools/examples/google_serper.ipynb similarity index 100% rename from docs/modules/utils/examples/google_serper.ipynb rename to docs/modules/agents/tools/examples/google_serper.ipynb diff --git a/docs/modules/agents/examples/human_tools.ipynb b/docs/modules/agents/tools/examples/human_tools.ipynb similarity index 100% rename from docs/modules/agents/examples/human_tools.ipynb rename to docs/modules/agents/tools/examples/human_tools.ipynb diff --git a/docs/modules/utils/examples/ifttt.ipynb b/docs/modules/agents/tools/examples/ifttt.ipynb similarity index 96% rename from docs/modules/utils/examples/ifttt.ipynb rename to docs/modules/agents/tools/examples/ifttt.ipynb index ab21d190..c9d6a68b 100644 --- a/docs/modules/utils/examples/ifttt.ipynb +++ b/docs/modules/agents/tools/examples/ifttt.ipynb @@ -11,10 +11,10 @@ "\n", "From https://github.com/SidU/teams-langchain-js/wiki/Connecting-IFTTT-Services.\n", "\n", - "# Creating a webhook\n", + "## Creating a webhook\n", "- Go to https://ifttt.com/create\n", "\n", - "# Configuring the \"If This\"\n", + "## Configuring the \"If This\"\n", "- Click on the \"If This\" button in the IFTTT interface.\n", "- Search for \"Webhooks\" in the search bar.\n", "- Choose the first option for \"Receive a web request with a JSON payload.\"\n", @@ -24,7 +24,7 @@ "Event Name.\n", "- Click the \"Create Trigger\" button to save your settings and create your webhook.\n", "\n", - "# Configuring the \"Then That\"\n", + "## Configuring the \"Then That\"\n", "- Tap on the \"Then That\" button in the IFTTT interface.\n", "- Search for the service you want to connect, such as Spotify.\n", "- Choose an action from the service, such as \"Add track to a playlist\".\n", @@ -38,7 +38,7 @@ "- Congratulations! You have successfully connected the Webhook to the desired\n", "service, and you're ready to start receiving data and triggering actions 🎉\n", "\n", - "# Finishing up\n", + "## Finishing up\n", "- To get your webhook URL go to https://ifttt.com/maker_webhooks/settings\n", "- Copy the IFTTT key value from there. The URL is of the form\n", "https://maker.ifttt.com/use/YOUR_IFTTT_KEY. Grab the YOUR_IFTTT_KEY value.\n" diff --git a/docs/modules/utils/examples/python.ipynb b/docs/modules/agents/tools/examples/python.ipynb similarity index 100% rename from docs/modules/utils/examples/python.ipynb rename to docs/modules/agents/tools/examples/python.ipynb diff --git a/docs/modules/utils/examples/requests.ipynb b/docs/modules/agents/tools/examples/requests.ipynb similarity index 100% rename from docs/modules/utils/examples/requests.ipynb rename to docs/modules/agents/tools/examples/requests.ipynb diff --git a/docs/modules/agents/examples/search_tools.ipynb b/docs/modules/agents/tools/examples/search_tools.ipynb similarity index 100% rename from docs/modules/agents/examples/search_tools.ipynb rename to docs/modules/agents/tools/examples/search_tools.ipynb diff --git a/docs/modules/utils/examples/searx_search.ipynb b/docs/modules/agents/tools/examples/searx_search.ipynb similarity index 99% rename from docs/modules/utils/examples/searx_search.ipynb rename to docs/modules/agents/tools/examples/searx_search.ipynb index 9059af1a..a487984c 100644 --- a/docs/modules/utils/examples/searx_search.ipynb +++ b/docs/modules/agents/tools/examples/searx_search.ipynb @@ -73,7 +73,7 @@ "jukit_cell_id": "OHyurqUPbS" }, "source": [ - "# Custom Parameters\n", + "## Custom Parameters\n", "\n", "SearxNG supports up to [139 search engines](https://docs.searxng.org/admin/engines/configured_engines.html#configured-engines). You can also customize the Searx wrapper with arbitrary named parameters that will be passed to the Searx search API . In the below example we will making a more interesting use of custom search parameters from searx search api." ] @@ -104,7 +104,7 @@ "metadata": { "jukit_cell_id": "3FyQ6yHI8K", "tags": [ - "scroll-output" + "scroll-output" ] }, "outputs": [ @@ -161,7 +161,7 @@ "jukit_cell_id": "d0x164ssV1" }, "source": [ - "# Obtaining results with metadata" + "## Obtaining results with metadata" ] }, { @@ -192,7 +192,7 @@ "metadata": { "jukit_cell_id": "r7qUtvKNOh", "tags": [ - "scroll-output" + "scroll-output" ] }, "outputs": [ @@ -263,7 +263,7 @@ "metadata": { "jukit_cell_id": "JyNgoFm0vo", "tags": [ - "scroll-output" + "scroll-output" ] }, "outputs": [ @@ -444,7 +444,7 @@ "metadata": { "jukit_cell_id": "5NrlredKxM", "tags": [ - "scroll-output" + "scroll-output" ] }, "outputs": [ @@ -600,7 +600,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.11" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/utils/examples/serpapi.ipynb b/docs/modules/agents/tools/examples/serpapi.ipynb similarity index 100% rename from docs/modules/utils/examples/serpapi.ipynb rename to docs/modules/agents/tools/examples/serpapi.ipynb diff --git a/docs/modules/utils/examples/wolfram_alpha.ipynb b/docs/modules/agents/tools/examples/wolfram_alpha.ipynb similarity index 100% rename from docs/modules/utils/examples/wolfram_alpha.ipynb rename to docs/modules/agents/tools/examples/wolfram_alpha.ipynb diff --git a/docs/modules/utils/examples/zapier.ipynb b/docs/modules/agents/tools/examples/zapier.ipynb similarity index 99% rename from docs/modules/utils/examples/zapier.ipynb rename to docs/modules/agents/tools/examples/zapier.ipynb index 9a0e95ea..75ccd1cb 100644 --- a/docs/modules/utils/examples/zapier.ipynb +++ b/docs/modules/agents/tools/examples/zapier.ipynb @@ -5,7 +5,7 @@ "id": "16763ed3", "metadata": {}, "source": [ - "## Zapier Natural Language Actions API\n", + "# Zapier Natural Language Actions API\n", "\\\n", "Full docs here: https://nla.zapier.com/api/v1/docs\n", "\n", @@ -318,7 +318,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/agents/tools.md b/docs/modules/agents/tools/getting_started.md similarity index 97% rename from docs/modules/agents/tools.md rename to docs/modules/agents/tools/getting_started.md index 67dab1ec..8af18f3c 100644 --- a/docs/modules/agents/tools.md +++ b/docs/modules/agents/tools/getting_started.md @@ -1,4 +1,4 @@ -# Tools +# Getting Started Tools are functions that agents can use to interact with the world. These tools can be generic utilities (e.g. search), other chains, or even other agents. @@ -118,7 +118,7 @@ Below is a list of all supported tools and relevant information: - Notes: Uses the Google Custom Search API - Requires LLM: No - Extra Parameters: `google_api_key`, `google_cse_id` -- For more information on this, see [this page](../../ecosystem/google_search.md) +- For more information on this, see [this page](../../../ecosystem/google_search.md) **searx-search** @@ -135,7 +135,7 @@ Below is a list of all supported tools and relevant information: - Notes: Calls the [serper.dev](https://serper.dev) Google Search API and then parses results. - Requires LLM: No - Extra Parameters: `serper_api_key` -- For more information on this, see [this page](../../ecosystem/google_serper.md) +- For more information on this, see [this page](../../../ecosystem/google_serper.md) **wikipedia** diff --git a/docs/modules/agents/examples/multi_input_tool.ipynb b/docs/modules/agents/tools/multi_input_tool.ipynb similarity index 100% rename from docs/modules/agents/examples/multi_input_tool.ipynb rename to docs/modules/agents/tools/multi_input_tool.ipynb diff --git a/docs/modules/chains.rst b/docs/modules/chains.rst index a23fead3..ce0daf19 100644 --- a/docs/modules/chains.rst +++ b/docs/modules/chains.rst @@ -1,6 +1,10 @@ Chains ========================== +.. note:: + `Conceptual Guide `_ + + Using an LLM in isolation is fine for some simple applications, but many more complex ones require chaining LLMs - either with each other or with other experts. LangChain provides a standard interface for Chains, as well as some common implementations of chains for ease of use. @@ -9,8 +13,6 @@ The following sections of documentation are provided: - `Getting Started <./chains/getting_started.html>`_: A getting started guide for chains, to get you up and running quickly. -- `Key Concepts <./chains/key_concepts.html>`_: A conceptual guide going over the various concepts related to chains. - - `How-To Guides <./chains/how_to_guides.html>`_: A collection of how-to guides. These highlight how to use various types of chains. - `Reference <../reference/modules/chains.html>`_: API reference documentation for all Chain classes. @@ -25,5 +27,4 @@ The following sections of documentation are provided: ./chains/getting_started.ipynb ./chains/how_to_guides.rst - ./chains/key_concepts.rst Reference<../reference/modules/chains.rst> diff --git a/docs/modules/chains/async_chain.ipynb b/docs/modules/chains/generic/async_chain.ipynb similarity index 100% rename from docs/modules/chains/async_chain.ipynb rename to docs/modules/chains/generic/async_chain.ipynb diff --git a/docs/modules/chains/generic/from_hub.ipynb b/docs/modules/chains/generic/from_hub.ipynb index b88d2fc3..84ee95c0 100644 --- a/docs/modules/chains/generic/from_hub.ipynb +++ b/docs/modules/chains/generic/from_hub.ipynb @@ -34,10 +34,10 @@ "text": [ "\n", "\n", - "\u001B[1m> Entering new LLMMathChain chain...\u001B[0m\n", - "whats 2 raised to .12\u001B[32;1m\u001B[1;3m\n", - "Answer: 1.0791812460476249\u001B[0m\n", - "\u001B[1m> Finished chain.\u001B[0m\n" + "\u001b[1m> Entering new LLMMathChain chain...\u001b[0m\n", + "whats 2 raised to .12\u001b[32;1m\u001b[1;3m\n", + "Answer: 1.0791812460476249\u001b[0m\n", + "\u001b[1m> Finished chain.\u001b[0m\n" ] }, { diff --git a/docs/modules/chains/generic/transformation.ipynb b/docs/modules/chains/generic/transformation.ipynb index b770f06c..dcb46f21 100644 --- a/docs/modules/chains/generic/transformation.ipynb +++ b/docs/modules/chains/generic/transformation.ipynb @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open('../../state_of_the_union.txt') as f:\n", + "with open(\"../../state_of_the_union.txt\") as f:\n", " state_of_the_union = f.read()" ] }, @@ -122,7 +122,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/chains/generic_how_to.rst b/docs/modules/chains/generic_how_to.rst deleted file mode 100644 index fe921585..00000000 --- a/docs/modules/chains/generic_how_to.rst +++ /dev/null @@ -1,33 +0,0 @@ -Generic Chains --------------- - -A chain is made up of links, which can be either primitives or other chains. -Primitives can be either `prompts <../prompts.html>`_, `llms <../llms.html>`_, `utils <../utils.html>`_, or other chains. -The examples here are all generic end-to-end chains that are meant to be used to construct other chains rather than serving a specific purpose. - -**LLMChain** - -- **Links Used**: PromptTemplate, LLM -- **Notes**: This chain is the simplest chain, and is widely used by almost every other chain. This chain takes arbitrary user input, creates a prompt with it from the PromptTemplate, passes that to the LLM, and then returns the output of the LLM as the final output. -- `Example Notebook <./generic/llm_chain.html>`_ - -**Transformation Chain** - -- **Links Used**: TransformationChain -- **Notes**: This notebook shows how to use the Transformation Chain, which takes an arbitrary python function and applies it to inputs/outputs of other chains. -- `Example Notebook <./generic/transformation.html>`_ - -**Sequential Chain** - -- **Links Used**: Sequential -- **Notes**: This notebook shows how to combine calling multiple other chains in sequence. -- `Example Notebook <./generic/sequential_chains.html>`_ - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Generic Chains - :name: generic - :hidden: - - ./generic/* \ No newline at end of file diff --git a/docs/modules/chains/how_to_guides.rst b/docs/modules/chains/how_to_guides.rst index 6fad1fcc..6499de65 100644 --- a/docs/modules/chains/how_to_guides.rst +++ b/docs/modules/chains/how_to_guides.rst @@ -2,23 +2,37 @@ How-To Guides ============= A chain is made up of links, which can be either primitives or other chains. -Primitives can be either `prompts <../prompts.html>`_, `llms <../llms.html>`_, `utils <../utils.html>`_, or other chains. -The examples here are all end-to-end chains for specific applications. -They are broken up into three categories: +Primitives can be either `prompts <../prompts.html>`_, `models <../models.html>`_, arbitrary functions, or other chains. +The examples here are broken up into three sections: -1. `Generic Chains <./generic_how_to.html>`_: Generic chains, that are meant to help build other chains rather than serve a particular purpose. -2. `Utility Chains <./utility_how_to.html>`_: Chains consisting of an LLMChain interacting with a specific util. -3. `Asynchronous <./async_chain.html>`_: Covering asynchronous functionality. +**Generic Functionality** + +Covers both generic chains (that are useful in a wide variety of applications) as well as generic functionality related to those chains. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./generic/* + +**Index-related Chains** + +Chains related to working with indexes. .. toctree:: :maxdepth: 1 :glob: - :hidden: - ./generic_how_to.rst - ./utility_how_to.rst - ./async_chain.ipynb + ./index_examples/* + + +**All other chains** + +All other types of chains! + +.. toctree:: + :maxdepth: 1 + :glob: -In addition to different types of chains, we also have the following how-to guides for working with chains in general: + ./examples/* -`Load From Hub <./generic/from_hub.html>`_: This notebook covers how to load chains from `LangChainHub `_. diff --git a/docs/modules/indexes/chain_examples/analyze_document.ipynb b/docs/modules/chains/index_examples/analyze_document.ipynb similarity index 98% rename from docs/modules/indexes/chain_examples/analyze_document.ipynb rename to docs/modules/chains/index_examples/analyze_document.ipynb index f451b3da..5f8f50f2 100644 --- a/docs/modules/indexes/chain_examples/analyze_document.ipynb +++ b/docs/modules/chains/index_examples/analyze_document.ipynb @@ -17,7 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open('../../state_of_the_union.txt') as f:\n", + "with open(\"../../state_of_the_union.txt\") as f:\n", " state_of_the_union = f.read()" ] }, @@ -170,7 +170,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/indexes/chain_examples/chat_vector_db.ipynb b/docs/modules/chains/index_examples/chat_vector_db.ipynb similarity index 99% rename from docs/modules/indexes/chain_examples/chat_vector_db.ipynb rename to docs/modules/chains/index_examples/chat_vector_db.ipynb index 8d6adc9e..c47d4833 100644 --- a/docs/modules/indexes/chain_examples/chat_vector_db.ipynb +++ b/docs/modules/chains/index_examples/chat_vector_db.ipynb @@ -44,7 +44,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader(\"../../state_of_the_union.txt\")\n", "documents = loader.load()" ] }, diff --git a/docs/modules/indexes/chain_examples/graph_qa.ipynb b/docs/modules/chains/index_examples/graph_qa.ipynb similarity index 100% rename from docs/modules/indexes/chain_examples/graph_qa.ipynb rename to docs/modules/chains/index_examples/graph_qa.ipynb diff --git a/docs/modules/indexes/examples/hyde.ipynb b/docs/modules/chains/index_examples/hyde.ipynb similarity index 97% rename from docs/modules/indexes/examples/hyde.ipynb rename to docs/modules/chains/index_examples/hyde.ipynb index 430db5ba..76189a76 100644 --- a/docs/modules/indexes/examples/hyde.ipynb +++ b/docs/modules/chains/index_examples/hyde.ipynb @@ -105,7 +105,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "id": "1da90437", "metadata": {}, @@ -169,7 +168,7 @@ "from langchain.text_splitter import CharacterTextSplitter\n", "from langchain.vectorstores import Chroma\n", "\n", - "with open('../../state_of_the_union.txt') as f:\n", + "with open(\"../../state_of_the_union.txt\") as f:\n", " state_of_the_union = f.read()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "texts = text_splitter.split_text(state_of_the_union)" @@ -236,7 +235,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -250,7 +249,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.12 (main, Mar 26 2022, 15:51:15) \n[Clang 13.1.6 (clang-1316.0.21.2)]" + "version": "3.9.1" }, "vscode": { "interpreter": { diff --git a/docs/modules/indexes/chain_examples/qa_with_sources.ipynb b/docs/modules/chains/index_examples/qa_with_sources.ipynb similarity index 99% rename from docs/modules/indexes/chain_examples/qa_with_sources.ipynb rename to docs/modules/chains/index_examples/qa_with_sources.ipynb index 70e570f7..7fc94d08 100644 --- a/docs/modules/indexes/chain_examples/qa_with_sources.ipynb +++ b/docs/modules/chains/index_examples/qa_with_sources.ipynb @@ -42,7 +42,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open('../../state_of_the_union.txt') as f:\n", + "with open(\"../../state_of_the_union.txt\") as f:\n", " state_of_the_union = f.read()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "texts = text_splitter.split_text(state_of_the_union)\n", diff --git a/docs/modules/indexes/chain_examples/question_answering.ipynb b/docs/modules/chains/index_examples/question_answering.ipynb similarity index 99% rename from docs/modules/indexes/chain_examples/question_answering.ipynb rename to docs/modules/chains/index_examples/question_answering.ipynb index 4820b5d6..e3ccd3c6 100644 --- a/docs/modules/indexes/chain_examples/question_answering.ipynb +++ b/docs/modules/chains/index_examples/question_answering.ipynb @@ -61,7 +61,7 @@ ], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader(\"../../state_of_the_union.txt\")\n", "docsearch = index_creator.from_loaders([loader])" ] }, diff --git a/docs/modules/indexes/chain_examples/summarize.ipynb b/docs/modules/chains/index_examples/summarize.ipynb similarity index 99% rename from docs/modules/indexes/chain_examples/summarize.ipynb rename to docs/modules/chains/index_examples/summarize.ipynb index f1d77c67..75dbd6ca 100644 --- a/docs/modules/indexes/chain_examples/summarize.ipynb +++ b/docs/modules/chains/index_examples/summarize.ipynb @@ -43,7 +43,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open('../../state_of_the_union.txt') as f:\n", + "with open(\"../../state_of_the_union.txt\") as f:\n", " state_of_the_union = f.read()\n", "texts = text_splitter.split_text(state_of_the_union)" ] diff --git a/docs/modules/indexes/chain_examples/vector_db_qa.ipynb b/docs/modules/chains/index_examples/vector_db_qa.ipynb similarity index 99% rename from docs/modules/indexes/chain_examples/vector_db_qa.ipynb rename to docs/modules/chains/index_examples/vector_db_qa.ipynb index e5a1b8f6..0e300121 100644 --- a/docs/modules/indexes/chain_examples/vector_db_qa.ipynb +++ b/docs/modules/chains/index_examples/vector_db_qa.ipynb @@ -41,7 +41,7 @@ ], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader(\"../../state_of_the_union.txt\")\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "texts = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/chain_examples/vector_db_qa_with_sources.ipynb b/docs/modules/chains/index_examples/vector_db_qa_with_sources.ipynb similarity index 99% rename from docs/modules/indexes/chain_examples/vector_db_qa_with_sources.ipynb rename to docs/modules/chains/index_examples/vector_db_qa_with_sources.ipynb index d921b794..9354f3cf 100644 --- a/docs/modules/indexes/chain_examples/vector_db_qa_with_sources.ipynb +++ b/docs/modules/chains/index_examples/vector_db_qa_with_sources.ipynb @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open('../../state_of_the_union.txt') as f:\n", + "with open(\"../../state_of_the_union.txt\") as f:\n", " state_of_the_union = f.read()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "texts = text_splitter.split_text(state_of_the_union)\n", diff --git a/docs/modules/indexes/chain_examples/vector_db_text_generation.ipynb b/docs/modules/chains/index_examples/vector_db_text_generation.ipynb similarity index 100% rename from docs/modules/indexes/chain_examples/vector_db_text_generation.ipynb rename to docs/modules/chains/index_examples/vector_db_text_generation.ipynb diff --git a/docs/modules/chains/key_concepts.md b/docs/modules/chains/key_concepts.md deleted file mode 100644 index 3e781870..00000000 --- a/docs/modules/chains/key_concepts.md +++ /dev/null @@ -1,20 +0,0 @@ -# Key Concepts - -## Chains -A chain is made up of links, which can be either primitives or other chains. -They vary greatly in complexity and are combination of generic, highly configurable pipelines and more narrow (but usually more complex) pipelines. - -## Sequential Chain -This is a specific type of chain where multiple other chains are run in sequence, with the outputs being added as inputs -to the next. A subtype of this type of chain is the [`SimpleSequentialChain`](./generic/sequential_chains.html#simplesequentialchain), where all subchains have only one input and one output, -and the output of one is therefore used as sole input to the next chain. - -## Prompt Selectors -One thing that we've noticed is that the best prompt to use is really dependent on the model you use. -Some prompts work really good with some models, but not great with others. -One of our goals is provide good chains that "just work" out of the box. -A big part of chains like that is having prompts that "just work". -So rather than having a default prompt for chains, we are moving towards a paradigm where if a prompt is not explicitly -provided we select one with a PromptSelector. This class takes in the model passed in, and returns a default prompt. -The inner workings of the PromptSelector can look at any aspect of the model - LLM vs ChatModel, OpenAI vs Cohere, GPT3 vs GPT4, etc. -Due to this being a newer feature, this may not be implemented for all chains, but this is the direction we are moving. diff --git a/docs/modules/chains/utility_how_to.rst b/docs/modules/chains/utility_how_to.rst deleted file mode 100644 index 0c07e1fa..00000000 --- a/docs/modules/chains/utility_how_to.rst +++ /dev/null @@ -1,65 +0,0 @@ -Utility Chains --------------- - -A chain is made up of links, which can be either primitives or other chains. -Primitives can be either `prompts <../prompts.html>`_, `llms <../llms.html>`_, `utils <../utils.html>`_, or other chains. -The examples here are all end-to-end chains for specific applications, focused on interacting an LLMChain with a specific utility. - -**LLMMath** - -- **Links Used**: Python REPL, LLMChain -- **Notes**: This chain takes user input (a math question), uses an LLMChain to convert it to python code snippet to run in the Python REPL, and then returns that as the result. -- `Example Notebook <./examples/llm_math.html>`_ - -**PAL** - -- **Links Used**: Python REPL, LLMChain -- **Notes**: This chain takes user input (a reasoning question), uses an LLMChain to convert it to python code snippet to run in the Python REPL, and then returns that as the result. -- `Paper `_ -- `Example Notebook <./examples/pal.html>`_ - -**SQLDatabase Chain** - -- **Links Used**: SQLDatabase, LLMChain -- **Notes**: This chain takes user input (a question), uses a first LLM chain to construct a SQL query to run against the SQL database, and then uses another LLMChain to take the results of that query and use it to answer the original question. -- `Example Notebook <./examples/sqlite.html>`_ - -**API Chain** - -- **Links Used**: LLMChain, Requests -- **Notes**: This chain first uses a LLM to construct the url to hit, then makes that request with the Requests wrapper, and finally runs that result through the language model again in order to product a natural language response. -- `Example Notebook <./examples/api.html>`_ - -**LLMBash Chain** - -- **Links Used**: BashProcess, LLMChain -- **Notes**: This chain takes user input (a question), uses an LLM chain to convert it to a bash command to run in the terminal, and then returns that as the result. -- `Example Notebook <./examples/llm_bash.html>`_ - -**LLMChecker Chain** - -- **Links Used**: LLMChain -- **Notes**: This chain takes user input (a question), uses an LLM chain to answer that question, and then uses other LLMChains to self-check that answer. -- `Example Notebook <./examples/llm_checker.html>`_ - -**LLMRequests Chain** - -- **Links Used**: Requests, LLMChain -- **Notes**: This chain takes a URL and other inputs, uses Requests to get the data at that URL, and then passes that along with the other inputs into an LLMChain to generate a response. The example included shows how to ask a question to Google - it firsts constructs a Google url, then fetches the data there, then passes that data + the original question into an LLMChain to get an answer. -- `Example Notebook <./examples/llm_requests.html>`_ - -**Moderation Chain** - -- **Links Used**: LLMChain, ModerationChain -- **Notes**: This chain shows how to use OpenAI's content moderation endpoint to screen output, and shows how to connect this to an LLMChain. -- `Example Notebook <./examples/moderation.html>`_ - - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Generic Chains - :name: generic - :hidden: - - ./examples/* \ No newline at end of file diff --git a/docs/modules/chat/examples/agent.ipynb b/docs/modules/chat/examples/agent.ipynb deleted file mode 100644 index 9a72abb9..00000000 --- a/docs/modules/chat/examples/agent.ipynb +++ /dev/null @@ -1,208 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e58f4d5a", - "metadata": {}, - "source": [ - "# Agent\n", - "This notebook covers how to create a custom agent for a chat model. It will utilize chat specific prompts." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "5268c7fa", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.agents import ZeroShotAgent, Tool, AgentExecutor\n", - "from langchain.chains import LLMChain\n", - "from langchain.utilities import SerpAPIWrapper" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "fbaa4dbe", - "metadata": {}, - "outputs": [], - "source": [ - "search = SerpAPIWrapper()\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", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "f3ba6f08", - "metadata": {}, - "outputs": [], - "source": [ - "prefix = \"\"\"Answer the following questions as best you can, but speaking as a pirate might speak. You have access to the following tools:\"\"\"\n", - "suffix = \"\"\"Begin! Remember to speak as a pirate when giving your final answer. Use lots of \"Args\"\"\"\n", - "\n", - "prompt = ZeroShotAgent.create_prompt(\n", - " tools, \n", - " prefix=prefix, \n", - " suffix=suffix, \n", - " input_variables=[]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "3547a37d", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.prompts.chat import (\n", - " ChatPromptTemplate,\n", - " SystemMessagePromptTemplate,\n", - " AIMessagePromptTemplate,\n", - " HumanMessagePromptTemplate,\n", - ")\n", - "from langchain.schema import (\n", - " AIMessage,\n", - " HumanMessage,\n", - " SystemMessage\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "a78f886f", - "metadata": {}, - "outputs": [], - "source": [ - "messages = [\n", - " SystemMessagePromptTemplate(prompt=prompt),\n", - " HumanMessagePromptTemplate.from_template(\"{input}\\n\\nThis was your previous work \"\n", - " f\"(but I haven't seen any of it! I only see what \"\n", - " \"you return as final answer):\\n{agent_scratchpad}\")\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "dadadd70", - "metadata": {}, - "outputs": [], - "source": [ - "prompt = ChatPromptTemplate.from_messages(messages)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "b7180182", - "metadata": {}, - "outputs": [], - "source": [ - "llm_chain = LLMChain(llm=ChatOpenAI(temperature=0), prompt=prompt)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ddddb07b", - "metadata": {}, - "outputs": [], - "source": [ - "tool_names = [tool.name for tool in tools]\n", - "agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "36aef054", - "metadata": {}, - "outputs": [], - "source": [ - "agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "33a4d6cc", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\u001b[32;1m\u001b[1;3mArrr, ye be in luck, matey! I'll find ye the answer to yer question.\n", - "\n", - "Thought: I need to search for the current population of Canada.\n", - "Action: Search\n", - "Action Input: \"current population of Canada 2023\"\n", - "\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3mThe current population of Canada is 38,623,091 as of Saturday, March 4, 2023, based on Worldometer elaboration of the latest United Nations data.\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3mAhoy, me hearties! I've found the answer to yer question.\n", - "\n", - "Final Answer: As of March 4, 2023, the population of Canada be 38,623,091. Arrr!\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'As of March 4, 2023, the population of Canada be 38,623,091. Arrr!'" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "agent_executor.run(\"How many people live in canada as of 2023?\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6aefe978", - "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 -} diff --git a/docs/modules/chat/examples/chat_vector_db.ipynb b/docs/modules/chat/examples/chat_vector_db.ipynb deleted file mode 100644 index a2a964f7..00000000 --- a/docs/modules/chat/examples/chat_vector_db.ipynb +++ /dev/null @@ -1,376 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "134a0785", - "metadata": {}, - "source": [ - "# Chat Vector DB\n", - "\n", - "This notebook goes over how to set up a chat model to chat with a vector database.\n", - "\n", - "This notebook is very similar to the example of using an LLM in the ConversationalRetrievalChain. The only differences here are (1) using a ChatModel, and (2) passing in a ChatPromptTemplate (optimized for chat models)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "70c4e529", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from langchain.embeddings.openai import OpenAIEmbeddings\n", - "from langchain.vectorstores import Chroma\n", - "from langchain.text_splitter import CharacterTextSplitter\n", - "from langchain.chains import ConversationalRetrievalChain" - ] - }, - { - "cell_type": "markdown", - "id": "cdff94be", - "metadata": {}, - "source": [ - "Load in documents. You can replace this with a loader for whatever type of data you want" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "01c46e92", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", - "documents = loader.load()" - ] - }, - { - "cell_type": "markdown", - "id": "e9be4779", - "metadata": {}, - "source": [ - "If you had multiple loaders that you wanted to combine, you do something like:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "433363a5", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# loaders = [....]\n", - "# docs = []\n", - "# for loader in loaders:\n", - "# docs.extend(loader.load())" - ] - }, - { - "cell_type": "markdown", - "id": "239475d2", - "metadata": {}, - "source": [ - "We now split the documents, create embeddings for them, and put them in a vectorstore. This allows us to do semantic search over them." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "a8930cf7", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running Chroma using direct local API.\n", - "Using DuckDB in-memory for database. Data will be transient.\n" - ] - } - ], - "source": [ - "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", - "documents = text_splitter.split_documents(documents)\n", - "\n", - "embeddings = OpenAIEmbeddings()\n", - "vectorstore = Chroma.from_documents(documents, embeddings)" - ] - }, - { - "cell_type": "markdown", - "id": "18415aca", - "metadata": {}, - "source": [ - "We are now going to construct a prompt specifically designed for chat models." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "c8805230", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.prompts.chat import (\n", - " ChatPromptTemplate,\n", - " SystemMessagePromptTemplate,\n", - " AIMessagePromptTemplate,\n", - " HumanMessagePromptTemplate,\n", - ")\n", - "from langchain.schema import (\n", - " AIMessage,\n", - " HumanMessage,\n", - " SystemMessage\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "cc86c30e", - "metadata": {}, - "outputs": [], - "source": [ - "system_template=\"\"\"Use the following pieces of context to answer the users question. \n", - "If you don't know the answer, just say that you don't know, don't try to make up an answer.\n", - "----------------\n", - "{context}\"\"\"\n", - "messages = [\n", - " SystemMessagePromptTemplate.from_template(system_template),\n", - " HumanMessagePromptTemplate.from_template(\"{question}\")\n", - "]\n", - "prompt = ChatPromptTemplate.from_messages(messages)" - ] - }, - { - "cell_type": "markdown", - "id": "3c96b118", - "metadata": {}, - "source": [ - "We now initialize the ConversationalRetrievalChain" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "7b4110f3", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "qa = ConversationalRetrievalChain.from_llm(ChatOpenAI(temperature=0), vectorstore,qa_prompt=prompt)" - ] - }, - { - "cell_type": "markdown", - "id": "3872432d", - "metadata": {}, - "source": [ - "Here's an example of asking a question with no chat history" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "7fe3e730", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "chat_history = []\n", - "query = \"What did the president say about Ketanji Brown Jackson\"\n", - "result = qa({\"question\": query, \"chat_history\": chat_history})" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "bfff9cc8", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "\"The President nominated Circuit Court of Appeals Judge Ketanji Brown Jackson to serve on the United States Supreme Court. He described her as one of the nation's top legal minds, a former top litigator in private practice, a former federal public defender, and a consensus builder. She has received a broad range of support from the Fraternal Order of Police to former judges appointed by Democrats and Republicans.\"" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result[\"answer\"]" - ] - }, - { - "cell_type": "markdown", - "id": "9e46edf7", - "metadata": {}, - "source": [ - "Here's an example of asking a question with some chat history" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "00b4cf00", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "chat_history = [(query, result[\"answer\"])]\n", - "query = \"Did he mention who came before her\"\n", - "result = qa({\"question\": query, \"chat_history\": chat_history})" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "f01828d1", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "\"The President mentioned Circuit Court of Appeals Judge Ketanji Brown Jackson as the nominee for the United States Supreme Court. He described her as one of the nation's top legal minds who will continue Justice Breyer's legacy of excellence. The President did not mention any specific sources of support for Judge Jackson, but he did note that advancing immigration reform is supported by everyone from labor unions to religious leaders to the U.S. Chamber of Commerce.\"" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result['answer']" - ] - }, - { - "cell_type": "markdown", - "id": "2324cdc6-98bf-4708-b8cd-02a98b1e5b67", - "metadata": {}, - "source": [ - "## ConversationalRetrievalChain with streaming to `stdout`\n", - "\n", - "Output from the chain will be streamed to `stdout` token by token in this example." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "2efacec3-2690-4b05-8de3-a32fd2ac3911", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from langchain.chains.llm import LLMChain\n", - "from langchain.llms import OpenAI\n", - "from langchain.callbacks.base import CallbackManager\n", - "from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n", - "from langchain.chains.chat_index.prompts import CONDENSE_QUESTION_PROMPT\n", - "from langchain.chains.question_answering import load_qa_chain\n", - "\n", - "# Construct a ChatVectorDBChain with a streaming llm for combine docs\n", - "# and a separate, non-streaming llm for question generation\n", - "llm = OpenAI(temperature=0)\n", - "streaming_llm = ChatOpenAI(streaming=True, callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]), verbose=True, temperature=0)\n", - "\n", - "question_generator = LLMChain(llm=llm, prompt=CONDENSE_QUESTION_PROMPT)\n", - "doc_chain = load_qa_chain(streaming_llm, chain_type=\"stuff\", prompt=prompt)\n", - "\n", - "qa = ConversationalRetrievalChain(retriever=vectorstore.as_retriever(), combine_docs_chain=doc_chain, question_generator=question_generator)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "fd6d43f4-7428-44a4-81bc-26fe88a98762", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The President nominated Circuit Court of Appeals Judge Ketanji Brown Jackson to serve on the United States Supreme Court. He described her as one of the nation's top legal minds, a former top litigator in private practice, a former federal public defender, and a consensus builder. He also mentioned that she has received a broad range of support from the Fraternal Order of Police to former judges appointed by Democrats and Republicans." - ] - } - ], - "source": [ - "chat_history = []\n", - "query = \"What did the president say about Ketanji Brown Jackson\"\n", - "result = qa({\"question\": query, \"chat_history\": chat_history})" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "5ab38978-f3e8-4fa7-808c-c79dec48379a", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The context does not provide information on who Ketanji Brown Jackson succeeded on the United States Supreme Court." - ] - } - ], - "source": [ - "chat_history = [(query, result[\"answer\"])]\n", - "query = \"Did he mention who she suceeded\"\n", - "result = qa({\"question\": query, \"chat_history\": chat_history})\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8e8d0055", - "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 -} diff --git a/docs/modules/chat/examples/memory.ipynb b/docs/modules/chat/examples/memory.ipynb deleted file mode 100644 index b3e944e3..00000000 --- a/docs/modules/chat/examples/memory.ipynb +++ /dev/null @@ -1,192 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9a9350a6", - "metadata": {}, - "source": [ - "# Memory\n", - "This notebook goes over how to use Memory with chat models. The main difference between this and Memory for LLMs is that rather than trying to condense all previous messages into a string, we can keep them as their own unique memory object." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "110935ae", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import (\n", - " ChatPromptTemplate, \n", - " MessagesPlaceholder, \n", - " SystemMessagePromptTemplate, \n", - " HumanMessagePromptTemplate\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "161b6629", - "metadata": {}, - "outputs": [], - "source": [ - "prompt = ChatPromptTemplate.from_messages([\n", - " SystemMessagePromptTemplate.from_template(\"The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\"),\n", - " MessagesPlaceholder(variable_name=\"history\"),\n", - " HumanMessagePromptTemplate.from_template(\"{input}\")\n", - "])" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "4976fbda", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chains import ConversationChain\n", - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.memory import ConversationBufferMemory" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "12a0bea6", - "metadata": {}, - "outputs": [], - "source": [ - "llm = ChatOpenAI(temperature=0)" - ] - }, - { - "cell_type": "markdown", - "id": "f6edcd6a", - "metadata": {}, - "source": [ - "We can now initialize the memory. Note that we set `return_messages=True` To denote that this should return a list of messages when appropriate" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "f55bea38", - "metadata": {}, - "outputs": [], - "source": [ - "memory = ConversationBufferMemory(return_messages=True)" - ] - }, - { - "cell_type": "markdown", - "id": "737e8c78", - "metadata": {}, - "source": [ - "We can now use this in the rest of the chain." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "80152db7", - "metadata": {}, - "outputs": [], - "source": [ - "conversation = ConversationChain(memory=memory, prompt=prompt, llm=llm)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "ac68e766", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Hello! How can I assist you today?'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"Hi there!\")" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "babb33d0", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\"That sounds like fun! I'm happy to chat with you. Is there anything specific you'd like to talk about?\"" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"I'm doing well! Just having a conversation with an AI.\")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "36f8a1dc", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\"Sure! I am an AI language model created by OpenAI. I was trained on a large dataset of text from the internet, which allows me to understand and generate human-like language. I can answer questions, provide information, and even have conversations like this one. Is there anything else you'd like to know about me?\"" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"Tell me about yourself.\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "79fb460b", - "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 -} diff --git a/docs/modules/chat/examples/vector_db_qa.ipynb b/docs/modules/chat/examples/vector_db_qa.ipynb deleted file mode 100644 index 368af6e3..00000000 --- a/docs/modules/chat/examples/vector_db_qa.ipynb +++ /dev/null @@ -1,169 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "07c1e3b9", - "metadata": {}, - "source": [ - "# Retrieval Question/Answering\n", - "\n", - "This example showcases using a chat model to do question answering over a vector database.\n", - "\n", - "This notebook is very similar to the example of using an LLM in the RetrievalQA. The only differences here are (1) using a ChatModel, and (2) passing in a ChatPromptTemplate (optimized for chat models)." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "82525493", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.embeddings.openai import OpenAIEmbeddings\n", - "from langchain.vectorstores import Chroma\n", - "from langchain.text_splitter import CharacterTextSplitter\n", - "from langchain.chains import RetrievalQA" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "5c7049db", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running Chroma using direct local API.\n", - "Using DuckDB in-memory for database. Data will be transient.\n" - ] - } - ], - "source": [ - "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", - "documents = loader.load()\n", - "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", - "texts = text_splitter.split_documents(documents)\n", - "\n", - "embeddings = OpenAIEmbeddings()\n", - "docsearch = Chroma.from_documents(texts, embeddings)" - ] - }, - { - "cell_type": "markdown", - "id": "35f99145", - "metadata": {}, - "source": [ - "We can now set up the chat model and chat model specific prompt" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "32a49412", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.prompts.chat import (\n", - " ChatPromptTemplate,\n", - " SystemMessagePromptTemplate,\n", - " AIMessagePromptTemplate,\n", - " HumanMessagePromptTemplate,\n", - ")\n", - "from langchain.schema import (\n", - " AIMessage,\n", - " HumanMessage,\n", - " SystemMessage\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "f231fb9b", - "metadata": {}, - "outputs": [], - "source": [ - "system_template=\"\"\"Use the following pieces of context to answer the users question. \n", - "If you don't know the answer, just say that you don't know, don't try to make up an answer.\n", - "----------------\n", - "{context}\"\"\"\n", - "messages = [\n", - " SystemMessagePromptTemplate.from_template(system_template),\n", - " HumanMessagePromptTemplate.from_template(\"{question}\")\n", - "]\n", - "prompt = ChatPromptTemplate.from_messages(messages)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "3018f865", - "metadata": {}, - "outputs": [], - "source": [ - "chain_type_kwargs = {\"prompt\": prompt}\n", - "qa = RetrievalQA.from_chain_type(llm=ChatOpenAI(), chain_type=\"stuff\", retriever=docsearch.as_retriever(), chain_type_kwargs=chain_type_kwargs)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "032a47f8", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\"The president nominated Ketanji Brown Jackson to serve on the United States Supreme Court. He referred to her as one of our nation's top legal minds, a former federal public defender, a consensus builder, and from a family of public school educators and police officers. Since she's been nominated, she has received a broad range of support from the Fraternal Order of Police to former judges appointed by Democrats and Republicans.\"" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "query = \"What did the president say about Ketanji Brown Jackson\"\n", - "qa.run(query)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8b403637", - "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" - }, - "vscode": { - "interpreter": { - "hash": "b1677b440931f40d89ef8be7bf03acb108ce003de0ac9b18e8d43753ea2e7103" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/modules/chat/examples/vector_db_qa_with_sources.ipynb b/docs/modules/chat/examples/vector_db_qa_with_sources.ipynb deleted file mode 100644 index 88d01a22..00000000 --- a/docs/modules/chat/examples/vector_db_qa_with_sources.ipynb +++ /dev/null @@ -1,206 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "efc5be67", - "metadata": {}, - "source": [ - "# Retrieval Question Answering with Sources\n", - "\n", - "This notebook goes over how to do question-answering with sources with a chat model over a vector database. It does this by using the `RetrievalQAWithSourcesChain`, which does the lookup of the documents from a vector database. \n", - "\n", - "This notebook is very similar to the example of using an LLM in the RetrievalQAWithSources. The only differences here are (1) using a ChatModel, and (2) passing in a ChatPromptTemplate (optimized for chat models)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "1c613960", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.embeddings.openai import OpenAIEmbeddings\n", - "from langchain.embeddings.cohere import CohereEmbeddings\n", - "from langchain.text_splitter import CharacterTextSplitter\n", - "from langchain.vectorstores.elastic_vector_search import ElasticVectorSearch\n", - "from langchain.vectorstores import Chroma" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "17d1306e", - "metadata": {}, - "outputs": [], - "source": [ - "with open('../../state_of_the_union.txt') as f:\n", - " state_of_the_union = f.read()\n", - "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", - "texts = text_splitter.split_text(state_of_the_union)\n", - "\n", - "embeddings = OpenAIEmbeddings()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0e745d99", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running Chroma using direct local API.\n", - "Using DuckDB in-memory for database. Data will be transient.\n", - "Running Chroma using direct local API.\n", - "Using DuckDB in-memory for database. Data will be transient.\n" - ] - } - ], - "source": [ - "docsearch = Chroma.from_texts(texts, embeddings, metadatas=[{\"source\": f\"{i}-pl\"} for i in range(len(texts))])" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "8aa571ae", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chains import RetrievalQAWithSourcesChain" - ] - }, - { - "cell_type": "markdown", - "id": "1f73b14a", - "metadata": {}, - "source": [ - "We can now set up the chat model and chat model specific prompt" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "9643c775", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.prompts.chat import (\n", - " ChatPromptTemplate,\n", - " SystemMessagePromptTemplate,\n", - " AIMessagePromptTemplate,\n", - " HumanMessagePromptTemplate,\n", - ")\n", - "from langchain.schema import (\n", - " AIMessage,\n", - " HumanMessage,\n", - " SystemMessage\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ed00e906", - "metadata": {}, - "outputs": [], - "source": [ - "system_template=\"\"\"Use the following pieces of context to answer the users question. \n", - "If you don't know the answer, just say that you don't know, don't try to make up an answer.\n", - "ALWAYS return a \"SOURCES\" part in your answer.\n", - "The \"SOURCES\" part should be a reference to the source of the document from which you got your answer.\n", - "\n", - "Example of your response should be:\n", - "\n", - "```\n", - "The answer is foo\n", - "SOURCES: xyz\n", - "```\n", - "\n", - "Begin!\n", - "----------------\n", - "{summaries}\"\"\"\n", - "messages = [\n", - " SystemMessagePromptTemplate.from_template(system_template),\n", - " HumanMessagePromptTemplate.from_template(\"{question}\")\n", - "]\n", - "prompt = ChatPromptTemplate.from_messages(messages)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "aa859d4c", - "metadata": {}, - "outputs": [], - "source": [ - "chain_type_kwargs = {\"prompt\": prompt}\n", - "chain = RetrievalQAWithSourcesChain.from_chain_type(\n", - " ChatOpenAI(temperature=0), \n", - " chain_type=\"stuff\", \n", - " retriever=docsearch.as_retriever(),\n", - " chain_type_kwargs=chain_type_kwargs\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "8ba36fa7", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'answer': 'The President honored Justice Stephen Breyer, an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court, for his dedicated service to the country. \\n',\n", - " 'sources': '31-pl'}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "chain({\"question\": \"What did the president say about Justice Breyer\"}, return_only_outputs=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8308fbf7", - "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" - }, - "vscode": { - "interpreter": { - "hash": "b1677b440931f40d89ef8be7bf03acb108ce003de0ac9b18e8d43753ea2e7103" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/modules/chat/key_concepts.md b/docs/modules/chat/key_concepts.md deleted file mode 100644 index 2f9110d4..00000000 --- a/docs/modules/chat/key_concepts.md +++ /dev/null @@ -1,29 +0,0 @@ -# Key Concepts - -## ChatMessage -A chat message is what we refer to as the modular unit of information. -At the moment, this consists of "content", which refers to the content of the chat message. -At the moment, most chat models are trained to predict sequences of Human <> AI messages. -This is because so far the primary interaction mode has been between a human user and a singular AI system. - -At the moment, there are four different classes of Chat Messages - -### HumanMessage -A HumanMessage is a ChatMessage that is sent as if from a Human's point of view. - -### AIMessage -An AIMessage is a ChatMessage that is sent from the point of view of the AI system to which the Human is corresponding. - -### SystemMessage -A SystemMessage is still a bit ambiguous, and so far seems to be a concept unique to OpenAI - -### ChatMessage -A chat message is a generic chat message, with not only a "content" field but also a "role" field. -With this field, arbitrary roles may be assigned to a message. - -## ChatGeneration -The output of a single prediction of a chat message. -Currently this is just a chat message itself (eg content and a role) - -## Chat Model -A model which takes in a list of chat messages, and predicts a chat message in response. \ No newline at end of file diff --git a/docs/modules/document_loaders/how_to_guides.rst b/docs/modules/document_loaders/how_to_guides.rst deleted file mode 100644 index e4270c61..00000000 --- a/docs/modules/document_loaders/how_to_guides.rst +++ /dev/null @@ -1,87 +0,0 @@ -How To Guides -==================================== - -There are a lot of different document loaders that LangChain supports. Below are how-to guides for working with them - -`File Loader <./examples/unstructured_file.html>`_: A walkthrough of how to use Unstructured to load files of arbitrary types (pdfs, txt, html, etc). - -`Directory Loader <./examples/directory_loader.html>`_: A walkthrough of how to use Unstructured load files from a given directory. - -`Notion <./examples/notion.html>`_: A walkthrough of how to load data for an arbitrary Notion DB. - -`ReadTheDocs <./examples/readthedocs_documentation.html>`_: A walkthrough of how to load data for documentation generated by ReadTheDocs. - -`HTML <./examples/html.html>`_: A walkthrough of how to load data from an html file. - -`PDF <./examples/pdf.html>`_: A walkthrough of how to load data from a PDF file. - -`PowerPoint <./examples/powerpoint.html>`_: A walkthrough of how to load data from a powerpoint file. - -`Email <./examples/email.html>`_: A walkthrough of how to load data from an email (`.eml`) file. - -`GoogleDrive <./examples/googledrive.html>`_: A walkthrough of how to load data from Google drive. - -`Obsidian <./examples/obsidian.html>`_: A walkthrough of how to load data from an Obsidian file dump. - -`Roam <./examples/roam.html>`_: A walkthrough of how to load data from a Roam file export. - -`EverNote <./examples/evernote.html>`_: A walkthrough of how to load data from a EverNote (`.enex`) file. - -`YouTube <./examples/youtube.html>`_: A walkthrough of how to load the transcript from a YouTube video. - -`Hacker News <./examples/hn.html>`_: A walkthrough of how to load a Hacker News page. - -`GitBook <./examples/gitbook.html>`_: A walkthrough of how to load a GitBook page. - -`s3 File <./examples/s3_file.html>`_: A walkthrough of how to load a file from s3. - -`s3 Directory <./examples/s3_directory.html>`_: A walkthrough of how to load all files in a directory from s3. - -`GCS File <./examples/gcs_file.html>`_: A walkthrough of how to load a file from Google Cloud Storage (GCS). - -`GCS Directory <./examples/gcs_directory.html>`_: A walkthrough of how to load all files in a directory from Google Cloud Storage (GCS). - -`Web Base <./examples/web_base.html>`_: A walkthrough of how to load all text data from webpages. - -`IMSDb <./examples/imsdb.html>`_: A walkthrough of how to load all text data from IMSDb webpage. - -`AZLyrics <./examples/azlyrics.html>`_: A walkthrough of how to load all text data from AZLyrics webpage. - -`College Confidential <./examples/college_confidential.html>`_: A walkthrough of how to load all text data from College Confidential webpage. - -`Gutenberg <./examples/gutenberg.html>`_: A walkthrough of how to load data from a Gutenberg ebook text. - -`Airbyte Json <./examples/airbyte_json.html>`_: A walkthrough of how to load data from a local Airbyte JSON file. - -`CoNLL-U <./examples/CoNLL-U.html>`_: A walkthrough of how to load data from a ConLL-U file. - -`iFixit <./examples/ifixit.html>`_: A walkthrough of how to search and load data like guides, technical Q&A's, and device wikis from iFixit.com - -`Notebook <./examples/notebook.html>`_: A walkthrough of how to load data from .ipynb notebook. - -`Copypaste <./examples/copypaste.html>`_: A walkthrough of how to load a document object from something you just want to copy and paste. - -`CSV <./examples/csv.html>`_: A walkthrough of how to load data from a .csv file. - -`Facebook Chat <./examples/facebook_chat.html>`_: A walkthrough of how to load data from a Facebook Chat json file. - -`Image <./examples/image.html>`_: A walkthrough of how to load images such as JPGs PNGs into a document format that can be used downstream. - -`Markdown <./examples/markdown.html>`_: A walkthrough of how to load data from a markdown file. - -`SRT <./examples/srt.html>`_: A walkthrough of how to load data from a subtitle (`.srt`) file. - -`Telegram <./examples/telegram.html>`_: A walkthrough of how to load data from a Telegram Chat json file. - -`URL <./examples/url.html>`_: A walkthrough of how to load HTML documents from a list of URLs into a document format that we can use downstream. - -`Word Document <./examples/word_document.html>`_: A walkthrough of how to load data from Microsoft Word files. - -`Blackboard <./examples/blackboard.html>`_: A walkthrough of how to load data from a Blackboard course. - -.. toctree:: - :maxdepth: 1 - :glob: - :hidden: - - examples/* diff --git a/docs/modules/document_loaders/key_concepts.md b/docs/modules/document_loaders/key_concepts.md deleted file mode 100644 index 82a2ebae..00000000 --- a/docs/modules/document_loaders/key_concepts.md +++ /dev/null @@ -1,12 +0,0 @@ -# Key Concepts - -## Document -This class is a container for document information. This contains two parts: -- `page_content`: The content of the actual page itself. -- `metadata`: The metadata associated with the document. This can be things like the file path, the url, etc. - -## Loader -This base class is a way to load documents. It exposes a `load` method that returns `Document` objects. - -## [Unstructured](https://github.com/Unstructured-IO/unstructured) -Unstructured is a python package specifically focused on transformations from raw documents to text. diff --git a/docs/modules/indexes.rst b/docs/modules/indexes.rst index 5d58558a..273189c7 100644 --- a/docs/modules/indexes.rst +++ b/docs/modules/indexes.rst @@ -1,6 +1,10 @@ Indexes ========================== +.. note:: + `Conceptual Guide `_ + + Indexes refer to ways to structure documents so that LLMs can best interact with them. This module contains utility functions for working with documents, different types of indexes, and then examples for using those indexes in chains. @@ -14,20 +18,42 @@ For interacting with structured data (SQL tables, etc) or APIs, please see the c The primary index and retrieval types supported by LangChain are currently centered around vector databases, and therefore a lot of the functionality we dive deep on those topics. -The following sections of documentation are provided: +For an overview of everything related to this, please see the below notebook for getting started: + +.. toctree:: + :maxdepth: 1 + + ./indexes/getting_started.ipynb + +We then provide a deep dive on the four main components. + +**Document Loaders** -- `Getting Started <./indexes/getting_started.html>`_: An overview of the base "Retriever" interface, and then all the functionality LangChain provides for working with indexes. +How to load documents from a variety of sources. -- `Key Concepts <./indexes/key_concepts.html>`_: A conceptual guide going over the various concepts related to indexes and the tools needed to create them. +**Text Splitters** -- `How-To Guides <./indexes/how_to_guides.html>`_: A collection of how-to guides. These highlight how to use all the relevant tools, the different types of vector databases, different types of retrievers, and how to use retrievers and indexes in chains. +An overview of the abstractions and implementions around splitting text. + + +**VectorStores** + +An overview of VectorStores and the many integrations LangChain provides. + + +**Retrievers** + +An overview of Retrievers and the implementations LangChain provides. + +Go Deeper +--------- .. toctree:: :maxdepth: 1 - :name: LLMs - :hidden: - ./indexes/getting_started.ipynb - ./indexes/key_concepts.md - ./indexes/how_to_guides.rst + ./indexes/document_loaders.rst + ./indexes/text_splitters.rst + ./indexes/vectorstores.rst + ./indexes/retrievers.rst + diff --git a/docs/modules/indexes/combine_docs.md b/docs/modules/indexes/combine_docs.md deleted file mode 100644 index bcd61a9e..00000000 --- a/docs/modules/indexes/combine_docs.md +++ /dev/null @@ -1,51 +0,0 @@ -# CombineDocuments Chains -CombineDocuments chains are useful for when you need to run a language over multiple documents. -Common use cases for this include question answering, question answering with sources, summarization, and more. -For more information on specific use cases as well as different methods for **fetching** these documents, please see -[this overview](/use_cases/combine_docs.md). - -This documentation now picks up from after you've fetched your documents - now what? -How do you pass them to the language model in a format it can understand? -There are a few different methods, or chains, for doing so. LangChain supports four of the more common ones - and -we are actively looking to include more, so if you have any ideas please reach out! Note that there is not -one best method - the decision of which one to use is often very context specific. In order from simplest to -most complex: - -## Stuffing -Stuffing is the simplest method, whereby you simply stuff all the related data into the prompt as context -to pass to the language model. This is implemented in LangChain as the `StuffDocumentsChain`. - -**Pros:** Only makes a single call to the LLM. When generating text, the LLM has access to all the data at once. - -**Cons:** Most LLMs have a context length, and for large documents (or many documents) this will not work as it will result in a prompt larger than the context length. - -The main downside of this method is that it only works on smaller pieces of data. Once you are working -with many pieces of data, this approach is no longer feasible. The next two approaches are designed to help deal with that. - -## Map Reduce -This method involves running an initial prompt on each chunk of data (for summarization tasks, this -could be a summary of that chunk; for question-answering tasks, it could be an answer based solely on that chunk). -Then a different prompt is run to combine all the initial outputs. This is implemented in the LangChain as the `MapReduceDocumentsChain`. - -**Pros:** Can scale to larger documents (and more documents) than `StuffDocumentsChain`. The calls to the LLM on individual documents are independent and can therefore be parallelized. - -**Cons:** Requires many more calls to the LLM than `StuffDocumentsChain`. Loses some information during the final combined call. - -## Refine -This method involves running an initial prompt on the first chunk of data, generating some output. -For the remaining documents, that output is passed in, along with the next document, -asking the LLM to refine the output based on the new document. - -**Pros:** Can pull in more relevant context, and may be less lossy than `MapReduceDocumentsChain`. - -**Cons:** Requires many more calls to the LLM than `StuffDocumentsChain`. The calls are also NOT independent, meaning they cannot be paralleled like `MapReduceDocumentsChain`. There is also some potential dependencies on the ordering of the documents. - - -## Map-Rerank -This method involves running an initial prompt on each chunk of data, that not only tries to complete a -task but also gives a score for how certain it is in its answer. The responses are then -ranked according to this score, and the highest score is returned. - -**Pros:** Similar pros as `MapReduceDocumentsChain`. Requires fewer calls, compared to `MapReduceDocumentsChain`. - -**Cons:** Cannot combine information between documents. This means it is most useful when you expect there to be a single simple answer in a single document. diff --git a/docs/modules/document_loaders.rst b/docs/modules/indexes/document_loaders.rst similarity index 60% rename from docs/modules/document_loaders.rst rename to docs/modules/indexes/document_loaders.rst index a393563a..45307041 100644 --- a/docs/modules/document_loaders.rst +++ b/docs/modules/indexes/document_loaders.rst @@ -1,6 +1,10 @@ Document Loaders ========================== +.. note:: + `Conceptual Guide `_ + + Combining language models with your own text data is a powerful way to differentiate them. The first step in doing this is to load the data into "documents" - a fancy way of say some pieces of text. This module is aimed at making this easy. @@ -10,20 +14,11 @@ This package is a great way to transform all types of files - text, powerpoint, For detailed instructions on how to get set up with Unstructured, see installation guidelines `here `_. -The following sections of documentation are provided: - -- `Key Concepts <./document_loaders/key_concepts.html>`_: A conceptual guide going over the various concepts related to loading documents. - -- `How-To Guides <./document_loaders/how_to_guides.html>`_: A collection of how-to guides. These highlight different types of loaders. - - +The following document loaders are provided: .. toctree:: :maxdepth: 1 - :caption: Document Loaders - :name: Document Loaders - :hidden: + :glob: - ./document_loaders/key_concepts.md - ./document_loaders/how_to_guides.rst \ No newline at end of file + ./document_loaders/examples/* \ No newline at end of file diff --git a/docs/modules/document_loaders/examples/CoNLL-U.ipynb b/docs/modules/indexes/document_loaders/examples/CoNLL-U.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/CoNLL-U.ipynb rename to docs/modules/indexes/document_loaders/examples/CoNLL-U.ipynb diff --git a/docs/modules/document_loaders/examples/airbyte_json.ipynb b/docs/modules/indexes/document_loaders/examples/airbyte_json.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/airbyte_json.ipynb rename to docs/modules/indexes/document_loaders/examples/airbyte_json.ipynb diff --git a/docs/modules/document_loaders/examples/azlyrics.ipynb b/docs/modules/indexes/document_loaders/examples/azlyrics.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/azlyrics.ipynb rename to docs/modules/indexes/document_loaders/examples/azlyrics.ipynb diff --git a/docs/modules/document_loaders/examples/blackboard.ipynb b/docs/modules/indexes/document_loaders/examples/blackboard.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/blackboard.ipynb rename to docs/modules/indexes/document_loaders/examples/blackboard.ipynb diff --git a/docs/modules/document_loaders/examples/college_confidential.ipynb b/docs/modules/indexes/document_loaders/examples/college_confidential.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/college_confidential.ipynb rename to docs/modules/indexes/document_loaders/examples/college_confidential.ipynb diff --git a/docs/modules/document_loaders/examples/copypaste.ipynb b/docs/modules/indexes/document_loaders/examples/copypaste.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/copypaste.ipynb rename to docs/modules/indexes/document_loaders/examples/copypaste.ipynb diff --git a/docs/modules/document_loaders/examples/csv.ipynb b/docs/modules/indexes/document_loaders/examples/csv.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/csv.ipynb rename to docs/modules/indexes/document_loaders/examples/csv.ipynb diff --git a/docs/modules/document_loaders/examples/directory_loader.ipynb b/docs/modules/indexes/document_loaders/examples/directory_loader.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/directory_loader.ipynb rename to docs/modules/indexes/document_loaders/examples/directory_loader.ipynb diff --git a/docs/modules/document_loaders/examples/email.ipynb b/docs/modules/indexes/document_loaders/examples/email.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/email.ipynb rename to docs/modules/indexes/document_loaders/examples/email.ipynb diff --git a/docs/modules/document_loaders/examples/evernote.ipynb b/docs/modules/indexes/document_loaders/examples/evernote.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/evernote.ipynb rename to docs/modules/indexes/document_loaders/examples/evernote.ipynb diff --git a/docs/modules/document_loaders/examples/example_data/conllu.conllu b/docs/modules/indexes/document_loaders/examples/example_data/conllu.conllu similarity index 100% rename from docs/modules/document_loaders/examples/example_data/conllu.conllu rename to docs/modules/indexes/document_loaders/examples/example_data/conllu.conllu diff --git a/docs/modules/document_loaders/examples/example_data/facebook_chat.json b/docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json similarity index 100% rename from docs/modules/document_loaders/examples/example_data/facebook_chat.json rename to docs/modules/indexes/document_loaders/examples/example_data/facebook_chat.json diff --git a/docs/modules/document_loaders/examples/example_data/fake-content.html b/docs/modules/indexes/document_loaders/examples/example_data/fake-content.html similarity index 100% rename from docs/modules/document_loaders/examples/example_data/fake-content.html rename to docs/modules/indexes/document_loaders/examples/example_data/fake-content.html diff --git a/docs/modules/document_loaders/examples/example_data/fake-email.eml b/docs/modules/indexes/document_loaders/examples/example_data/fake-email.eml similarity index 100% rename from docs/modules/document_loaders/examples/example_data/fake-email.eml rename to docs/modules/indexes/document_loaders/examples/example_data/fake-email.eml diff --git a/docs/modules/document_loaders/examples/example_data/fake-power-point.pptx b/docs/modules/indexes/document_loaders/examples/example_data/fake-power-point.pptx similarity index 100% rename from docs/modules/document_loaders/examples/example_data/fake-power-point.pptx rename to docs/modules/indexes/document_loaders/examples/example_data/fake-power-point.pptx diff --git a/docs/modules/document_loaders/examples/example_data/fake.docx b/docs/modules/indexes/document_loaders/examples/example_data/fake.docx similarity index 100% rename from docs/modules/document_loaders/examples/example_data/fake.docx rename to docs/modules/indexes/document_loaders/examples/example_data/fake.docx diff --git a/docs/modules/document_loaders/examples/example_data/layout-parser-paper.pdf b/docs/modules/indexes/document_loaders/examples/example_data/layout-parser-paper.pdf similarity index 100% rename from docs/modules/document_loaders/examples/example_data/layout-parser-paper.pdf rename to docs/modules/indexes/document_loaders/examples/example_data/layout-parser-paper.pdf diff --git a/docs/modules/document_loaders/examples/example_data/mlb_teams_2012.csv b/docs/modules/indexes/document_loaders/examples/example_data/mlb_teams_2012.csv similarity index 100% rename from docs/modules/document_loaders/examples/example_data/mlb_teams_2012.csv rename to docs/modules/indexes/document_loaders/examples/example_data/mlb_teams_2012.csv diff --git a/docs/modules/document_loaders/examples/example_data/notebook.ipynb b/docs/modules/indexes/document_loaders/examples/example_data/notebook.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/example_data/notebook.ipynb rename to docs/modules/indexes/document_loaders/examples/example_data/notebook.ipynb diff --git a/docs/modules/document_loaders/examples/example_data/telegram.json b/docs/modules/indexes/document_loaders/examples/example_data/telegram.json similarity index 100% rename from docs/modules/document_loaders/examples/example_data/telegram.json rename to docs/modules/indexes/document_loaders/examples/example_data/telegram.json diff --git a/docs/modules/document_loaders/examples/example_data/testing.enex b/docs/modules/indexes/document_loaders/examples/example_data/testing.enex similarity index 100% rename from docs/modules/document_loaders/examples/example_data/testing.enex rename to docs/modules/indexes/document_loaders/examples/example_data/testing.enex diff --git a/docs/modules/document_loaders/examples/facebook_chat.ipynb b/docs/modules/indexes/document_loaders/examples/facebook_chat.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/facebook_chat.ipynb rename to docs/modules/indexes/document_loaders/examples/facebook_chat.ipynb diff --git a/docs/modules/document_loaders/examples/figma.ipynb b/docs/modules/indexes/document_loaders/examples/figma.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/figma.ipynb rename to docs/modules/indexes/document_loaders/examples/figma.ipynb diff --git a/docs/modules/document_loaders/examples/gcs_directory.ipynb b/docs/modules/indexes/document_loaders/examples/gcs_directory.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/gcs_directory.ipynb rename to docs/modules/indexes/document_loaders/examples/gcs_directory.ipynb diff --git a/docs/modules/document_loaders/examples/gcs_file.ipynb b/docs/modules/indexes/document_loaders/examples/gcs_file.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/gcs_file.ipynb rename to docs/modules/indexes/document_loaders/examples/gcs_file.ipynb diff --git a/docs/modules/document_loaders/examples/gitbook.ipynb b/docs/modules/indexes/document_loaders/examples/gitbook.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/gitbook.ipynb rename to docs/modules/indexes/document_loaders/examples/gitbook.ipynb diff --git a/docs/modules/document_loaders/examples/googledrive.ipynb b/docs/modules/indexes/document_loaders/examples/googledrive.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/googledrive.ipynb rename to docs/modules/indexes/document_loaders/examples/googledrive.ipynb diff --git a/docs/modules/document_loaders/examples/gutenberg.ipynb b/docs/modules/indexes/document_loaders/examples/gutenberg.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/gutenberg.ipynb rename to docs/modules/indexes/document_loaders/examples/gutenberg.ipynb diff --git a/docs/modules/document_loaders/examples/hn.ipynb b/docs/modules/indexes/document_loaders/examples/hn.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/hn.ipynb rename to docs/modules/indexes/document_loaders/examples/hn.ipynb diff --git a/docs/modules/document_loaders/examples/html.ipynb b/docs/modules/indexes/document_loaders/examples/html.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/html.ipynb rename to docs/modules/indexes/document_loaders/examples/html.ipynb diff --git a/docs/modules/document_loaders/examples/ifixit.ipynb b/docs/modules/indexes/document_loaders/examples/ifixit.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/ifixit.ipynb rename to docs/modules/indexes/document_loaders/examples/ifixit.ipynb diff --git a/docs/modules/document_loaders/examples/image.ipynb b/docs/modules/indexes/document_loaders/examples/image.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/image.ipynb rename to docs/modules/indexes/document_loaders/examples/image.ipynb diff --git a/docs/modules/document_loaders/examples/imsdb.ipynb b/docs/modules/indexes/document_loaders/examples/imsdb.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/imsdb.ipynb rename to docs/modules/indexes/document_loaders/examples/imsdb.ipynb diff --git a/docs/modules/document_loaders/examples/markdown.ipynb b/docs/modules/indexes/document_loaders/examples/markdown.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/markdown.ipynb rename to docs/modules/indexes/document_loaders/examples/markdown.ipynb diff --git a/docs/modules/document_loaders/examples/notebook.ipynb b/docs/modules/indexes/document_loaders/examples/notebook.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/notebook.ipynb rename to docs/modules/indexes/document_loaders/examples/notebook.ipynb diff --git a/docs/modules/document_loaders/examples/notion.ipynb b/docs/modules/indexes/document_loaders/examples/notion.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/notion.ipynb rename to docs/modules/indexes/document_loaders/examples/notion.ipynb diff --git a/docs/modules/document_loaders/examples/obsidian.ipynb b/docs/modules/indexes/document_loaders/examples/obsidian.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/obsidian.ipynb rename to docs/modules/indexes/document_loaders/examples/obsidian.ipynb diff --git a/docs/modules/document_loaders/examples/pdf.ipynb b/docs/modules/indexes/document_loaders/examples/pdf.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/pdf.ipynb rename to docs/modules/indexes/document_loaders/examples/pdf.ipynb diff --git a/docs/modules/document_loaders/examples/powerpoint.ipynb b/docs/modules/indexes/document_loaders/examples/powerpoint.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/powerpoint.ipynb rename to docs/modules/indexes/document_loaders/examples/powerpoint.ipynb diff --git a/docs/modules/document_loaders/examples/readthedocs_documentation.ipynb b/docs/modules/indexes/document_loaders/examples/readthedocs_documentation.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/readthedocs_documentation.ipynb rename to docs/modules/indexes/document_loaders/examples/readthedocs_documentation.ipynb diff --git a/docs/modules/document_loaders/examples/roam.ipynb b/docs/modules/indexes/document_loaders/examples/roam.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/roam.ipynb rename to docs/modules/indexes/document_loaders/examples/roam.ipynb diff --git a/docs/modules/document_loaders/examples/s3_directory.ipynb b/docs/modules/indexes/document_loaders/examples/s3_directory.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/s3_directory.ipynb rename to docs/modules/indexes/document_loaders/examples/s3_directory.ipynb diff --git a/docs/modules/document_loaders/examples/s3_file.ipynb b/docs/modules/indexes/document_loaders/examples/s3_file.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/s3_file.ipynb rename to docs/modules/indexes/document_loaders/examples/s3_file.ipynb diff --git a/docs/modules/document_loaders/examples/srt.ipynb b/docs/modules/indexes/document_loaders/examples/srt.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/srt.ipynb rename to docs/modules/indexes/document_loaders/examples/srt.ipynb diff --git a/docs/modules/document_loaders/examples/telegram.ipynb b/docs/modules/indexes/document_loaders/examples/telegram.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/telegram.ipynb rename to docs/modules/indexes/document_loaders/examples/telegram.ipynb diff --git a/docs/modules/document_loaders/examples/unstructured_file.ipynb b/docs/modules/indexes/document_loaders/examples/unstructured_file.ipynb similarity index 96% rename from docs/modules/document_loaders/examples/unstructured_file.ipynb rename to docs/modules/indexes/document_loaders/examples/unstructured_file.ipynb index 1db5f7ce..fd1da88a 100644 --- a/docs/modules/document_loaders/examples/unstructured_file.ipynb +++ b/docs/modules/indexes/document_loaders/examples/unstructured_file.ipynb @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "id": "79d3e549", "metadata": {}, "outputs": [], @@ -67,7 +67,7 @@ "metadata": {}, "outputs": [], "source": [ - "loader = UnstructuredFileLoader(\"../../state_of_the_union.txt\")" + "loader = UnstructuredFileLoader(\"./example_data/state_of_the_union.txt\")" ] }, { @@ -118,7 +118,7 @@ "metadata": {}, "outputs": [], "source": [ - "loader = UnstructuredFileLoader(\"../../state_of_the_union.txt\", mode=\"elements\")" + "loader = UnstructuredFileLoader(\"./example_data/state_of_the_union.txt\", mode=\"elements\")" ] }, { @@ -243,18 +243,18 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 7, "id": "686e5eb4", "metadata": {}, "outputs": [], "source": [ - "loader = UnstructuredFileLoader(\"../../layout-parser-paper.pdf\", mode=\"elements\")" + "loader = UnstructuredFileLoader(\"./example_data/layout-parser-paper.pdf\", mode=\"elements\")" ] }, { "cell_type": "code", - "execution_count": 1, - "id": "f8348ca0", + "execution_count": null, + "id": "c90f0e94", "metadata": {}, "outputs": [], "source": [ @@ -311,7 +311,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/document_loaders/examples/url.ipynb b/docs/modules/indexes/document_loaders/examples/url.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/url.ipynb rename to docs/modules/indexes/document_loaders/examples/url.ipynb diff --git a/docs/modules/document_loaders/examples/web_base.ipynb b/docs/modules/indexes/document_loaders/examples/web_base.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/web_base.ipynb rename to docs/modules/indexes/document_loaders/examples/web_base.ipynb diff --git a/docs/modules/document_loaders/examples/word_document.ipynb b/docs/modules/indexes/document_loaders/examples/word_document.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/word_document.ipynb rename to docs/modules/indexes/document_loaders/examples/word_document.ipynb diff --git a/docs/modules/document_loaders/examples/youtube.ipynb b/docs/modules/indexes/document_loaders/examples/youtube.ipynb similarity index 100% rename from docs/modules/document_loaders/examples/youtube.ipynb rename to docs/modules/indexes/document_loaders/examples/youtube.ipynb diff --git a/docs/modules/indexes/examples/embeddings.ipynb b/docs/modules/indexes/examples/embeddings.ipynb deleted file mode 100644 index 0ceb437c..00000000 --- a/docs/modules/indexes/examples/embeddings.ipynb +++ /dev/null @@ -1,778 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "249b4058", - "metadata": {}, - "source": [ - "# Embeddings\n", - "\n", - "This notebook goes over how to use the Embedding class in LangChain.\n", - "\n", - "The Embedding class is a class designed for interfacing with embeddings. There are lots of Embedding providers (OpenAI, Cohere, Hugging Face, etc) - this class is designed to provide a standard interface for all of them.\n", - "\n", - "Embeddings create a vector representation of a piece of text. This is useful because it means we can think about text in the vector space, and do things like semantic search where we look for pieces of text that are most similar in the vector space.\n", - "\n", - "The base Embedding class in LangChain exposes two methods: `embed_documents` and `embed_query`. The largest difference is that these two methods have different interfaces: one works over multiple documents, while the other works over a single document. Besides this, another reason for having these as two separate methods is that some embedding providers have different embedding methods for documents (to be searched over) vs queries (the search query itself)." - ] - }, - { - "cell_type": "markdown", - "id": "278b6c63", - "metadata": {}, - "source": [ - "## OpenAI\n", - "\n", - "Let's load the OpenAI Embedding class." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "0be1af71", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.embeddings import OpenAIEmbeddings" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "2c66e5da", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = OpenAIEmbeddings()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "01370375", - "metadata": {}, - "outputs": [], - "source": [ - "text = \"This is a test document.\"" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "bfb6142c", - "metadata": {}, - "outputs": [], - "source": [ - "query_result = embeddings.embed_query(text)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "0356c3b7", - "metadata": {}, - "outputs": [], - "source": [ - "doc_result = embeddings.embed_documents([text])" - ] - }, - { - "cell_type": "markdown", - "id": "bb61bbeb", - "metadata": {}, - "source": [ - "Let's load the OpenAI Embedding class with first generation models (e.g. text-search-ada-doc-001/text-search-ada-query-001). Note: These are not recommended models - see [here](https://platform.openai.com/docs/guides/embeddings/what-are-embeddings)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c0b072cc", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.embeddings.openai import OpenAIEmbeddings" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a56b70f5", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = OpenAIEmbeddings(model_name=\"ada\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "14aefb64", - "metadata": {}, - "outputs": [], - "source": [ - "text = \"This is a test document.\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3c39ed33", - "metadata": {}, - "outputs": [], - "source": [ - "query_result = embeddings.embed_query(text)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3221db6", - "metadata": {}, - "outputs": [], - "source": [ - "doc_result = embeddings.embed_documents([text])" - ] - }, - { - "cell_type": "markdown", - "id": "c3852491", - "metadata": {}, - "source": [ - "## AzureOpenAI\n", - "\n", - "Let's load the OpenAI Embedding class with environment variables set to indicate to use Azure endpoints." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1b40f827", - "metadata": {}, - "outputs": [], - "source": [ - "# set the environment variables needed for openai package to know to reach out to azure\n", - "import os\n", - "\n", - "os.environ[\"OPENAI_API_TYPE\"] = \"azure\"\n", - "os.environ[\"OPENAI_API_BASE\"] = \"https://'],\n", - "# ssh_creds={'ssh_user': '...', 'ssh_private_key':''},\n", - "# name='my-cluster')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1230f7df", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = SelfHostedHuggingFaceEmbeddings(hardware=gpu)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "2684e928", - "metadata": {}, - "outputs": [], - "source": [ - "text = \"This is a test document.\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1dc5e606", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "query_result = embeddings.embed_query(text)" - ] - }, - { - "cell_type": "markdown", - "id": "cef9cc54", - "metadata": {}, - "source": [ - "And similarly for SelfHostedHuggingFaceInstructEmbeddings:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "81a17ca3", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = SelfHostedHuggingFaceInstructEmbeddings(hardware=gpu)" - ] - }, - { - "cell_type": "markdown", - "id": "5a33d1c8", - "metadata": {}, - "source": [ - "Now let's load an embedding model with a custom load function:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "c4af5679", - "metadata": {}, - "outputs": [], - "source": [ - "def get_pipeline():\n", - " from transformers import (\n", - " AutoModelForCausalLM,\n", - " AutoTokenizer,\n", - " pipeline,\n", - " ) # Must be inside the function in notebooks\n", - "\n", - " model_id = \"facebook/bart-base\"\n", - " tokenizer = AutoTokenizer.from_pretrained(model_id)\n", - " model = AutoModelForCausalLM.from_pretrained(model_id)\n", - " return pipeline(\"feature-extraction\", model=model, tokenizer=tokenizer)\n", - "\n", - "\n", - "def inference_fn(pipeline, prompt):\n", - " # Return last hidden state of the model\n", - " if isinstance(prompt, list):\n", - " return [emb[0][-1] for emb in pipeline(prompt)]\n", - " return pipeline(prompt)[0][-1]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8654334b", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = SelfHostedEmbeddings(\n", - " model_load_fn=get_pipeline,\n", - " hardware=gpu,\n", - " model_reqs=[\"./\", \"torch\", \"transformers\"],\n", - " inference_fn=inference_fn,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fc1bfd0f", - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "query_result = embeddings.embed_query(text)" - ] - }, - { - "cell_type": "markdown", - "id": "f9c02c78", - "metadata": {}, - "source": [ - "## Fake Embeddings\n", - "\n", - "LangChain also provides a fake embedding class. You can use this to test your pipelines." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "2ffc2e4b", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.embeddings import FakeEmbeddings" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "80777571", - "metadata": {}, - "outputs": [], - "source": [ - "embeddings = FakeEmbeddings(size=1352)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "3ec9d8f0", - "metadata": {}, - "outputs": [], - "source": [ - "query_result = embeddings.embed_query(\"foo\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "3b9ae9e1", - "metadata": {}, - "outputs": [], - "source": [ - "doc_results = embeddings.embed_documents([\"foo\"])" - ] - }, - { - "cell_type": "markdown", - "id": "1f83f273", - "metadata": {}, - "source": [ - "## SageMaker Endpoint Embeddings\n", - "\n", - "Let's load the SageMaker Endpoints Embeddings class. The class can be used if you host, e.g. your own Hugging Face model on SageMaker.\n", - "\n", - "For instrucstions on how to do this, please see [here](https://www.philschmid.de/custom-inference-huggingface-sagemaker)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "88d366bd", - "metadata": {}, - "outputs": [], - "source": [ - "!pip3 install langchain boto3" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "1e9b926a", - "metadata": {}, - "outputs": [], - "source": [ - "from typing import Dict\n", - "from langchain.embeddings import SagemakerEndpointEmbeddings\n", - "from langchain.llms.sagemaker_endpoint import ContentHandlerBase\n", - "import json\n", - "\n", - "\n", - "class ContentHandler(ContentHandlerBase):\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({\"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[\"embeddings\"]\n", - "\n", - "content_handler = ContentHandler()\n", - "\n", - "\n", - "embeddings = SagemakerEndpointEmbeddings(\n", - " # endpoint_name=\"endpoint-name\", \n", - " # credentials_profile_name=\"credentials-profile-name\", \n", - " endpoint_name=\"huggingface-pytorch-inference-2023-03-21-16-14-03-834\", \n", - " region_name=\"us-east-1\", \n", - " content_handler=content_handler\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fe9797b8", - "metadata": {}, - "outputs": [], - "source": [ - "query_result = embeddings.embed_query(\"foo\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "76f1b752", - "metadata": {}, - "outputs": [], - "source": [ - "doc_results = embeddings.embed_documents([\"foo\"])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fff99b21", - "metadata": {}, - "outputs": [], - "source": [ - "doc_results" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aaad49f8", - "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" - }, - "vscode": { - "interpreter": { - "hash": "7377c2ccc78bc62c2683122d48c8cd1fb85a53850a1b1fc29736ed39852c9885" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/modules/indexes/examples/textsplitter.ipynb b/docs/modules/indexes/examples/textsplitter.ipynb deleted file mode 100644 index 2d7bcf99..00000000 --- a/docs/modules/indexes/examples/textsplitter.ipynb +++ /dev/null @@ -1,826 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "b118c9dc", - "metadata": {}, - "source": [ - "# Text Splitter\n", - "\n", - "When you want to deal with long pieces of text, it is necessary to split up that text into chunks.\n", - "As simple as this sounds, there is a lot of potential complexity here. Ideally, you want to keep the semantically related pieces of text together. What \"semantically related\" means could depend on the type of text.\n", - "This notebook showcases several ways to do that.\n", - "\n", - "At a high level, text splitters work as following:\n", - "\n", - "1. Split the text up into small, semantically meaningful chunks (often sentences).\n", - "2. Start combining these small chunks into a larger chunk until you reach a certain size (as measured by some function).\n", - "3. Once you reach that size, make that chunk its own piece of text and then start creating a new chunk of text with some overlap (to keep context between chunks).\n", - "\n", - "That means there two different axes along which you can customize your text splitter:\n", - "\n", - "1. How the text is split\n", - "2. How the chunk size is measured\n", - "\n", - "For all the examples below, we will highlight both of these attributes" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "e82c4685", - "metadata": {}, - "outputs": [], - "source": [ - "# This is a long document we can split up.\n", - "with open('../../state_of_the_union.txt') as f:\n", - " state_of_the_union = f.read()" - ] - }, - { - "cell_type": "markdown", - "id": "072eee66", - "metadata": {}, - "source": [ - "## Generic Recursive Text Splitting\n", - "This text splitter is the recommended one for generic text. It is parameterized by a list of characters. It tries to split on them in order until the chunks are small enough. The default list is `[\"\\n\\n\", \"\\n\", \" \", \"\"]`. This has the effect of trying to keep all paragraphs (and then sentences, and then words) together as long as possible, as those would generically seem to be the strongest semantically related pieces of text.\n", - "\n", - "\n", - "1. How the text is split: by list of characters\n", - "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "14662639", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.text_splitter import RecursiveCharacterTextSplitter" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "fc6e42c8", - "metadata": {}, - "outputs": [], - "source": [ - "text_splitter = RecursiveCharacterTextSplitter(\n", - " # Set a really small chunk size, just to show.\n", - " chunk_size = 100,\n", - " chunk_overlap = 20,\n", - " length_function = len,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "bd1a0a15", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet.' lookup_str='' metadata={} lookup_index=0\n", - "page_content='and the Cabinet. Justices of the Supreme Court. My fellow Americans.' lookup_str='' metadata={} lookup_index=0\n" - ] - } - ], - "source": [ - "texts = text_splitter.create_documents([state_of_the_union])\n", - "print(texts[0])\n", - "print(texts[1])" - ] - }, - { - "cell_type": "markdown", - "id": "80f6cd99", - "metadata": {}, - "source": [ - "## Markdown Text Splitter\n", - "\n", - "MarkdownTextSplitter splits text along Markdown headings, code blocks, or horizontal rules. It's implemented as a simple subclass of RecursiveCharacterSplitter with Markdown-specific separators. See the source code to see the Markdown syntax expected by default.\n", - "\n", - "1. How the text is split: by list of markdown specific characters\n", - "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "96d64839", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.text_splitter import MarkdownTextSplitter" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "cfb0da17", - "metadata": {}, - "outputs": [], - "source": [ - "markdown_text = \"\"\"\n", - "# 🦜️🔗 LangChain\n", - "\n", - "⚡ Building applications with LLMs through composability ⚡\n", - "\n", - "## Quick Install\n", - "\n", - "```bash\n", - "# Hopefully this code block isn't split\n", - "pip install langchain\n", - "```\n", - "\n", - "As an open source project in a rapidly developing field, we are extremely open to contributions.\n", - "\"\"\"\n", - "markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "d59a4fe8", - "metadata": {}, - "outputs": [], - "source": [ - "docs = markdown_splitter.create_documents([markdown_text])" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "cbb2e100", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[Document(page_content='# 🦜️🔗 LangChain\\n\\n⚡ Building applications with LLMs through composability ⚡', lookup_str='', metadata={}, lookup_index=0),\n", - " Document(page_content=\"Quick Install\\n\\n```bash\\n# Hopefully this code block isn't split\\npip install langchain\", lookup_str='', metadata={}, lookup_index=0),\n", - " Document(page_content='As an open source project in a rapidly developing field, we are extremely open to contributions.', lookup_str='', metadata={}, lookup_index=0)]" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "docs" - ] - }, - { - "cell_type": "markdown", - "id": "3a2f572e", - "metadata": {}, - "source": [ - "## Latex Text Splitter\n", - "\n", - "LatexTextSplitter splits text along Latex headings, headlines, enumerations and more. It's implemented as a simple subclass of RecursiveCharacterSplitter with Latex-specific separators. See the source code to see the Latex syntax expected by default.\n", - "\n", - "1. How the text is split: by list of latex specific tags\n", - "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c2503917", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.text_splitter import LatexTextSplitter" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e46b753b", - "metadata": {}, - "outputs": [], - "source": [ - "latex_text = \"\"\"\n", - "\\documentclass{article}\n", - "\n", - "\\begin{document}\n", - "\n", - "\\maketitle\n", - "\n", - "\\section{Introduction}\n", - "Large language models (LLMs) are a type of machine learning model that can be trained on vast amounts of text data to generate human-like language. In recent years, LLMs have made significant advances in a variety of natural language processing tasks, including language translation, text generation, and sentiment analysis.\n", - "\n", - "\\subsection{History of LLMs}\n", - "The earliest LLMs were developed in the 1980s and 1990s, but they were limited by the amount of data that could be processed and the computational power available at the time. In the past decade, however, advances in hardware and software have made it possible to train LLMs on massive datasets, leading to significant improvements in performance.\n", - "\n", - "\\subsection{Applications of LLMs}\n", - "LLMs have many applications in industry, including chatbots, content creation, and virtual assistants. They can also be used in academia for research in linguistics, psychology, and computational linguistics.\n", - "\n", - "\\end{document}\n", - "\"\"\"\n", - "latex_splitter = LatexTextSplitter(chunk_size=400, chunk_overlap=0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "73b5bd33", - "metadata": {}, - "outputs": [], - "source": [ - "docs = latex_splitter.create_documents([latex_text])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e1c7fbd5", - "metadata": {}, - "outputs": [], - "source": [ - "docs" - ] - }, - { - "cell_type": "markdown", - "id": "c350765d", - "metadata": {}, - "source": [ - "## Python Code Text Splitter\n", - "\n", - "PythonCodeTextSplitter splits text along python class and method definitions. It's implemented as a simple subclass of RecursiveCharacterSplitter with Python-specific separators. See the source code to see the Python syntax expected by default.\n", - "\n", - "1. How the text is split: by list of python specific characters\n", - "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "1703463f", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.text_splitter import PythonCodeTextSplitter" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "f17a1854", - "metadata": {}, - "outputs": [], - "source": [ - "python_text = \"\"\"\n", - "class Foo:\n", - "\n", - " def bar():\n", - " \n", - " \n", - "def foo():\n", - "\n", - "def testing_func():\n", - "\n", - "def bar():\n", - "\"\"\"\n", - "python_splitter = PythonCodeTextSplitter(chunk_size=30, chunk_overlap=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "6cdc55f3", - "metadata": {}, - "outputs": [], - "source": [ - "docs = python_splitter.create_documents([python_text])" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "8cc33770", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[Document(page_content='Foo:\\n\\n def bar():', lookup_str='', metadata={}, lookup_index=0),\n", - " Document(page_content='foo():\\n\\ndef testing_func():', lookup_str='', metadata={}, lookup_index=0),\n", - " Document(page_content='bar():', lookup_str='', metadata={}, lookup_index=0)]" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "docs" - ] - }, - { - "cell_type": "markdown", - "id": "5c461b26", - "metadata": {}, - "source": [ - "## Character Text Splitting\n", - "\n", - "This is a more simple method. This splits based on characters (by default \"\\n\\n\") and measure chunk length by number of characters.\n", - "\n", - "1. How the text is split: by single character\n", - "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "79ff6737", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.text_splitter import CharacterTextSplitter\n", - "text_splitter = CharacterTextSplitter( \n", - " separator = \"\\n\\n\",\n", - " chunk_size = 1000,\n", - " chunk_overlap = 200,\n", - " length_function = len,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "38547666", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \\n\\nLast year COVID-19 kept us apart. This year we are finally together again. \\n\\nTonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \\n\\nWith a duty to one another to the American people to the Constitution. \\n\\nAnd with an unwavering resolve that freedom will always triumph over tyranny. \\n\\nSix days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways. But he badly miscalculated. \\n\\nHe thought he could roll into Ukraine and the world would roll over. Instead he met a wall of strength he never imagined. \\n\\nHe met the Ukrainian people. \\n\\nFrom President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.' lookup_str='' metadata={} lookup_index=0\n" - ] - } - ], - "source": [ - "texts = text_splitter.create_documents([state_of_the_union])\n", - "print(texts[0])" - ] - }, - { - "cell_type": "markdown", - "id": "2cede1b1", - "metadata": {}, - "source": [ - "Here's an example of passing metadata along with the documents, notice that it is split along with the documents." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "4a47515a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \\n\\nLast year COVID-19 kept us apart. This year we are finally together again. \\n\\nTonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \\n\\nWith a duty to one another to the American people to the Constitution. \\n\\nAnd with an unwavering resolve that freedom will always triumph over tyranny. \\n\\nSix days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways. But he badly miscalculated. \\n\\nHe thought he could roll into Ukraine and the world would roll over. Instead he met a wall of strength he never imagined. \\n\\nHe met the Ukrainian people. \\n\\nFrom President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.' lookup_str='' metadata={'document': 1} lookup_index=0\n" - ] - } - ], - "source": [ - "metadatas = [{\"document\": 1}, {\"document\": 2}]\n", - "documents = text_splitter.create_documents([state_of_the_union, state_of_the_union], metadatas=metadatas)\n", - "print(documents[0])" - ] - }, - { - "cell_type": "markdown", - "id": "13dc0983", - "metadata": {}, - "source": [ - "## HuggingFace Length Function\n", - "Most LLMs are constrained by the number of tokens that you can pass in, which is not the same as the number of characters. In order to get a more accurate estimate, we can use HuggingFace tokenizers to count the text length.\n", - "\n", - "1. How the text is split: by character passed in\n", - "2. How the chunk size is measured: by Hugging Face tokenizer" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "a8ce51d5", - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "365a203647c94effb38c2058a6c88577", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Downloading (…)olve/main/vocab.json: 0%| | 0.00/1.04M [00:00`_: A walkthrough of how to split large documents up into smaller, more manageable pieces of text. - -`VectorStores <./examples/vectorstores.html>`_: A walkthrough of the vectorstore abstraction that LangChain supports. - -`Embeddings <./examples/embeddings.html>`_: A walkthrough of embedding functionalities, and different types of embeddings, that LangChain supports. - -`HyDE <./examples/hyde.html>`_: How to use Hypothetical Document Embeddings, a novel way of constructing embeddings for document retrieval systems. - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Utils - :name: utils - :hidden: - - examples/* - - -Vectorstores ------------- - - -Vectorstores are one of the most important components of building indexes. -In the below guides, we cover different types of vectorstores and how to use them. - -`Chroma <./vectorstore_examples/chroma.html>`_: A walkthrough of how to use the Chroma vectorstore wrapper. - -`AtlasDB <./vectorstore_examples/atlas.html>`_: A walkthrough of how to use the AtlasDB vectorstore and visualizer wrapper. - -`DeepLake <./vectorstore_examples/deeplake.html>`_: A walkthrough of how to use the Deep Lake, data lake, wrapper. - -`FAISS <./vectorstore_examples/faiss.html>`_: A walkthrough of how to use the FAISS vectorstore wrapper. - -`Elastic Search <./vectorstore_examples/elasticsearch.html>`_: A walkthrough of how to use the ElasticSearch wrapper. - -`Milvus <./vectorstore_examples/milvus.html>`_: A walkthrough of how to use the Milvus vectorstore wrapper. - -`Open Search <./vectorstore_examples/opensearch.html>`_: A walkthrough of how to use the OpenSearch wrapper. - -`Pinecone <./vectorstore_examples/pinecone.html>`_: A walkthrough of how to use the Pinecone vectorstore wrapper. - -`Qdrant <./vectorstore_examples/qdrant.html>`_: A walkthrough of how to use the Qdrant vectorstore wrapper. - -`Weaviate <./vectorstore_examples/weaviate.html>`_: A walkthrough of how to use the Weaviate vectorstore wrapper. - -`PGVector <./vectorstore_examples/pgvector.html>`_: A walkthrough of how to use the PGVector (Postgres Vector DB) vectorstore wrapper. - - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Vectorstores - :name: vectorstores - :hidden: - - vectorstore_examples/* - - -Retrievers ------------- - - -The retriever interface is a generic interface that makes it easy to combine documents with -language models. This interface exposes a `get_relevant_documents` method which takes in a query -(a string) and returns a list of documents. - -`Vectorstore Retriever <./retriever_examples/vectorstore-retriever.html>`_: A walkthrough of how to use a VectorStore as a Retriever. - -`ChatGPT Plugin Retriever <./retriever_examples/chatgpt-plugin-retriever.html>`_: A walkthrough of how to use the ChatGPT Plugin Retriever within the LangChain framework. - - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Retrievers - :name: retrievers - :hidden: - - retriever_examples/* - - -Chains ------- - -The examples here are all end-to-end chains that use indexes or utils covered above. - -`Question Answering <./chain_examples/question_answering.html>`_: A walkthrough of how to use LangChain for question answering over specific documents. - -`Question Answering with Sources <./chain_examples/qa_with_sources.html>`_: A walkthrough of how to use LangChain for question answering (with sources) over specific documents. - -`Summarization <./chain_examples/summarize.html>`_: A walkthrough of how to use LangChain for summarization over specific documents. - -`Vector DB Text Generation <./chain_examples/vector_db_text_generation.html>`_: A walkthrough of how to use LangChain for text generation over a vector database. - -`Vector DB Question Answering <./chain_examples/vector_db_qa.html>`_: A walkthrough of how to use LangChain for question answering over a vector database. - -`Vector DB Question Answering with Sources <./chain_examples/vector_db_qa_with_sources.html>`_: A walkthrough of how to use LangChain for question answering (with sources) over a vector database. - -`Graph Question Answering <./chain_examples/graph_qa.html>`_: A walkthrough of how to use LangChain for question answering (with sources) over a graph database. - -`Chat Vector DB <./chain_examples/chat_vector_db.html>`_: A walkthrough of how to use LangChain as a chatbot over a vector database. - -`Analyze Document <./chain_examples/analyze_document.html>`_: A walkthrough of how to use LangChain to analyze long documents. - - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: With Chains - :name: chains - :hidden: - - ./chain_examples/* diff --git a/docs/modules/indexes/key_concepts.md b/docs/modules/indexes/key_concepts.md deleted file mode 100644 index 8e20ee10..00000000 --- a/docs/modules/indexes/key_concepts.md +++ /dev/null @@ -1,27 +0,0 @@ -# Key Concepts - -## Text Splitter -This class is responsible for splitting long pieces of text into smaller components. -It contains different ways for splitting text (on characters, using Spacy, etc) -as well as different ways for measuring length (token based, character based, etc). - -## Embeddings -These classes are very similar to the LLM classes in that they are wrappers around models, -but rather than return a string they return an embedding (list of floats). These are particularly useful when -implementing semantic search functionality. They expose separate methods for embedding queries versus embedding documents. - -## Vectorstores -These are datastores that store embeddings of documents in vector form. -They expose a method for passing in a string and finding similar documents. - - -## CombineDocuments Chains -These are a subset of chains designed to work with documents. There are two pieces to consider: - -1. The underlying chain method (eg, how the documents are combined) -2. Use cases for these types of chains. - -For the first, please see [this documentation](combine_docs.md) for more detailed information on the types of chains LangChain supports. -For the second, please see the Use Cases section for more information on [question answering](/use_cases/question_answering.md), -[question answering with sources](/use_cases/qa_with_sources.md), and [summarization](/use_cases/summarization.md). - diff --git a/docs/modules/indexes/retrievers.rst b/docs/modules/indexes/retrievers.rst new file mode 100644 index 00000000..ba8fe0db --- /dev/null +++ b/docs/modules/indexes/retrievers.rst @@ -0,0 +1,19 @@ +Retrievers +========================== + +.. note:: + `Conceptual Guide `_ + + +The retriever interface is a generic interface that makes it easy to combine documents with +language models. This interface exposes a `get_relevant_documents` method which takes in a query +(a string) and returns a list of documents. + +Please see below for a list of all the retrievers supported. + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./retrievers/examples/* \ No newline at end of file diff --git a/docs/modules/indexes/retriever_examples/chatgpt-plugin-retriever.ipynb b/docs/modules/indexes/retrievers/examples/chatgpt-plugin-retriever.ipynb similarity index 100% rename from docs/modules/indexes/retriever_examples/chatgpt-plugin-retriever.ipynb rename to docs/modules/indexes/retrievers/examples/chatgpt-plugin-retriever.ipynb diff --git a/docs/modules/indexes/retriever_examples/vectorstore-retriever.ipynb b/docs/modules/indexes/retrievers/examples/vectorstore-retriever.ipynb similarity index 97% rename from docs/modules/indexes/retriever_examples/vectorstore-retriever.ipynb rename to docs/modules/indexes/retrievers/examples/vectorstore-retriever.ipynb index ca03103e..d96ab341 100644 --- a/docs/modules/indexes/retriever_examples/vectorstore-retriever.ipynb +++ b/docs/modules/indexes/retrievers/examples/vectorstore-retriever.ipynb @@ -20,7 +20,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')" + "loader = TextLoader('../../../state_of_the_union.txt')" ] }, { diff --git a/docs/modules/indexes/text_splitters.rst b/docs/modules/indexes/text_splitters.rst new file mode 100644 index 00000000..ec020e57 --- /dev/null +++ b/docs/modules/indexes/text_splitters.rst @@ -0,0 +1,41 @@ +Text Splitters +========================== + +.. note:: + `Conceptual Guide `_ + + +When you want to deal with long pieces of text, it is necessary to split up that text into chunks. +As simple as this sounds, there is a lot of potential complexity here. Ideally, you want to keep the semantically related pieces of text together. What "semantically related" means could depend on the type of text. +This notebook showcases several ways to do that. + +At a high level, text splitters work as following: + +1. Split the text up into small, semantically meaningful chunks (often sentences). +2. Start combining these small chunks into a larger chunk until you reach a certain size (as measured by some function). +3. Once you reach that size, make that chunk its own piece of text and then start creating a new chunk of text with some overlap (to keep context between chunks). + +That means there two different axes along which you can customize your text splitter: + +1. How the text is split +2. How the chunk size is measured + +For an introduction to the default text splitter and generic functionality see: + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./text_splitters/getting_started.ipynb + + +We also have documentation for all the types of text splitters that are supported. +Please see below for that list. + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./text_splitters/examples/* \ No newline at end of file diff --git a/docs/modules/indexes/text_splitters/examples/character_text_splitter.ipynb b/docs/modules/indexes/text_splitters/examples/character_text_splitter.ipynb new file mode 100644 index 00000000..0f6ccf01 --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/character_text_splitter.ipynb @@ -0,0 +1,118 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5c461b26", + "metadata": {}, + "source": [ + "# Character Text Splitter\n", + "\n", + "This is a more simple method. This splits based on characters (by default \"\\n\\n\") and measure chunk length by number of characters.\n", + "\n", + "1. How the text is split: by single character\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9c21e679", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "79ff6737", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import CharacterTextSplitter\n", + "text_splitter = CharacterTextSplitter( \n", + " separator = \"\\n\\n\",\n", + " chunk_size = 1000,\n", + " chunk_overlap = 200,\n", + " length_function = len,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "38547666", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \\n\\nLast year COVID-19 kept us apart. This year we are finally together again. \\n\\nTonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \\n\\nWith a duty to one another to the American people to the Constitution. \\n\\nAnd with an unwavering resolve that freedom will always triumph over tyranny. \\n\\nSix days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways. But he badly miscalculated. \\n\\nHe thought he could roll into Ukraine and the world would roll over. Instead he met a wall of strength he never imagined. \\n\\nHe met the Ukrainian people. \\n\\nFrom President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.' lookup_str='' metadata={} lookup_index=0\n" + ] + } + ], + "source": [ + "texts = text_splitter.create_documents([state_of_the_union])\n", + "print(texts[0])" + ] + }, + { + "cell_type": "markdown", + "id": "2cede1b1", + "metadata": {}, + "source": [ + "Here's an example of passing metadata along with the documents, notice that it is split along with the documents." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4a47515a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \\n\\nLast year COVID-19 kept us apart. This year we are finally together again. \\n\\nTonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \\n\\nWith a duty to one another to the American people to the Constitution. \\n\\nAnd with an unwavering resolve that freedom will always triumph over tyranny. \\n\\nSix days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways. But he badly miscalculated. \\n\\nHe thought he could roll into Ukraine and the world would roll over. Instead he met a wall of strength he never imagined. \\n\\nHe met the Ukrainian people. \\n\\nFrom President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.' lookup_str='' metadata={'document': 1} lookup_index=0\n" + ] + } + ], + "source": [ + "metadatas = [{\"document\": 1}, {\"document\": 2}]\n", + "documents = text_splitter.create_documents([state_of_the_union, state_of_the_union], metadatas=metadatas)\n", + "print(documents[0])" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/huggingface_length_function.ipynb b/docs/modules/indexes/text_splitters/examples/huggingface_length_function.ipynb new file mode 100644 index 00000000..ef98bcfb --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/huggingface_length_function.ipynb @@ -0,0 +1,102 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "13dc0983", + "metadata": {}, + "source": [ + "# HuggingFace Length Function\n", + "Most LLMs are constrained by the number of tokens that you can pass in, which is not the same as the number of characters. In order to get a more accurate estimate, we can use HuggingFace tokenizers to count the text length.\n", + "\n", + "1. How the text is split: by character passed in\n", + "2. How the chunk size is measured: by Hugging Face tokenizer" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a8ce51d5", + "metadata": {}, + "outputs": [], + "source": [ + "from transformers import GPT2TokenizerFast\n", + "\n", + "tokenizer = GPT2TokenizerFast.from_pretrained(\"gpt2\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "388369ed", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()\n", + "from langchain.text_splitter import CharacterTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ca5e72c0", + "metadata": {}, + "outputs": [], + "source": [ + "text_splitter = CharacterTextSplitter.from_huggingface_tokenizer(tokenizer, chunk_size=100, chunk_overlap=0)\n", + "texts = text_splitter.split_text(state_of_the_union)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "37cdfbeb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \n", + "\n", + "Last year COVID-19 kept us apart. This year we are finally together again. \n", + "\n", + "Tonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \n", + "\n", + "With a duty to one another to the American people to the Constitution.\n" + ] + } + ], + "source": [ + "print(texts[0])" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/latex.ipynb b/docs/modules/indexes/text_splitters/examples/latex.ipynb new file mode 100644 index 00000000..596dd8c1 --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/latex.ipynb @@ -0,0 +1,115 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "3a2f572e", + "metadata": {}, + "source": [ + "# Latex Text Splitter\n", + "\n", + "LatexTextSplitter splits text along Latex headings, headlines, enumerations and more. It's implemented as a simple subclass of RecursiveCharacterSplitter with Latex-specific separators. See the source code to see the Latex syntax expected by default.\n", + "\n", + "1. How the text is split: by list of latex specific tags\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c2503917", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import LatexTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e46b753b", + "metadata": {}, + "outputs": [], + "source": [ + "latex_text = \"\"\"\n", + "\\documentclass{article}\n", + "\n", + "\\begin{document}\n", + "\n", + "\\maketitle\n", + "\n", + "\\section{Introduction}\n", + "Large language models (LLMs) are a type of machine learning model that can be trained on vast amounts of text data to generate human-like language. In recent years, LLMs have made significant advances in a variety of natural language processing tasks, including language translation, text generation, and sentiment analysis.\n", + "\n", + "\\subsection{History of LLMs}\n", + "The earliest LLMs were developed in the 1980s and 1990s, but they were limited by the amount of data that could be processed and the computational power available at the time. In the past decade, however, advances in hardware and software have made it possible to train LLMs on massive datasets, leading to significant improvements in performance.\n", + "\n", + "\\subsection{Applications of LLMs}\n", + "LLMs have many applications in industry, including chatbots, content creation, and virtual assistants. They can also be used in academia for research in linguistics, psychology, and computational linguistics.\n", + "\n", + "\\end{document}\n", + "\"\"\"\n", + "latex_splitter = LatexTextSplitter(chunk_size=400, chunk_overlap=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "73b5bd33", + "metadata": {}, + "outputs": [], + "source": [ + "docs = latex_splitter.create_documents([latex_text])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e1c7fbd5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Document(page_content='\\\\documentclass{article}\\n\\n\\x08egin{document}\\n\\n\\\\maketitle', lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content='Introduction}\\nLarge language models (LLMs) are a type of machine learning model that can be trained on vast amounts of text data to generate human-like language. In recent years, LLMs have made significant advances in a variety of natural language processing tasks, including language translation, text generation, and sentiment analysis.', lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content='History of LLMs}\\nThe earliest LLMs were developed in the 1980s and 1990s, but they were limited by the amount of data that could be processed and the computational power available at the time. In the past decade, however, advances in hardware and software have made it possible to train LLMs on massive datasets, leading to significant improvements in performance.', lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content='Applications of LLMs}\\nLLMs have many applications in industry, including chatbots, content creation, and virtual assistants. They can also be used in academia for research in linguistics, psychology, and computational linguistics.\\n\\n\\\\end{document}', lookup_str='', metadata={}, lookup_index=0)]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "docs" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/markdown.ipynb b/docs/modules/indexes/text_splitters/examples/markdown.ipynb new file mode 100644 index 00000000..adcc099f --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/markdown.ipynb @@ -0,0 +1,110 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "80f6cd99", + "metadata": {}, + "source": [ + "# Markdown Text Splitter\n", + "\n", + "MarkdownTextSplitter splits text along Markdown headings, code blocks, or horizontal rules. It's implemented as a simple subclass of RecursiveCharacterSplitter with Markdown-specific separators. See the source code to see the Markdown syntax expected by default.\n", + "\n", + "1. How the text is split: by list of markdown specific characters\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "96d64839", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import MarkdownTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cfb0da17", + "metadata": {}, + "outputs": [], + "source": [ + "markdown_text = \"\"\"\n", + "# 🦜️🔗 LangChain\n", + "\n", + "⚡ Building applications with LLMs through composability ⚡\n", + "\n", + "## Quick Install\n", + "\n", + "```bash\n", + "# Hopefully this code block isn't split\n", + "pip install langchain\n", + "```\n", + "\n", + "As an open source project in a rapidly developing field, we are extremely open to contributions.\n", + "\"\"\"\n", + "markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d59a4fe8", + "metadata": {}, + "outputs": [], + "source": [ + "docs = markdown_splitter.create_documents([markdown_text])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "cbb2e100", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Document(page_content='# 🦜️🔗 LangChain\\n\\n⚡ Building applications with LLMs through composability ⚡', lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content=\"Quick Install\\n\\n```bash\\n# Hopefully this code block isn't split\\npip install langchain\", lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content='As an open source project in a rapidly developing field, we are extremely open to contributions.', lookup_str='', metadata={}, lookup_index=0)]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "docs" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/nltk.ipynb b/docs/modules/indexes/text_splitters/examples/nltk.ipynb new file mode 100644 index 00000000..bdf084a6 --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/nltk.ipynb @@ -0,0 +1,116 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ea2973ac", + "metadata": {}, + "source": [ + "# NLTK Text Splitter\n", + "Rather than just splitting on \"\\n\\n\", we can use NLTK to split based on tokenizers.\n", + "\n", + "1. How the text is split: by NLTK\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "aed17ddf", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "20fa9c23", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import NLTKTextSplitter\n", + "text_splitter = NLTKTextSplitter(chunk_size=1000)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5ea10835", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Madam Speaker, Madam Vice President, our First Lady and Second Gentleman.\n", + "\n", + "Members of Congress and the Cabinet.\n", + "\n", + "Justices of the Supreme Court.\n", + "\n", + "My fellow Americans.\n", + "\n", + "Last year COVID-19 kept us apart.\n", + "\n", + "This year we are finally together again.\n", + "\n", + "Tonight, we meet as Democrats Republicans and Independents.\n", + "\n", + "But most importantly as Americans.\n", + "\n", + "With a duty to one another to the American people to the Constitution.\n", + "\n", + "And with an unwavering resolve that freedom will always triumph over tyranny.\n", + "\n", + "Six days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways.\n", + "\n", + "But he badly miscalculated.\n", + "\n", + "He thought he could roll into Ukraine and the world would roll over.\n", + "\n", + "Instead he met a wall of strength he never imagined.\n", + "\n", + "He met the Ukrainian people.\n", + "\n", + "From President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.\n", + "\n", + "Groups of citizens blocking tanks with their bodies.\n" + ] + } + ], + "source": [ + "texts = text_splitter.split_text(state_of_the_union)\n", + "print(texts[0])" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/python.ipynb b/docs/modules/indexes/text_splitters/examples/python.ipynb new file mode 100644 index 00000000..7dddfc8f --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/python.ipynb @@ -0,0 +1,108 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c350765d", + "metadata": {}, + "source": [ + "# Python Code Text Splitter\n", + "\n", + "PythonCodeTextSplitter splits text along python class and method definitions. It's implemented as a simple subclass of RecursiveCharacterSplitter with Python-specific separators. See the source code to see the Python syntax expected by default.\n", + "\n", + "1. How the text is split: by list of python specific characters\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1703463f", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import PythonCodeTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f17a1854", + "metadata": {}, + "outputs": [], + "source": [ + "python_text = \"\"\"\n", + "class Foo:\n", + "\n", + " def bar():\n", + " \n", + " \n", + "def foo():\n", + "\n", + "def testing_func():\n", + "\n", + "def bar():\n", + "\"\"\"\n", + "python_splitter = PythonCodeTextSplitter(chunk_size=30, chunk_overlap=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "6cdc55f3", + "metadata": {}, + "outputs": [], + "source": [ + "docs = python_splitter.create_documents([python_text])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8cc33770", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Document(page_content='Foo:\\n\\n def bar():', lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content='foo():\\n\\ndef testing_func():', lookup_str='', metadata={}, lookup_index=0),\n", + " Document(page_content='bar():', lookup_str='', metadata={}, lookup_index=0)]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "docs" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/recursive_text_splitter.ipynb b/docs/modules/indexes/text_splitters/examples/recursive_text_splitter.ipynb new file mode 100644 index 00000000..c9cb7356 --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/recursive_text_splitter.ipynb @@ -0,0 +1,101 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "072eee66", + "metadata": {}, + "source": [ + "# RecursiveCharaterTextSplitter\n", + "This text splitter is the recommended one for generic text. It is parameterized by a list of characters. It tries to split on them in order until the chunks are small enough. The default list is `[\"\\n\\n\", \"\\n\", \" \", \"\"]`. This has the effect of trying to keep all paragraphs (and then sentences, and then words) together as long as possible, as those would generically seem to be the strongest semantically related pieces of text.\n", + "\n", + "\n", + "1. How the text is split: by list of characters\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d887c134", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "14662639", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import RecursiveCharacterTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "fc6e42c8", + "metadata": {}, + "outputs": [], + "source": [ + "text_splitter = RecursiveCharacterTextSplitter(\n", + " # Set a really small chunk size, just to show.\n", + " chunk_size = 100,\n", + " chunk_overlap = 20,\n", + " length_function = len,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bd1a0a15", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and' lookup_str='' metadata={} lookup_index=0\n", + "page_content='of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.' lookup_str='' metadata={} lookup_index=0\n" + ] + } + ], + "source": [ + "texts = text_splitter.create_documents([state_of_the_union])\n", + "print(texts[0])\n", + "print(texts[1])" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/spacy.ipynb b/docs/modules/indexes/text_splitters/examples/spacy.ipynb new file mode 100644 index 00000000..ba442723 --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/spacy.ipynb @@ -0,0 +1,138 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "dab86b60", + "metadata": {}, + "source": [ + "# Spacy Text Splitter\n", + "Another alternative to NLTK is to use Spacy.\n", + "\n", + "1. How the text is split: by Spacy\n", + "2. How the chunk size is measured: by length function passed in (defaults to number of characters)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f1de7767", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f4ec9b90", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import SpacyTextSplitter\n", + "text_splitter = SpacyTextSplitter(chunk_size=1000)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "cef2b29e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Madam Speaker, Madam Vice President, our First Lady and Second Gentleman.\n", + "\n", + "Members of Congress and the Cabinet.\n", + "\n", + "Justices of the Supreme Court.\n", + "\n", + "My fellow Americans. \n", + "\n", + "\n", + "\n", + "Last year COVID-19 kept us apart.\n", + "\n", + "This year we are finally together again. \n", + "\n", + "\n", + "\n", + "Tonight, we meet as Democrats Republicans and Independents.\n", + "\n", + "But most importantly as Americans. \n", + "\n", + "\n", + "\n", + "With a duty to one another to the American people to the Constitution. \n", + "\n", + "\n", + "\n", + "And with an unwavering resolve that freedom will always triumph over tyranny. \n", + "\n", + "\n", + "\n", + "Six days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways.\n", + "\n", + "But he badly miscalculated. \n", + "\n", + "\n", + "\n", + "He thought he could roll into Ukraine and the world would roll over.\n", + "\n", + "Instead he met a wall of strength he never imagined. \n", + "\n", + "\n", + "\n", + "He met the Ukrainian people. \n", + "\n", + "\n", + "\n", + "From President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world.\n" + ] + } + ], + "source": [ + "texts = text_splitter.split_text(state_of_the_union)\n", + "print(texts[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff3064a7", + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/tiktoken.ipynb b/docs/modules/indexes/text_splitters/examples/tiktoken.ipynb new file mode 100644 index 00000000..c09b5cdf --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/tiktoken.ipynb @@ -0,0 +1,90 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7683b36a", + "metadata": {}, + "source": [ + "# tiktoken (OpenAI) Length Function\n", + "You can also use tiktoken, a open source tokenizer package from OpenAI to estimate tokens used. Will probably be more accurate for their models.\n", + "\n", + "1. How the text is split: by character passed in\n", + "2. How the chunk size is measured: by `tiktoken` tokenizer" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1ad2d0f2", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()\n", + "from langchain.text_splitter import CharacterTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "825f7c0a", + "metadata": {}, + "outputs": [], + "source": [ + "text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=100, chunk_overlap=0)\n", + "texts = text_splitter.split_text(state_of_the_union)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ae35d165", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \n", + "\n", + "Last year COVID-19 kept us apart. This year we are finally together again. \n", + "\n", + "Tonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \n", + "\n", + "With a duty to one another to the American people to the Constitution.\n" + ] + } + ], + "source": [ + "print(texts[0])" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/examples/tiktoken_splitter.ipynb b/docs/modules/indexes/text_splitters/examples/tiktoken_splitter.ipynb new file mode 100644 index 00000000..a3ad0a1a --- /dev/null +++ b/docs/modules/indexes/text_splitters/examples/tiktoken_splitter.ipynb @@ -0,0 +1,102 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "53049ff5", + "metadata": {}, + "source": [ + "# TiktokenText Splitter\n", + "\n", + "1. How the text is split: by `tiktoken` tokens\n", + "2. How the chunk size is measured: by `tiktoken` tokens" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8c73186a", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a1a118b1", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import TokenTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ef37c5d3", + "metadata": {}, + "outputs": [], + "source": [ + "text_splitter = TokenTextSplitter(chunk_size=10, chunk_overlap=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5750228a", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Madam Speaker, Madam Vice President, our\n" + ] + } + ], + "source": [ + "texts = text_splitter.split_text(state_of_the_union)\n", + "print(texts[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a87dc30", + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/text_splitters/getting_started.ipynb b/docs/modules/indexes/text_splitters/getting_started.ipynb new file mode 100644 index 00000000..ad8e179d --- /dev/null +++ b/docs/modules/indexes/text_splitters/getting_started.ipynb @@ -0,0 +1,103 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "072eee66", + "metadata": {}, + "source": [ + "# Getting Started\n", + "The default recommended text splitter is the RecursiveCharacterTextSplitter. This text splitter takes a list of characters. It tries to create chunks based on splitting on the first character, but if any chunks are too large it then moves onto the next character, and so forth. By default the characters it tries to split on are `[\"\\n\\n\", \"\\n\", \" \", \"\"]`\n", + "\n", + "In addition to controlling which characters you can split on, you can also control a few other things:\n", + "\n", + "- `length_function`: how the length of chunks is calculated. Defaults to just counting number of characters, but it's pretty common to pass a token counter here.\n", + "- `chunk_size`: the maximum size of your chunks (as measured by the length function).\n", + "- `chunk_overlap`: the maximum overlap between chunks. It can be nice to have some overlap to maintain some continuity between chunks (eg do a sliding window)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "aeff9aa3", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a long document we can split up.\n", + "with open('../../state_of_the_union.txt') as f:\n", + " state_of_the_union = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "14662639", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.text_splitter import RecursiveCharacterTextSplitter" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "fc6e42c8", + "metadata": {}, + "outputs": [], + "source": [ + "text_splitter = RecursiveCharacterTextSplitter(\n", + " # Set a really small chunk size, just to show.\n", + " chunk_size = 100,\n", + " chunk_overlap = 20,\n", + " length_function = len,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "bd1a0a15", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and' lookup_str='' metadata={} lookup_index=0\n", + "page_content='of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.' lookup_str='' metadata={} lookup_index=0\n" + ] + } + ], + "source": [ + "texts = text_splitter.create_documents([state_of_the_union])\n", + "print(texts[0])\n", + "print(texts[1])" + ] + } + ], + "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" + }, + "vscode": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/indexes/vectorstores.rst b/docs/modules/indexes/vectorstores.rst new file mode 100644 index 00000000..3f78ba0f --- /dev/null +++ b/docs/modules/indexes/vectorstores.rst @@ -0,0 +1,27 @@ +Vectorstores +========================== + +.. note:: + `Conceptual Guide `_ + + +Vectorstores are one of the most important components of building indexes. + +For an introduction to vectorstores and generic functionality see: + +.. toctree:: + :maxdepth: 1 + :glob: + + ./vectorstores/getting_started.ipynb + + +We also have documentation for all the types of vectorstores that are supported. +Please see below for that list. + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./vectorstores/examples/* \ No newline at end of file diff --git a/docs/modules/indexes/vectorstore_examples/atlas.ipynb b/docs/modules/indexes/vectorstores/examples/atlas.ipynb similarity index 97% rename from docs/modules/indexes/vectorstore_examples/atlas.ipynb rename to docs/modules/indexes/vectorstores/examples/atlas.ipynb index 92c388dc..53d57fc5 100644 --- a/docs/modules/indexes/vectorstore_examples/atlas.ipynb +++ b/docs/modules/indexes/vectorstores/examples/atlas.ipynb @@ -30,10 +30,10 @@ "cell_type": "code", "execution_count": null, "metadata": { - "scrolled": true, "pycharm": { "is_executing": true - } + }, + "scrolled": true }, "outputs": [], "source": [ @@ -55,7 +55,7 @@ "metadata": {}, "outputs": [], "source": [ - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = SpacyTextSplitter(separator='|')\n", "texts = []\n", @@ -85,13 +85,11 @@ { "cell_type": "code", "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "db.project.wait_for_project_lock()" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", @@ -192,7 +190,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.4" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/indexes/vectorstore_examples/chroma.ipynb b/docs/modules/indexes/vectorstores/examples/chroma.ipynb similarity index 99% rename from docs/modules/indexes/vectorstore_examples/chroma.ipynb rename to docs/modules/indexes/vectorstores/examples/chroma.ipynb index 2759548d..13738c16 100644 --- a/docs/modules/indexes/vectorstore_examples/chroma.ipynb +++ b/docs/modules/indexes/vectorstores/examples/chroma.ipynb @@ -31,7 +31,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/vectorstore_examples/deeplake.ipynb b/docs/modules/indexes/vectorstores/examples/deeplake.ipynb similarity index 97% rename from docs/modules/indexes/vectorstore_examples/deeplake.ipynb rename to docs/modules/indexes/vectorstores/examples/deeplake.ipynb index 3db7619c..3fc5e32c 100644 --- a/docs/modules/indexes/vectorstore_examples/deeplake.ipynb +++ b/docs/modules/indexes/vectorstores/examples/deeplake.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -31,7 +30,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", @@ -87,7 +86,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -206,7 +204,7 @@ ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -220,9 +218,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.7" + "version": "3.9.1" }, - "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "7b14174bb6f9d4680b62ac2a6390e1ce94fbfabf172a10844870451d539c58d6" diff --git a/docs/modules/indexes/vectorstore_examples/elasticsearch.ipynb b/docs/modules/indexes/vectorstores/examples/elasticsearch.ipynb similarity index 98% rename from docs/modules/indexes/vectorstore_examples/elasticsearch.ipynb rename to docs/modules/indexes/vectorstores/examples/elasticsearch.ipynb index d60f0500..74e3343c 100644 --- a/docs/modules/indexes/vectorstore_examples/elasticsearch.ipynb +++ b/docs/modules/indexes/vectorstores/examples/elasticsearch.ipynb @@ -31,7 +31,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/vectorstore_examples/faiss.ipynb b/docs/modules/indexes/vectorstores/examples/faiss.ipynb similarity index 99% rename from docs/modules/indexes/vectorstore_examples/faiss.ipynb rename to docs/modules/indexes/vectorstores/examples/faiss.ipynb index c15716fc..87933750 100644 --- a/docs/modules/indexes/vectorstore_examples/faiss.ipynb +++ b/docs/modules/indexes/vectorstores/examples/faiss.ipynb @@ -31,7 +31,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/vectorstore_examples/milvus.ipynb b/docs/modules/indexes/vectorstores/examples/milvus.ipynb similarity index 97% rename from docs/modules/indexes/vectorstore_examples/milvus.ipynb rename to docs/modules/indexes/vectorstores/examples/milvus.ipynb index d1f3110d..ffdbb5d0 100644 --- a/docs/modules/indexes/vectorstore_examples/milvus.ipynb +++ b/docs/modules/indexes/vectorstores/examples/milvus.ipynb @@ -33,7 +33,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/vectorstore_examples/opensearch.ipynb b/docs/modules/indexes/vectorstores/examples/opensearch.ipynb similarity index 91% rename from docs/modules/indexes/vectorstore_examples/opensearch.ipynb rename to docs/modules/indexes/vectorstores/examples/opensearch.ipynb index 226090a2..4cc937c5 100644 --- a/docs/modules/indexes/vectorstore_examples/opensearch.ipynb +++ b/docs/modules/indexes/vectorstores/examples/opensearch.ipynb @@ -36,7 +36,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", @@ -47,153 +47,150 @@ { "cell_type": "code", "execution_count": null, + "id": "db3fa309", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [], "source": [ "docsearch = OpenSearchVectorSearch.from_texts(texts, embeddings, opensearch_url=\"http://localhost:9200\")\n", "\n", "query = \"What did the president say about Ketanji Brown Jackson\"\n", "docs = docsearch.similarity_search(query)" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } + ] }, { "cell_type": "code", "execution_count": null, - "outputs": [], - "source": [ - "print(docs[0].page_content)" - ], + "id": "c160d5bb", "metadata": { - "collapsed": false, "pycharm": { "name": "#%%\n" } - } + }, + "outputs": [], + "source": [ + "print(docs[0].page_content)" + ] }, { "cell_type": "markdown", + "id": "01a9a035", + "metadata": {}, "source": [ "#### similarity_search using Approximate k-NN Search with Custom Parameters" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "id": "96215c90", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [], "source": [ "docsearch = OpenSearchVectorSearch.from_texts(texts, embeddings, opensearch_url=\"http://localhost:9200\", engine=\"faiss\", space_type=\"innerproduct\", ef_construction=256, m=48)\n", "\n", "query = \"What did the president say about Ketanji Brown Jackson\"\n", "docs = docsearch.similarity_search(query)" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } + ] }, { "cell_type": "code", "execution_count": null, - "outputs": [], - "source": [ - "print(docs[0].page_content)" - ], + "id": "62a7cea0", "metadata": { - "collapsed": false, "pycharm": { "name": "#%%\n" } - } + }, + "outputs": [], + "source": [ + "print(docs[0].page_content)" + ] }, { "cell_type": "markdown", + "id": "0d0cd877", + "metadata": {}, "source": [ "#### similarity_search using Script Scoring with Custom Parameters" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "id": "0a8e3c0e", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [], "source": [ "docsearch = OpenSearchVectorSearch.from_texts(texts, embeddings, opensearch_url=\"http://localhost:9200\", is_appx_search=False)\n", "\n", "query = \"What did the president say about Ketanji Brown Jackson\"\n", "docs = docsearch.similarity_search(\"What did the president say about Ketanji Brown Jackson\", k=1, search_type=\"script_scoring\")" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } + ] }, { "cell_type": "code", "execution_count": null, - "outputs": [], - "source": [ - "print(docs[0].page_content)" - ], + "id": "92bc40db", "metadata": { - "collapsed": false, "pycharm": { "name": "#%%\n" } - } + }, + "outputs": [], + "source": [ + "print(docs[0].page_content)" + ] }, { "cell_type": "markdown", + "id": "a4af96cc", + "metadata": {}, "source": [ "#### similarity_search using Painless Scripting with Custom Parameters" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "id": "6d9f436e", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [], "source": [ "docsearch = OpenSearchVectorSearch.from_texts(texts, embeddings, opensearch_url=\"http://localhost:9200\", is_appx_search=False)\n", "filter = {\"bool\": {\"filter\": {\"term\": {\"text\": \"smuggling\"}}}}\n", "query = \"What did the president say about Ketanji Brown Jackson\"\n", "docs = docsearch.similarity_search(\"What did the president say about Ketanji Brown Jackson\", search_type=\"painless_scripting\", space_type=\"cosineSimilarity\", pre_filter=filter)" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } + ] }, { "cell_type": "code", "execution_count": null, - "outputs": [], - "source": [ - "print(docs[0].page_content)" - ], + "id": "8ca50bce", "metadata": { - "collapsed": false, "pycharm": { "name": "#%%\n" } - } + }, + "outputs": [], + "source": [ + "print(docs[0].page_content)" + ] } ], "metadata": { @@ -217,4 +214,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/modules/indexes/vectorstore_examples/pgvector.ipynb b/docs/modules/indexes/vectorstores/examples/pgvector.ipynb similarity index 97% rename from docs/modules/indexes/vectorstore_examples/pgvector.ipynb rename to docs/modules/indexes/vectorstores/examples/pgvector.ipynb index e460d832..e71e1ac4 100644 --- a/docs/modules/indexes/vectorstore_examples/pgvector.ipynb +++ b/docs/modules/indexes/vectorstores/examples/pgvector.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -41,7 +40,7 @@ "metadata": {}, "outputs": [], "source": [ - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", @@ -73,7 +72,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -81,7 +79,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -171,7 +168,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -185,9 +182,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.10" - }, - "orig_nbformat": 4 + "version": "3.9.1" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/docs/modules/indexes/vectorstore_examples/pinecone.ipynb b/docs/modules/indexes/vectorstores/examples/pinecone.ipynb similarity index 97% rename from docs/modules/indexes/vectorstore_examples/pinecone.ipynb rename to docs/modules/indexes/vectorstores/examples/pinecone.ipynb index 95c4e029..eaa35b47 100644 --- a/docs/modules/indexes/vectorstore_examples/pinecone.ipynb +++ b/docs/modules/indexes/vectorstores/examples/pinecone.ipynb @@ -31,7 +31,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/vectorstore_examples/qdrant.ipynb b/docs/modules/indexes/vectorstores/examples/qdrant.ipynb similarity index 97% rename from docs/modules/indexes/vectorstore_examples/qdrant.ipynb rename to docs/modules/indexes/vectorstores/examples/qdrant.ipynb index 250a88b8..73f2fd2d 100644 --- a/docs/modules/indexes/vectorstore_examples/qdrant.ipynb +++ b/docs/modules/indexes/vectorstores/examples/qdrant.ipynb @@ -31,7 +31,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/vectorstore_examples/redis.ipynb b/docs/modules/indexes/vectorstores/examples/redis.ipynb similarity index 84% rename from docs/modules/indexes/vectorstore_examples/redis.ipynb rename to docs/modules/indexes/vectorstores/examples/redis.ipynb index 385ba0b7..5fe54f1d 100644 --- a/docs/modules/indexes/vectorstore_examples/redis.ipynb +++ b/docs/modules/indexes/vectorstores/examples/redis.ipynb @@ -2,63 +2,58 @@ "cells": [ { "cell_type": "markdown", + "metadata": {}, "source": [ "# Redis\n", "\n", "This notebook shows how to use functionality related to the Redis database." - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": 1, + "metadata": {}, "outputs": [], "source": [ "from langchain.embeddings.openai import OpenAIEmbeddings\n", "from langchain.text_splitter import CharacterTextSplitter\n", "from langchain.vectorstores.redis import Redis" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": 3, + "metadata": {}, "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", "\n", "embeddings = OpenAIEmbeddings()" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": 4, + "metadata": {}, "outputs": [], "source": [ "rds = Redis.from_documents(docs, embeddings, redis_url=\"redis://localhost:6379\", index_name='link')" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": 5, + "metadata": {}, "outputs": [ { "data": { - "text/plain": "'b564189668a343648996bd5a1d353d4e'" + "text/plain": [ + "'b564189668a343648996bd5a1d353d4e'" + ] }, "execution_count": 5, "metadata": {}, @@ -67,21 +62,17 @@ ], "source": [ "rds.index_name" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", - "source": [], - "metadata": { - "collapsed": false - } + "metadata": {}, + "source": [] }, { "cell_type": "code", "execution_count": 6, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -105,14 +96,12 @@ "query = \"What did the president say about Ketanji Brown Jackson\"\n", "results = rds.similarity_search(query)\n", "print(results[0].page_content)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": 7, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -124,14 +113,12 @@ ], "source": [ "print(rds.add_texts([\"Ankush went to Princeton\"]))" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": 8, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -145,14 +132,12 @@ "query = \"Princeton\"\n", "results = rds.similarity_search(query)\n", "print(results[0].page_content)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "#Query\n", @@ -161,31 +146,28 @@ "query = \"What did the president say about Ketanji Brown Jackson\"\n", "results = rds.similarity_search(query)\n", "print(results[0].page_content)" - ], - "metadata": { - "collapsed": false - } + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" + "pygments_lexer": "ipython3", + "version": "3.9.1" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/docs/modules/indexes/vectorstore_examples/weaviate.ipynb b/docs/modules/indexes/vectorstores/examples/weaviate.ipynb similarity index 98% rename from docs/modules/indexes/vectorstore_examples/weaviate.ipynb rename to docs/modules/indexes/vectorstores/examples/weaviate.ipynb index 9ae4abe8..1c5b001f 100644 --- a/docs/modules/indexes/vectorstore_examples/weaviate.ipynb +++ b/docs/modules/indexes/vectorstores/examples/weaviate.ipynb @@ -31,7 +31,7 @@ "outputs": [], "source": [ "from langchain.document_loaders import TextLoader\n", - "loader = TextLoader('../../state_of_the_union.txt')\n", + "loader = TextLoader('../../../state_of_the_union.txt')\n", "documents = loader.load()\n", "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", "docs = text_splitter.split_documents(documents)\n", diff --git a/docs/modules/indexes/examples/vectorstores.ipynb b/docs/modules/indexes/vectorstores/getting_started.ipynb similarity index 99% rename from docs/modules/indexes/examples/vectorstores.ipynb rename to docs/modules/indexes/vectorstores/getting_started.ipynb index ee30111d..7070933d 100644 --- a/docs/modules/indexes/examples/vectorstores.ipynb +++ b/docs/modules/indexes/vectorstores/getting_started.ipynb @@ -9,7 +9,7 @@ } }, "source": [ - "# VectorStores\n", + "# Getting Started\n", "\n", "This notebook showcases basic functionality related to VectorStores. A key part of working with vectorstores is creating the vector to put in them, which is usually created via embeddings. Therefore, it is recommended that you familiarize yourself with the [embedding notebook](embeddings.ipynb) before diving into this.\n", "\n", diff --git a/docs/modules/llms/generic_how_to.rst b/docs/modules/llms/generic_how_to.rst deleted file mode 100644 index c1146aa2..00000000 --- a/docs/modules/llms/generic_how_to.rst +++ /dev/null @@ -1,24 +0,0 @@ -Generic Functionality -===================== - -The examples here all address certain "how-to" guides for working with LLMs. - -`LLM Serialization <./examples/llm_serialization.html>`_: A walkthrough of how to serialize LLMs to and from disk. - -`LLM Caching <./examples/llm_caching.html>`_: Covers different types of caches, and how to use a cache to save results of LLM calls. - -`Custom LLM <./examples/custom_llm.html>`_: How to create and use a custom LLM class, in case you have an LLM not from one of the standard providers (including one that you host yourself). - -`Token Usage Tracking <./examples/token_usage_tracking.html>`_: How to track the token usage of various chains/agents/LLM calls. - -`Fake LLM <./examples/fake_llm.html>`_: How to create and use a fake LLM for testing and debugging purposes. - - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Generic Functionality - :name: Generic Functionality - :hidden: - - ./examples/* diff --git a/docs/modules/llms/how_to_guides.rst b/docs/modules/llms/how_to_guides.rst deleted file mode 100644 index a8a71cc9..00000000 --- a/docs/modules/llms/how_to_guides.rst +++ /dev/null @@ -1,21 +0,0 @@ -How-To Guides -============= - -The examples here all address certain "how-to" guides for working with LLMs. -They are split into two categories: - - -1. `Generic Functionality <./generic_how_to.html>`_: Covering generic functionality all LLMs should have. -2. `Integrations <./integrations.html>`_: Covering integrations with various LLM providers. -3. `Asynchronous <./async_llm.html>`_: Covering asynchronous functionality. -4. `Streaming <./streaming_llm.html>`_: Covering streaming functionality. - -.. toctree:: - :maxdepth: 1 - :glob: - :hidden: - - ./generic_how_to.rst - ./integrations.rst - ./async_llm.ipynb - ./streaming_llm.ipynb diff --git a/docs/modules/llms/integrations.rst b/docs/modules/llms/integrations.rst deleted file mode 100644 index 55056431..00000000 --- a/docs/modules/llms/integrations.rst +++ /dev/null @@ -1,50 +0,0 @@ -Integrations -============= - -The examples here are all "how-to" guides for how to integrate with various LLM providers. - -`OpenAI <./integrations/openai.html>`_: Covers how to connect to OpenAI models. - -`Cohere <./integrations/cohere.html>`_: Covers how to connect to Cohere models. - -`AI21 <./integrations/ai21.html>`_: Covers how to connect to AI21 models. - -`Huggingface Hub <./integrations/huggingface_hub.html>`_: Covers how to connect to LLMs hosted on HuggingFace Hub. - -`Azure OpenAI <./integrations/azure_openai_example.html>`_: Covers how to connect to Azure-hosted OpenAI Models. - -`Manifest <./integrations/manifest.html>`_: Covers how to utilize the Manifest wrapper. - -`Goose AI <./integrations/gooseai_example.html>`_: Covers how to utilize the Goose AI wrapper. - -`Writer <./integrations/writer.html>`_: Covers how to utilize the Writer wrapper. - -`Banana <./integrations/banana.html>`_: Covers how to utilize the Banana wrapper. - -`Modal <./integrations/modal.html>`_: Covers how to utilize the Modal wrapper. - -`StochasticAI <./integrations/stochasticai.html>`_: Covers how to utilize the Stochastic AI wrapper. - -`Cerebrium <./integrations/cerebriumai_example.html>`_: Covers how to utilize the Cerebrium AI wrapper. - -`Petals <./integrations/petals_example.html>`_: Covers how to utilize the Petals wrapper. - -`Forefront AI <./integrations/forefrontai_example.html>`_: Covers how to utilize the Forefront AI wrapper. - -`PromptLayer OpenAI <./integrations/promptlayer_openai.html>`_: Covers how to use `PromptLayer `_ with LangChain. - -`Anthropic <./integrations/anthropic_example.html>`_: Covers how to use Anthropic models with LangChain. - -`DeepInfra <./integrations/deepinfra_example.html>`_: Covers how to utilize the DeepInfra wrapper. - -`Self-Hosted Models (via Runhouse) <./integrations/self_hosted_examples.html>`_: Covers how to run models on existing or on-demand remote compute with LangChain. - - -.. toctree:: - :maxdepth: 1 - :glob: - :caption: Specific LLM Integrations - :name: Specific LLM Integrations - :hidden: - - ./integrations/* diff --git a/docs/modules/llms/key_concepts.md b/docs/modules/llms/key_concepts.md deleted file mode 100644 index 47512248..00000000 --- a/docs/modules/llms/key_concepts.md +++ /dev/null @@ -1,19 +0,0 @@ -# Key Concepts - -## LLMs -Wrappers around Large Language Models (in particular, the "generate" ability of large language models) are at the core of LangChain functionality. -The core method that these classes expose is a `generate` method, which takes in a list of strings and returns an LLMResult (which contains outputs for all input strings). Read more about [LLMResult](#llmresult). - -This interface operates over a list of strings because often the lists of strings can be batched to the LLM provider, providing speed and efficiency gains. -For convenience, this class also exposes a simpler, more user friendly interface (via `__call__`). -The interface for this takes in a single string, and returns a single string. - -## Generation -The output of a single generation. Currently in LangChain this is just the generated text, although could be extended in the future -to contain log probs or the like. - -## LLMResult -The full output of a call to the `generate` method of the LLM class. -Since the `generate` method takes as input a list of strings, this returns a list of results. -Each result consists of a list of generations (since you can request N generations per input string). -This also contains a `llm_output` attribute which contains provider-specific information about the call. diff --git a/docs/modules/memory.rst b/docs/modules/memory.rst index e084ca3d..53ea84cd 100644 --- a/docs/modules/memory.rst +++ b/docs/modules/memory.rst @@ -1,6 +1,10 @@ Memory ========================== +.. note:: + `Conceptual Guide `_ + + By default, Chains and Agents are stateless, meaning that they treat each incoming query independently (as are the underlying LLMs and chat models). In some applications (chatbots being a GREAT example) it is highly important @@ -16,8 +20,6 @@ The following sections of documentation are provided: - `Getting Started <./memory/getting_started.html>`_: An overview of how to get started with different types of memory. -- `Key Concepts <./memory/key_concepts.html>`_: A conceptual guide going over the various concepts related to memory. - - `How-To Guides <./memory/how_to_guides.html>`_: A collection of how-to guides. These highlight different types of memory, as well as how to use memory in chains. @@ -28,5 +30,4 @@ The following sections of documentation are provided: :name: Memory ./memory/getting_started.ipynb - ./memory/key_concepts.rst ./memory/how_to_guides.rst diff --git a/docs/modules/memory/examples/adding_memory.ipynb b/docs/modules/memory/examples/adding_memory.ipynb index aed96f3d..0855aad0 100644 --- a/docs/modules/memory/examples/adding_memory.ipynb +++ b/docs/modules/memory/examples/adding_memory.ipynb @@ -5,7 +5,7 @@ "id": "00695447", "metadata": {}, "source": [ - "# Adding Memory To an LLMChain\n", + "# How to add Memory to an LLMChain\n", "\n", "This notebook goes over how to use the Memory class with an LLMChain. For the purposes of this walkthrough, we will add the `ConversationBufferMemory` class, although this can be any memory class." ] diff --git a/docs/modules/memory/examples/adding_memory_chain_multiple_inputs.ipynb b/docs/modules/memory/examples/adding_memory_chain_multiple_inputs.ipynb index 714ddb79..7e3febb5 100644 --- a/docs/modules/memory/examples/adding_memory_chain_multiple_inputs.ipynb +++ b/docs/modules/memory/examples/adding_memory_chain_multiple_inputs.ipynb @@ -5,7 +5,7 @@ "id": "e42733c5", "metadata": {}, "source": [ - "# Adding Memory to a Multi-Input Chain\n", + "# How to add memory to a Multi-Input Chain\n", "\n", "Most memory objects assume a single output. In this notebook, we go over how to add memory to a chain that has multiple outputs. As an example of such a chain, we will add memory to a question/answering chain. This chain takes as inputs both related documents and a user question." ] diff --git a/docs/modules/memory/examples/agent_with_memory.ipynb b/docs/modules/memory/examples/agent_with_memory.ipynb index 002a1aa2..4f0010a8 100644 --- a/docs/modules/memory/examples/agent_with_memory.ipynb +++ b/docs/modules/memory/examples/agent_with_memory.ipynb @@ -5,7 +5,7 @@ "id": "fa6802ac", "metadata": {}, "source": [ - "# Adding Memory to an Agent\n", + "# How to add Memory to an Agent\n", "\n", "This notebook goes over adding memory to an Agent. Before going through this notebook, please walkthrough the following notebooks, as this will build on top of both of them:\n", "\n", diff --git a/docs/modules/memory/examples/conversational_customization.ipynb b/docs/modules/memory/examples/conversational_customization.ipynb index 2f28e605..27559e80 100644 --- a/docs/modules/memory/examples/conversational_customization.ipynb +++ b/docs/modules/memory/examples/conversational_customization.ipynb @@ -5,7 +5,7 @@ "id": "69e35d6f", "metadata": {}, "source": [ - "# Conversational Memory Customization\n", + "# How to customize conversational memory\n", "\n", "This notebook walks through a few ways to customize conversational memory." ] diff --git a/docs/modules/memory/examples/custom_memory.ipynb b/docs/modules/memory/examples/custom_memory.ipynb index b66dbe63..d752731b 100644 --- a/docs/modules/memory/examples/custom_memory.ipynb +++ b/docs/modules/memory/examples/custom_memory.ipynb @@ -5,7 +5,7 @@ "id": "94e33ebe", "metadata": {}, "source": [ - "# Custom Memory\n", + "# How to create a custom Memory class\n", "Although there are a few predefined types of memory in LangChain, it is highly possible you will want to add your own type of memory that is optimal for your application. This notebook covers how to do that." ] }, diff --git a/docs/modules/memory/examples/multiple_memory.ipynb b/docs/modules/memory/examples/multiple_memory.ipynb index 082b8f31..dd25bde1 100644 --- a/docs/modules/memory/examples/multiple_memory.ipynb +++ b/docs/modules/memory/examples/multiple_memory.ipynb @@ -5,7 +5,7 @@ "id": "d9fec22e", "metadata": {}, "source": [ - "# Multiple Memory\n", + "# How to use multiple memroy classes in the same chain\n", "It is also possible to use multiple memory classes in the same chain. To combine multiple memory classes, we can initialize the `CombinedMemory` class, and then use that." ] }, diff --git a/docs/modules/memory/how_to_guides.rst b/docs/modules/memory/how_to_guides.rst index 0818cdc0..6c36cd2f 100644 --- a/docs/modules/memory/how_to_guides.rst +++ b/docs/modules/memory/how_to_guides.rst @@ -6,23 +6,10 @@ Types The first set of examples all highlight different types of memory. -`Buffer <./types/buffer.html>`_: How to use a type of memory that just keeps previous messages in a buffer. - -`Buffer Window <./types/buffer_window.html>`_: How to use a type of memory that keeps previous messages in a buffer but only uses the previous `k` of them. - -`Summary <./types/summary.html>`_: How to use a type of memory that summarizes previous messages. - -`Summary Buffer <./types/summary_buffer.html>`_: How to use a type of memory that keeps a buffer of messages up to a point, and then summarizes them. - -`Entity Memory <./types/entity_summary_memory.html>`_: How to use a type of memory that organizes information by entity. - -`Knowledge Graph Memory <./types/kg.html>`_: How to use a type of memory that extracts and organizes information in a knowledge graph - .. toctree:: :maxdepth: 1 :glob: - :hidden: ./types/* @@ -32,26 +19,8 @@ Usage The examples here all highlight how to use memory in different ways. -`Adding Memory <./examples/adding_memory.html>`_: How to add a memory component to any single input chain. - -`ChatGPT Clone <./examples/chatgpt_clone.html>`_: How to recreate ChatGPT with LangChain prompting + memory components. - -`Adding Memory to Multi-Input Chain <./examples/adding_memory_chain_multiple_inputs.html>`_: How to add a memory component to any multiple input chain. - -`Conversational Memory Customization <./examples/conversational_customization.html>`_: How to customize existing conversation memory components. - -`Custom Memory <./examples/custom_memory.html>`_: How to write your own custom memory component. - -`Adding Memory to Agents <./examples/agent_with_memory.html>`_: How to add a memory component to any agent. - -`Conversation Agent <./examples/conversational_agent.html>`_: Example of a conversation agent, which combines memory with agents and a conversation focused prompt. - -`Multiple Memory <./examples/multiple_memory.html>`_: How to use multiple types of memory in the same chain. - - .. toctree:: :maxdepth: 1 :glob: - :hidden: ./examples/* \ No newline at end of file diff --git a/docs/modules/memory/key_concepts.md b/docs/modules/memory/key_concepts.md deleted file mode 100644 index 445cf6d4..00000000 --- a/docs/modules/memory/key_concepts.md +++ /dev/null @@ -1,19 +0,0 @@ -# Key Concepts - -## Memory -By default, Chains and Agents are stateless, meaning that they treat each incoming query independently. -In some applications (chatbots being a GREAT example) it is highly important to remember previous interactions, -both at a short term but also at a long term level. The concept of "Memory" exists to do exactly that. - -## Conversational Memory -One of the simpler forms of memory occurs in chatbots, where they remember previous conversations. -There are a few different ways to accomplish this: -- Buffer: This is just passing in the past `N` interactions in as context. `N` can be chosen based on a fixed number, the length of the interactions, or other! -- Summary: This involves summarizing previous conversations and passing that summary in, instead of the raw dialogue itself. Compared to `Buffer`, this compresses information: meaning it is more lossy, but also less likely to run into context length limits. -- Combination: A combination of the above two approaches, where you compute a summary but also pass in some previous interactions directly! - -## Entity Memory -A more complex form of memory is remembering information about specific entities in the conversation. -This is a more direct and organized way of remembering information over time. -Putting it a more structured form also has the benefit of allowing easy inspection of what is known about specific entities. -For a guide on how to use this type of memory, see [this notebook](types/entity_summary_memory.ipynb). diff --git a/docs/modules/models.rst b/docs/modules/models.rst new file mode 100644 index 00000000..f82fd8d1 --- /dev/null +++ b/docs/modules/models.rst @@ -0,0 +1,40 @@ +Models +========================== + +.. note:: + `Conceptual Guide `_ + + +This section of the documentation deals with different types of models that are used in LangChain. +On this page we will go over the model types at a high level, +but we have individual pages for each model type. +The pages contain more detailed "how-to" guides for working with that model, +as well as a list of different model providers. + +**LLMs** + +Large Language Models (LLMs) are the first type of models we cover. +These models take a text string as input, and return a text string as output. + + +**Chat Models** + +Chat Models are the second type of models we cover. +These models are usually backed by a language model, but their APIs are more structured. +Specifically, these models take a list of Chat Messages as input, and return a Chat Message. + +**Text Embedding Models** + +The third type of models we cover are text embedding models. +These models take text as input and return a list of floats. + + +Go Deeper +--------- + +.. toctree:: + :maxdepth: 1 + + ./models/llms.rst + ./models/chat.rst + ./models/text_embedding.rst diff --git a/docs/modules/chat.rst b/docs/modules/models/chat.rst similarity index 65% rename from docs/modules/chat.rst rename to docs/modules/models/chat.rst index b8c69ee7..83516a7e 100644 --- a/docs/modules/chat.rst +++ b/docs/modules/models/chat.rst @@ -1,6 +1,10 @@ -Chat +Chat Models ========================== +.. note:: + `Conceptual Guide `_ + + Chat models are a variation on language models. While chat models use language models under the hood, the interface they expose is a bit different. Rather than expose a "text in, text out" API, they expose an interface where "chat messages" are the inputs and outputs. @@ -9,18 +13,18 @@ Chat model APIs are fairly new, so we are still figuring out the correct abstrac The following sections of documentation are provided: -- `Getting Started <./chat/getting_started.html>`_: An overview of the basics of chat models. +- `Getting Started <./chat/getting_started.html>`_: An overview of all the functionality the LangChain LLM class provides. -- `Key Concepts <./chat/key_concepts.html>`_: A conceptual guide going over the various concepts related to chat models. +- `How-To Guides <./chat/how_to_guides.html>`_: A collection of how-to guides. These highlight how to accomplish various objectives with our LLM class (streaming, async, etc). -- `How-To Guides <./chat/how_to_guides.html>`_: A collection of how-to guides. These highlight how to accomplish various objectives with our chat model class, as well as how to integrate with various chat model providers. +- `Integrations <./chat/integrations.html>`_: A collection of examples on how to integrate different LLM providers with LangChain (OpenAI, Hugging Face, etc). .. toctree:: :maxdepth: 1 :name: LLMs :hidden: - + ./chat/getting_started.ipynb - ./chat/key_concepts.md ./chat/how_to_guides.rst + ./chat/integrations.rst diff --git a/docs/modules/chat/examples/few_shot_examples.ipynb b/docs/modules/models/chat/examples/few_shot_examples.ipynb similarity index 99% rename from docs/modules/chat/examples/few_shot_examples.ipynb rename to docs/modules/models/chat/examples/few_shot_examples.ipynb index 651e59da..a4471e7f 100644 --- a/docs/modules/chat/examples/few_shot_examples.ipynb +++ b/docs/modules/models/chat/examples/few_shot_examples.ipynb @@ -5,7 +5,7 @@ "id": "bb0735c0", "metadata": {}, "source": [ - "# Few Shot Examples\n", + "# How to use few shot examples\n", "\n", "This notebook covers how to use few shot examples in chat models.\n", "\n", diff --git a/docs/modules/chat/examples/streaming.ipynb b/docs/modules/models/chat/examples/streaming.ipynb similarity index 98% rename from docs/modules/chat/examples/streaming.ipynb rename to docs/modules/models/chat/examples/streaming.ipynb index fd696c92..22b27e0c 100644 --- a/docs/modules/chat/examples/streaming.ipynb +++ b/docs/modules/models/chat/examples/streaming.ipynb @@ -5,7 +5,7 @@ "id": "fe4e96b5", "metadata": {}, "source": [ - "# Streaming\n", + "# How to stream responses\n", "\n", "This notebook goes over how to use streaming with a chat model." ] diff --git a/docs/modules/chat/getting_started.ipynb b/docs/modules/models/chat/getting_started.ipynb similarity index 100% rename from docs/modules/chat/getting_started.ipynb rename to docs/modules/models/chat/getting_started.ipynb diff --git a/docs/modules/chat/how_to_guides.rst b/docs/modules/models/chat/how_to_guides.rst similarity index 100% rename from docs/modules/chat/how_to_guides.rst rename to docs/modules/models/chat/how_to_guides.rst diff --git a/docs/modules/models/chat/integrations.rst b/docs/modules/models/chat/integrations.rst new file mode 100644 index 00000000..42b65111 --- /dev/null +++ b/docs/modules/models/chat/integrations.rst @@ -0,0 +1,10 @@ +Integrations +============= + +The examples here all highlight how to integrate with different chat models. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./integrations/* diff --git a/docs/modules/models/chat/integrations/azure_chat_openai.ipynb b/docs/modules/models/chat/integrations/azure_chat_openai.ipynb new file mode 100644 index 00000000..60b38ad4 --- /dev/null +++ b/docs/modules/models/chat/integrations/azure_chat_openai.ipynb @@ -0,0 +1,94 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "38f26d7a", + "metadata": {}, + "source": [ + "# Azure\n", + "\n", + "This notebook goes over how to connect to an Azure hosted OpenAI endpoint" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "96164b42", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chat_models import AzureChatOpenAI\n", + "from langchain.schema import HumanMessage" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "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-03-15-preview\",\n", + " deployment_name=DEPLOYMENT_NAME,\n", + " openai_api_key=API_KEY,\n", + " openai_api_type = \"azure\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "99509140", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content=\"\\n\\nJ'aime programmer.\", additional_kwargs={})" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model([HumanMessage(content=\"Translate this sentence from English to French. I love programming.\")])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b6e9376", + "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 +} diff --git a/docs/modules/models/chat/integrations/openai.ipynb b/docs/modules/models/chat/integrations/openai.ipynb new file mode 100644 index 00000000..c01fe50e --- /dev/null +++ b/docs/modules/models/chat/integrations/openai.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e49f1e0d", + "metadata": {}, + "source": [ + "# OpenAI\n", + "\n", + "This notebook covers how to get started with OpenAI chat models." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "522686de", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.prompts.chat import (\n", + " ChatPromptTemplate,\n", + " SystemMessagePromptTemplate,\n", + " AIMessagePromptTemplate,\n", + " HumanMessagePromptTemplate,\n", + ")\n", + "from langchain.schema import (\n", + " AIMessage,\n", + " HumanMessage,\n", + " SystemMessage\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "62e0dbc3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "chat = ChatOpenAI(temperature=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ce16ad78-8e6f-48cd-954e-98be75eb5836", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content=\"J'aime programmer.\", additional_kwargs={})" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "messages = [\n", + " SystemMessage(content=\"You are a helpful assistant that translates English to French.\"),\n", + " HumanMessage(content=\"Translate this sentence from English to French. I love programming.\")\n", + "]\n", + "chat(messages)" + ] + }, + { + "cell_type": "markdown", + "id": "778f912a-66ea-4a5d-b3de-6c7db4baba26", + "metadata": {}, + "source": [ + "You can make use of templating by using a `MessagePromptTemplate`. You can build a `ChatPromptTemplate` from one or more `MessagePromptTemplates`. You can use `ChatPromptTemplate`'s `format_prompt` -- this returns a `PromptValue`, which you can convert to a string or Message object, depending on whether you want to use the formatted value as input to an llm or chat model.\n", + "\n", + "For convience, there is a `from_template` method exposed on the template. If you were to use this template, this is what it would look like:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "180c5cc8", + "metadata": {}, + "outputs": [], + "source": [ + "template=\"You are a helpful assistant that translates {input_language} to {output_language}.\"\n", + "system_message_prompt = SystemMessagePromptTemplate.from_template(template)\n", + "human_template=\"{text}\"\n", + "human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "fbb043e6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content=\"J'adore la programmation.\", additional_kwargs={})" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])\n", + "\n", + "# get a chat completion from the formatted messages\n", + "chat(chat_prompt.format_prompt(input_language=\"English\", output_language=\"French\", text=\"I love programming.\").to_messages())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c095285d", + "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 +} diff --git a/docs/modules/chat/examples/promptlayer_chatopenai.ipynb b/docs/modules/models/chat/integrations/promptlayer_chatopenai.ipynb similarity index 100% rename from docs/modules/chat/examples/promptlayer_chatopenai.ipynb rename to docs/modules/models/chat/integrations/promptlayer_chatopenai.ipynb diff --git a/docs/modules/llms.rst b/docs/modules/models/llms.rst similarity index 57% rename from docs/modules/llms.rst rename to docs/modules/models/llms.rst index d514ba64..f800eab6 100644 --- a/docs/modules/llms.rst +++ b/docs/modules/models/llms.rst @@ -1,6 +1,10 @@ LLMs ========================== +.. note:: + `Conceptual Guide `_ + + Large Language Models (LLMs) are a core component of LangChain. LangChain is not a provider of LLMs, but rather provides a standard interface through which you can interact with a variety of LLMs. @@ -9,11 +13,11 @@ The following sections of documentation are provided: - `Getting Started <./llms/getting_started.html>`_: An overview of all the functionality the LangChain LLM class provides. -- `Key Concepts <./llms/key_concepts.html>`_: A conceptual guide going over the various concepts related to LLMs. +- `How-To Guides <./llms/how_to_guides.html>`_: A collection of how-to guides. These highlight how to accomplish various objectives with our LLM class (streaming, async, etc). -- `How-To Guides <./llms/how_to_guides.html>`_: A collection of how-to guides. These highlight how to accomplish various objectives with our LLM class, as well as how to integrate with various LLM providers. +- `Integrations <./llms/integrations.html>`_: A collection of examples on how to integrate different LLM providers with LangChain (OpenAI, Hugging Face, etc). -- `Reference <../reference/modules/llms.html>`_: API reference documentation for all LLM classes. +- `Reference <../../reference/modules/llms.html>`_: API reference documentation for all LLM classes. .. toctree:: @@ -22,6 +26,6 @@ The following sections of documentation are provided: :hidden: ./llms/getting_started.ipynb - ./llms/key_concepts.md ./llms/how_to_guides.rst - Reference<../reference/modules/llms.rst> + ./llms/integrations.rst + Reference<../../reference/modules/llms.rst> diff --git a/docs/modules/llms/async_llm.ipynb b/docs/modules/models/llms/examples/async_llm.ipynb similarity index 98% rename from docs/modules/llms/async_llm.ipynb rename to docs/modules/models/llms/examples/async_llm.ipynb index 021f0868..f3ccfc60 100644 --- a/docs/modules/llms/async_llm.ipynb +++ b/docs/modules/models/llms/examples/async_llm.ipynb @@ -5,7 +5,7 @@ "id": "f6574496-b360-4ffa-9523-7fd34a590164", "metadata": {}, "source": [ - "# Async API for LLM\n", + "# How to use the async API for LLMs\n", "\n", "LangChain provides async support for LLMs by leveraging the [asyncio](https://docs.python.org/3/library/asyncio.html) library.\n", "\n", diff --git a/docs/modules/llms/examples/custom_llm.ipynb b/docs/modules/models/llms/examples/custom_llm.ipynb similarity index 98% rename from docs/modules/llms/examples/custom_llm.ipynb rename to docs/modules/models/llms/examples/custom_llm.ipynb index 35027925..1375d639 100644 --- a/docs/modules/llms/examples/custom_llm.ipynb +++ b/docs/modules/models/llms/examples/custom_llm.ipynb @@ -5,7 +5,7 @@ "id": "9e9b7651", "metadata": {}, "source": [ - "# Custom LLM\n", + "# How to write a custom LLM wrapper\n", "\n", "This notebook goes over how to create a custom LLM wrapper, in case you want to use your own LLM or a different wrapper than one that is supported in LangChain.\n", "\n", @@ -148,7 +148,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/llms/examples/fake_llm.ipynb b/docs/modules/models/llms/examples/fake_llm.ipynb similarity index 87% rename from docs/modules/llms/examples/fake_llm.ipynb rename to docs/modules/models/llms/examples/fake_llm.ipynb index 43a5981e..508d0fd2 100644 --- a/docs/modules/llms/examples/fake_llm.ipynb +++ b/docs/modules/models/llms/examples/fake_llm.ipynb @@ -5,7 +5,7 @@ "id": "052dfe58", "metadata": {}, "source": [ - "# Fake LLM\n", + "# How (and why) to use the fake LLM\n", "We expose a fake LLM class that can be used for testing. This allows you to mock out calls to the LLM and simulate what would happen if the LLM responded in a certain way.\n", "\n", "In this notebook we go over how to use this.\n", @@ -80,14 +80,14 @@ "text": [ "\n", "\n", - "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n", - "\u001B[32;1m\u001B[1;3mAction: Python REPL\n", - "Action Input: print(2 + 2)\u001B[0m\n", - "Observation: \u001B[36;1m\u001B[1;3m4\n", - "\u001B[0m\n", - "Thought:\u001B[32;1m\u001B[1;3mFinal Answer: 4\u001B[0m\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mAction: Python REPL\n", + "Action Input: print(2 + 2)\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3m4\n", + "\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3mFinal Answer: 4\u001b[0m\n", "\n", - "\u001B[1m> Finished chain.\u001B[0m\n" + "\u001b[1m> Finished chain.\u001b[0m\n" ] }, { diff --git a/docs/modules/llms/examples/llm.json b/docs/modules/models/llms/examples/llm.json similarity index 100% rename from docs/modules/llms/examples/llm.json rename to docs/modules/models/llms/examples/llm.json diff --git a/docs/modules/llms/examples/llm.yaml b/docs/modules/models/llms/examples/llm.yaml similarity index 100% rename from docs/modules/llms/examples/llm.yaml rename to docs/modules/models/llms/examples/llm.yaml diff --git a/docs/modules/llms/examples/llm_caching.ipynb b/docs/modules/models/llms/examples/llm_caching.ipynb similarity index 98% rename from docs/modules/llms/examples/llm_caching.ipynb rename to docs/modules/models/llms/examples/llm_caching.ipynb index 4060689b..e9ae75eb 100644 --- a/docs/modules/llms/examples/llm_caching.ipynb +++ b/docs/modules/models/llms/examples/llm_caching.ipynb @@ -5,7 +5,7 @@ "id": "f36d938c", "metadata": {}, "source": [ - "# LLM Caching\n", + "# How to cache LLM calls\n", "This notebook covers how to cache results of individual LLM calls." ] }, @@ -278,16 +278,17 @@ }, { "cell_type": "markdown", + "id": "0959d640", + "metadata": {}, "source": [ "### Custom SQLAlchemy Schemas" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "code", "execution_count": null, + "id": "ac967b39", + "metadata": {}, "outputs": [], "source": [ "# You can define your own declarative SQLAlchemyCache child class to customize the schema used for caching. For example, to support high-speed fulltext prompt indexing with Postgres, use:\n", @@ -317,10 +318,7 @@ "\n", "engine = create_engine(\"postgresql://postgres:postgres@localhost:5432/postgres\")\n", "langchain.llm_cache = SQLAlchemyCache(engine, FulltextLLMCache)" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", @@ -443,7 +441,7 @@ "metadata": {}, "outputs": [], "source": [ - "with open('../../state_of_the_union.txt') as f:\n", + "with open('../../../state_of_the_union.txt') as f:\n", " state_of_the_union = f.read()\n", "texts = text_splitter.split_text(state_of_the_union)" ] @@ -563,7 +561,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/llms/examples/llm_serialization.ipynb b/docs/modules/models/llms/examples/llm_serialization.ipynb similarity index 98% rename from docs/modules/llms/examples/llm_serialization.ipynb rename to docs/modules/models/llms/examples/llm_serialization.ipynb index da64b197..6dfde6e4 100644 --- a/docs/modules/llms/examples/llm_serialization.ipynb +++ b/docs/modules/models/llms/examples/llm_serialization.ipynb @@ -5,7 +5,7 @@ "id": "73f9bf40", "metadata": {}, "source": [ - "# LLM Serialization\n", + "# How to serialize LLM classes\n", "\n", "This notebook walks through how to write and read an LLM Configuration to and from disk. This is useful if you want to save the configuration for a given LLM (e.g., the provider, the temperature, etc)." ] @@ -160,7 +160,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/llms/streaming_llm.ipynb b/docs/modules/models/llms/examples/streaming_llm.ipynb similarity index 99% rename from docs/modules/llms/streaming_llm.ipynb rename to docs/modules/models/llms/examples/streaming_llm.ipynb index 6d761e4a..02d53d0e 100644 --- a/docs/modules/llms/streaming_llm.ipynb +++ b/docs/modules/models/llms/examples/streaming_llm.ipynb @@ -5,7 +5,7 @@ "id": "6eaf7e66-f49c-42da-8d11-22ea13bef718", "metadata": {}, "source": [ - "# Streaming with LLMs\n", + "# How to stream LLM responses\n", "\n", "LangChain provides streaming support for LLMs. Currently, we only support streaming for the `OpenAI` and `ChatOpenAI` LLM implementation, but streaming support for other LLM implementations is on the roadmap. To utilize streaming, use a [`CallbackHandler`](https://github.com/hwchase17/langchain/blob/master/langchain/callbacks/base.py) that implements `on_llm_new_token`. In this example, we are using [`StreamingStdOutCallbackHandler`]()." ] @@ -213,7 +213,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/llms/examples/token_usage_tracking.ipynb b/docs/modules/models/llms/examples/token_usage_tracking.ipynb similarity index 98% rename from docs/modules/llms/examples/token_usage_tracking.ipynb rename to docs/modules/models/llms/examples/token_usage_tracking.ipynb index 199fcf7c..e8449e9e 100644 --- a/docs/modules/llms/examples/token_usage_tracking.ipynb +++ b/docs/modules/models/llms/examples/token_usage_tracking.ipynb @@ -5,7 +5,7 @@ "id": "e5715368", "metadata": {}, "source": [ - "# Token Usage Tracking\n", + "# How to track token usage\n", "\n", "This notebook goes over how to track your token usage for specific calls. It is currently only implemented for the OpenAI API.\n", "\n", @@ -171,7 +171,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/llms/getting_started.ipynb b/docs/modules/models/llms/getting_started.ipynb similarity index 100% rename from docs/modules/llms/getting_started.ipynb rename to docs/modules/models/llms/getting_started.ipynb diff --git a/docs/modules/models/llms/how_to_guides.rst b/docs/modules/models/llms/how_to_guides.rst new file mode 100644 index 00000000..634cde19 --- /dev/null +++ b/docs/modules/models/llms/how_to_guides.rst @@ -0,0 +1,10 @@ +Generic Functionality +===================== + +The examples here all address certain "how-to" guides for working with LLMs. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./examples/* diff --git a/docs/modules/models/llms/integrations.rst b/docs/modules/models/llms/integrations.rst new file mode 100644 index 00000000..2c3ce40c --- /dev/null +++ b/docs/modules/models/llms/integrations.rst @@ -0,0 +1,10 @@ +Integrations +============= + +The examples here are all "how-to" guides for how to integrate with various LLM providers. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./integrations/* diff --git a/docs/modules/llms/integrations/ai21.ipynb b/docs/modules/models/llms/integrations/ai21.ipynb similarity index 100% rename from docs/modules/llms/integrations/ai21.ipynb rename to docs/modules/models/llms/integrations/ai21.ipynb diff --git a/docs/modules/llms/integrations/aleph_alpha.ipynb b/docs/modules/models/llms/integrations/aleph_alpha.ipynb similarity index 100% rename from docs/modules/llms/integrations/aleph_alpha.ipynb rename to docs/modules/models/llms/integrations/aleph_alpha.ipynb diff --git a/docs/modules/llms/integrations/anthropic_example.ipynb b/docs/modules/models/llms/integrations/anthropic_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/anthropic_example.ipynb rename to docs/modules/models/llms/integrations/anthropic_example.ipynb diff --git a/docs/modules/llms/integrations/azure_openai_example.ipynb b/docs/modules/models/llms/integrations/azure_openai_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/azure_openai_example.ipynb rename to docs/modules/models/llms/integrations/azure_openai_example.ipynb diff --git a/docs/modules/llms/integrations/banana.ipynb b/docs/modules/models/llms/integrations/banana.ipynb similarity index 100% rename from docs/modules/llms/integrations/banana.ipynb rename to docs/modules/models/llms/integrations/banana.ipynb diff --git a/docs/modules/llms/integrations/cerebriumai_example.ipynb b/docs/modules/models/llms/integrations/cerebriumai_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/cerebriumai_example.ipynb rename to docs/modules/models/llms/integrations/cerebriumai_example.ipynb diff --git a/docs/modules/llms/integrations/cohere.ipynb b/docs/modules/models/llms/integrations/cohere.ipynb similarity index 100% rename from docs/modules/llms/integrations/cohere.ipynb rename to docs/modules/models/llms/integrations/cohere.ipynb diff --git a/docs/modules/llms/integrations/deepinfra_example.ipynb b/docs/modules/models/llms/integrations/deepinfra_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/deepinfra_example.ipynb rename to docs/modules/models/llms/integrations/deepinfra_example.ipynb diff --git a/docs/modules/llms/integrations/forefrontai_example.ipynb b/docs/modules/models/llms/integrations/forefrontai_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/forefrontai_example.ipynb rename to docs/modules/models/llms/integrations/forefrontai_example.ipynb diff --git a/docs/modules/llms/integrations/gooseai_example.ipynb b/docs/modules/models/llms/integrations/gooseai_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/gooseai_example.ipynb rename to docs/modules/models/llms/integrations/gooseai_example.ipynb diff --git a/docs/modules/llms/integrations/huggingface_hub.ipynb b/docs/modules/models/llms/integrations/huggingface_hub.ipynb similarity index 100% rename from docs/modules/llms/integrations/huggingface_hub.ipynb rename to docs/modules/models/llms/integrations/huggingface_hub.ipynb diff --git a/docs/modules/llms/integrations/manifest.ipynb b/docs/modules/models/llms/integrations/manifest.ipynb similarity index 98% rename from docs/modules/llms/integrations/manifest.ipynb rename to docs/modules/models/llms/integrations/manifest.ipynb index 40e6b8c0..8b21e43e 100644 --- a/docs/modules/llms/integrations/manifest.ipynb +++ b/docs/modules/models/llms/integrations/manifest.ipynb @@ -106,7 +106,7 @@ } ], "source": [ - "with open('../state_of_the_union.txt') as f:\n", + "with open('../../../state_of_the_union.txt') as f:\n", " state_of_the_union = f.read()\n", "mp_chain.run(state_of_the_union)" ] @@ -202,7 +202,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.7" + "version": "3.9.1" }, "vscode": { "interpreter": { diff --git a/docs/modules/llms/integrations/modal.ipynb b/docs/modules/models/llms/integrations/modal.ipynb similarity index 100% rename from docs/modules/llms/integrations/modal.ipynb rename to docs/modules/models/llms/integrations/modal.ipynb diff --git a/docs/modules/llms/integrations/openai.ipynb b/docs/modules/models/llms/integrations/openai.ipynb similarity index 100% rename from docs/modules/llms/integrations/openai.ipynb rename to docs/modules/models/llms/integrations/openai.ipynb diff --git a/docs/modules/llms/integrations/petals_example.ipynb b/docs/modules/models/llms/integrations/petals_example.ipynb similarity index 100% rename from docs/modules/llms/integrations/petals_example.ipynb rename to docs/modules/models/llms/integrations/petals_example.ipynb diff --git a/docs/modules/llms/integrations/promptlayer_openai.ipynb b/docs/modules/models/llms/integrations/promptlayer_openai.ipynb similarity index 100% rename from docs/modules/llms/integrations/promptlayer_openai.ipynb rename to docs/modules/models/llms/integrations/promptlayer_openai.ipynb diff --git a/docs/modules/llms/integrations/sagemaker.ipynb b/docs/modules/models/llms/integrations/sagemaker.ipynb similarity index 100% rename from docs/modules/llms/integrations/sagemaker.ipynb rename to docs/modules/models/llms/integrations/sagemaker.ipynb diff --git a/docs/modules/llms/integrations/self_hosted_examples.ipynb b/docs/modules/models/llms/integrations/self_hosted_examples.ipynb similarity index 100% rename from docs/modules/llms/integrations/self_hosted_examples.ipynb rename to docs/modules/models/llms/integrations/self_hosted_examples.ipynb diff --git a/docs/modules/llms/integrations/stochasticai.ipynb b/docs/modules/models/llms/integrations/stochasticai.ipynb similarity index 100% rename from docs/modules/llms/integrations/stochasticai.ipynb rename to docs/modules/models/llms/integrations/stochasticai.ipynb diff --git a/docs/modules/llms/integrations/writer.ipynb b/docs/modules/models/llms/integrations/writer.ipynb similarity index 100% rename from docs/modules/llms/integrations/writer.ipynb rename to docs/modules/models/llms/integrations/writer.ipynb diff --git a/docs/modules/models/text_embedding.rst b/docs/modules/models/text_embedding.rst new file mode 100644 index 00000000..ed96503a --- /dev/null +++ b/docs/modules/models/text_embedding.rst @@ -0,0 +1,22 @@ +Text Embedding Models +========================== + +.. note:: + `Conceptual Guide `_ + + +This documentation goes over how to use the Embedding class in LangChain. + +The Embedding class is a class designed for interfacing with embeddings. There are lots of Embedding providers (OpenAI, Cohere, Hugging Face, etc) - this class is designed to provide a standard interface for all of them. + +Embeddings create a vector representation of a piece of text. This is useful because it means we can think about text in the vector space, and do things like semantic search where we look for pieces of text that are most similar in the vector space. + +The base Embedding class in LangChain exposes two methods: `embed_documents` and `embed_query`. The largest difference is that these two methods have different interfaces: one works over multiple documents, while the other works over a single document. Besides this, another reason for having these as two separate methods is that some embedding providers have different embedding methods for documents (to be searched over) vs queries (the search query itself). + +The following integrations exist for text embeddings. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./text_embedding/examples/* diff --git a/docs/modules/models/text_embedding/examples/azureopenai.ipynb b/docs/modules/models/text_embedding/examples/azureopenai.ipynb new file mode 100644 index 00000000..55f56f18 --- /dev/null +++ b/docs/modules/models/text_embedding/examples/azureopenai.ipynb @@ -0,0 +1,103 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c3852491", + "metadata": {}, + "source": [ + "# AzureOpenAI\n", + "\n", + "Let's load the OpenAI Embedding class with environment variables set to indicate to use Azure endpoints." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b40f827", + "metadata": {}, + "outputs": [], + "source": [ + "# set the environment variables needed for openai package to know to reach out to azure\n", + "import os\n", + "\n", + "os.environ[\"OPENAI_API_TYPE\"] = \"azure\"\n", + "os.environ[\"OPENAI_API_BASE\"] = \"https:// bytes:\n", + " input_str = json.dumps({\"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[\"embeddings\"]\n", + "\n", + "content_handler = ContentHandler()\n", + "\n", + "\n", + "embeddings = SagemakerEndpointEmbeddings(\n", + " # endpoint_name=\"endpoint-name\", \n", + " # credentials_profile_name=\"credentials-profile-name\", \n", + " endpoint_name=\"huggingface-pytorch-inference-2023-03-21-16-14-03-834\", \n", + " region_name=\"us-east-1\", \n", + " content_handler=content_handler\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe9797b8", + "metadata": {}, + "outputs": [], + "source": [ + "query_result = embeddings.embed_query(\"foo\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "76f1b752", + "metadata": {}, + "outputs": [], + "source": [ + "doc_results = embeddings.embed_documents([\"foo\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fff99b21", + "metadata": {}, + "outputs": [], + "source": [ + "doc_results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaad49f8", + "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" + }, + "vscode": { + "interpreter": { + "hash": "7377c2ccc78bc62c2683122d48c8cd1fb85a53850a1b1fc29736ed39852c9885" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/models/text_embedding/examples/self-hosted.ipynb b/docs/modules/models/text_embedding/examples/self-hosted.ipynb new file mode 100644 index 00000000..00c49722 --- /dev/null +++ b/docs/modules/models/text_embedding/examples/self-hosted.ipynb @@ -0,0 +1,195 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "eec4efda", + "metadata": {}, + "source": [ + "# Self Hosted Embeddings\n", + "Let's load the SelfHostedEmbeddings, SelfHostedHuggingFaceEmbeddings, and SelfHostedHuggingFaceInstructEmbeddings classes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d338722a", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "from langchain.embeddings import (\n", + " SelfHostedEmbeddings,\n", + " SelfHostedHuggingFaceEmbeddings,\n", + " SelfHostedHuggingFaceInstructEmbeddings,\n", + ")\n", + "import runhouse as rh" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "146559e8", + "metadata": {}, + "outputs": [], + "source": [ + "# For an on-demand A100 with GCP, Azure, or Lambda\n", + "gpu = rh.cluster(name=\"rh-a10x\", instance_type=\"A100:1\", use_spot=False)\n", + "\n", + "# For an on-demand A10G with AWS (no single A100s on AWS)\n", + "# gpu = rh.cluster(name='rh-a10x', instance_type='g5.2xlarge', provider='aws')\n", + "\n", + "# For an existing cluster\n", + "# gpu = rh.cluster(ips=[''],\n", + "# ssh_creds={'ssh_user': '...', 'ssh_private_key':''},\n", + "# name='my-cluster')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1230f7df", + "metadata": {}, + "outputs": [], + "source": [ + "embeddings = SelfHostedHuggingFaceEmbeddings(hardware=gpu)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2684e928", + "metadata": {}, + "outputs": [], + "source": [ + "text = \"This is a test document.\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1dc5e606", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "query_result = embeddings.embed_query(text)" + ] + }, + { + "cell_type": "markdown", + "id": "cef9cc54", + "metadata": {}, + "source": [ + "And similarly for SelfHostedHuggingFaceInstructEmbeddings:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81a17ca3", + "metadata": {}, + "outputs": [], + "source": [ + "embeddings = SelfHostedHuggingFaceInstructEmbeddings(hardware=gpu)" + ] + }, + { + "cell_type": "markdown", + "id": "5a33d1c8", + "metadata": {}, + "source": [ + "Now let's load an embedding model with a custom load function:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c4af5679", + "metadata": {}, + "outputs": [], + "source": [ + "def get_pipeline():\n", + " from transformers import (\n", + " AutoModelForCausalLM,\n", + " AutoTokenizer,\n", + " pipeline,\n", + " ) # Must be inside the function in notebooks\n", + "\n", + " model_id = \"facebook/bart-base\"\n", + " tokenizer = AutoTokenizer.from_pretrained(model_id)\n", + " model = AutoModelForCausalLM.from_pretrained(model_id)\n", + " return pipeline(\"feature-extraction\", model=model, tokenizer=tokenizer)\n", + "\n", + "\n", + "def inference_fn(pipeline, prompt):\n", + " # Return last hidden state of the model\n", + " if isinstance(prompt, list):\n", + " return [emb[0][-1] for emb in pipeline(prompt)]\n", + " return pipeline(prompt)[0][-1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8654334b", + "metadata": {}, + "outputs": [], + "source": [ + "embeddings = SelfHostedEmbeddings(\n", + " model_load_fn=get_pipeline,\n", + " hardware=gpu,\n", + " model_reqs=[\"./\", \"torch\", \"transformers\"],\n", + " inference_fn=inference_fn,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc1bfd0f", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "query_result = embeddings.embed_query(text)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaad49f8", + "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" + }, + "vscode": { + "interpreter": { + "hash": "7377c2ccc78bc62c2683122d48c8cd1fb85a53850a1b1fc29736ed39852c9885" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/models/text_embedding/examples/tensorflowhub.ipynb b/docs/modules/models/text_embedding/examples/tensorflowhub.ipynb new file mode 100644 index 00000000..bcda70d6 --- /dev/null +++ b/docs/modules/models/text_embedding/examples/tensorflowhub.ipynb @@ -0,0 +1,118 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fff4734f", + "metadata": {}, + "source": [ + "# TensorflowHub\n", + "Let's load the TensorflowHub Embedding class." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f822104b", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.embeddings import TensorflowHubEmbeddings" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bac84e46", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-01-30 23:53:01.652176: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2023-01-30 23:53:34.362802: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n" + ] + } + ], + "source": [ + "embeddings = TensorflowHubEmbeddings()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4790d770", + "metadata": {}, + "outputs": [], + "source": [ + "text = \"This is a test document.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f556dcdb", + "metadata": {}, + "outputs": [], + "source": [ + "query_result = embeddings.embed_query(text)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "76f1b752", + "metadata": {}, + "outputs": [], + "source": [ + "doc_results = embeddings.embed_documents([\"foo\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fff99b21", + "metadata": {}, + "outputs": [], + "source": [ + "doc_results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaad49f8", + "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" + }, + "vscode": { + "interpreter": { + "hash": "7377c2ccc78bc62c2683122d48c8cd1fb85a53850a1b1fc29736ed39852c9885" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/prompts.rst b/docs/modules/prompts.rst index 1efa510a..f72d09c7 100644 --- a/docs/modules/prompts.rst +++ b/docs/modules/prompts.rst @@ -1,30 +1,49 @@ -Prompt Templates +Prompts ========================== -Language models take text as input - that text is commonly referred to as a prompt. -Typically this is not simply a hardcoded string but rather a combination of a template, some examples, and user input. +.. note:: + `Conceptual Guide `_ + + +The new way of programming models is through prompts. +A "prompt" refers to the input to the model. +This input is rarely hard coded, but rather is often constructed from multiple components. +A PromptTemplate is responsible for the construction of this input. LangChain provides several classes and functions to make constructing and working with prompts easy. -The following sections of documentation are provided: +This section of documentation is split into four sections: + +**LLM Prompt Templates** + +How to use PromptTemplates to prompt Language Models. -- `Getting Started <./prompts/getting_started.html>`_: An overview of all the functionality LangChain provides for working with and constructing prompts. +**Chat Prompt Templates** -- `Key Concepts <./prompts/key_concepts.html>`_: A conceptual guide going over the various concepts related to prompts. +How to use PromptTemplates to prompt Chat Models. -- `How-To Guides <./prompts/how_to_guides.html>`_: A collection of how-to guides. These highlight how to accomplish various objectives with our prompt class. +**Example Selectors** -- `Reference <../reference/prompts.html>`_: API reference documentation for all prompt classes. +Often times it is useful to include examples in prompts. +These examples can be hardcoded, but it is often more powerful if they are dynamically selected. +This section goes over example selection. +**Output Parsers** +Language models (and Chat Models) output text. +But many times you may want to get more structured information than just text back. +This is where output parsers come in. +Output Parsers are responsible for (1) instructing the model how output should be formatted, +(2) parsing output into the desired formatting (including retrying if necessary). + + +Go Deeper +--------- .. toctree:: :maxdepth: 1 - :caption: Prompt Templates - :name: Prompts - :hidden: - - ./prompts/getting_started.md - ./prompts/key_concepts.md - ./prompts/how_to_guides.rst - Reference<../reference/prompts.rst> \ No newline at end of file + + ./prompts/prompt_templates.rst + ./prompts/chat_prompt_template.ipynb + ./prompts/example_selectors.rst + ./prompts/output_parsers.rst diff --git a/docs/modules/prompts/chat_prompt_template.ipynb b/docs/modules/prompts/chat_prompt_template.ipynb new file mode 100644 index 00000000..df40ff0a --- /dev/null +++ b/docs/modules/prompts/chat_prompt_template.ipynb @@ -0,0 +1,128 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6488fdaf", + "metadata": {}, + "source": [ + "# Chat Prompt Template\n", + "\n", + "Chat Models takes a list of chat messages as input - this list commonly referred to as a prompt.\n", + "Typically this is not simply a hardcoded list of messages but rather a combination of a template, some examples, and user input.\n", + "LangChain provides several classes and functions to make constructing and working with prompts easy.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "7647a621", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import (\n", + " ChatPromptTemplate,\n", + " PromptTemplate,\n", + " SystemMessagePromptTemplate,\n", + " AIMessagePromptTemplate,\n", + " HumanMessagePromptTemplate,\n", + ")\n", + "from langchain.schema import (\n", + " AIMessage,\n", + " HumanMessage,\n", + " SystemMessage\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "acb4a2f6", + "metadata": {}, + "source": [ + "You can make use of templating by using a `MessagePromptTemplate`. You can build a `ChatPromptTemplate` from one or more `MessagePromptTemplates`. You can use `ChatPromptTemplate`'s `format_prompt` -- this returns a `PromptValue`, which you can convert to a string or Message object, depending on whether you want to use the formatted value as input to an llm or chat model.\n", + "\n", + "For convience, there is a `from_template` method exposed on the template. If you were to use this template, this is what it would look like:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3124f5e9", + "metadata": {}, + "outputs": [], + "source": [ + "template=\"You are a helpful assistant that translates {input_language} to {output_language}.\"\n", + "system_message_prompt = SystemMessagePromptTemplate.from_template(template)\n", + "human_template=\"{text}\"\n", + "human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9c7e2e6f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[SystemMessage(content='You are a helpful assistant that translates English to French.', additional_kwargs={}),\n", + " HumanMessage(content='I love programming.', additional_kwargs={})]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])\n", + "\n", + "# get a chat completion from the formatted messages\n", + "chat_prompt.format_prompt(input_language=\"English\", output_language=\"French\", text=\"I love programming.\").to_messages()" + ] + }, + { + "cell_type": "markdown", + "id": "0dbdf94f", + "metadata": {}, + "source": [ + "If you wanted to construct the MessagePromptTemplate more directly, you could create a PromptTemplate outside and then pass it in, eg:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "5a8d249e", + "metadata": {}, + "outputs": [], + "source": [ + "prompt=PromptTemplate(\n", + " template=\"You are a helpful assistant that translates {input_language} to {output_language}.\",\n", + " input_variables=[\"input_language\", \"output_language\"],\n", + ")\n", + "system_message_prompt = SystemMessagePromptTemplate(prompt=prompt)" + ] + } + ], + "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 +} diff --git a/docs/modules/prompts/example_selectors.rst b/docs/modules/prompts/example_selectors.rst new file mode 100644 index 00000000..015d487d --- /dev/null +++ b/docs/modules/prompts/example_selectors.rst @@ -0,0 +1,29 @@ +Example Selectors +========================== + +.. note:: + `Conceptual Guide `_ + + +If you have a large number of examples, you may need to select which ones to include in the prompt. The ExampleSelector is the class responsible for doing so. + +The base interface is defined as below:: + + class BaseExampleSelector(ABC): + """Interface for selecting examples to include in prompts.""" + + @abstractmethod + def select_examples(self, input_variables: Dict[str, str]) -> List[dict]: + """Select which examples to use based on the inputs.""" + + +The only method it needs to expose is a ``select_examples`` method. This takes in the input variables and then returns a list of examples. It is up to each specific implementation as to how those examples are selected. Let's take a look at some below. + +See below for a list of example selectors. + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./example_selectors/examples/* \ No newline at end of file diff --git a/docs/modules/prompts/examples/custom_example_selector.md b/docs/modules/prompts/example_selectors/examples/custom_example_selector.md similarity index 94% rename from docs/modules/prompts/examples/custom_example_selector.md rename to docs/modules/prompts/example_selectors/examples/custom_example_selector.md index 41b8e788..9b665718 100644 --- a/docs/modules/prompts/examples/custom_example_selector.md +++ b/docs/modules/prompts/example_selectors/examples/custom_example_selector.md @@ -1,4 +1,4 @@ -# Create a custom example selector +# How to create a custom example selector In this tutorial, we'll create a custom example selector that selects every alternate example from a given list of examples. @@ -10,7 +10,7 @@ An `ExampleSelector` must implement two methods: Let's implement a custom `ExampleSelector` that just selects two examples at random. :::{note} -Take a look at the current set of example selector implementations supported in LangChain [here](../getting_started.md). +Take a look at the current set of example selector implementations supported in LangChain [here](../../prompt_templates/getting_started.md). ::: diff --git a/docs/modules/prompts/example_selectors/examples/length_based.ipynb b/docs/modules/prompts/example_selectors/examples/length_based.ipynb new file mode 100644 index 00000000..6440311c --- /dev/null +++ b/docs/modules/prompts/example_selectors/examples/length_based.ipynb @@ -0,0 +1,211 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "861a4d1f", + "metadata": {}, + "source": [ + "# LengthBased ExampleSelector\n", + "\n", + "This ExampleSelector selects which examples to use based on length. This is useful when you are worried about constructing a prompt that will go over the length of the context window. For longer inputs, it will select fewer examples to include, while for shorter inputs it will select more.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "7c469c95", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import PromptTemplate\n", + "from langchain.prompts import FewShotPromptTemplate\n", + "from langchain.prompts.example_selector import LengthBasedExampleSelector" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0ec6d950", + "metadata": {}, + "outputs": [], + "source": [ + "# These are a lot of examples of a pretend task of creating antonyms.\n", + "examples = [\n", + " {\"input\": \"happy\", \"output\": \"sad\"},\n", + " {\"input\": \"tall\", \"output\": \"short\"},\n", + " {\"input\": \"energetic\", \"output\": \"lethargic\"},\n", + " {\"input\": \"sunny\", \"output\": \"gloomy\"},\n", + " {\"input\": \"windy\", \"output\": \"calm\"},\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "207e55f7", + "metadata": {}, + "outputs": [], + "source": [ + "example_prompt = PromptTemplate(\n", + " input_variables=[\"input\", \"output\"],\n", + " template=\"Input: {input}\\nOutput: {output}\",\n", + ")\n", + "example_selector = LengthBasedExampleSelector(\n", + " # These are the examples it has available to choose from.\n", + " examples=examples, \n", + " # This is the PromptTemplate being used to format the examples.\n", + " example_prompt=example_prompt, \n", + " # This is the maximum length that the formatted examples should be.\n", + " # Length is measured by the get_text_length function below.\n", + " max_length=25,\n", + " # This is the function used to get the length of a string, which is used\n", + " # to determine which examples to include. It is commented out because\n", + " # it is provided as a default value if none is specified.\n", + " # get_text_length: Callable[[str], int] = lambda x: len(re.split(\"\\n| \", x))\n", + ")\n", + "dynamic_prompt = FewShotPromptTemplate(\n", + " # We provide an ExampleSelector instead of examples.\n", + " example_selector=example_selector,\n", + " example_prompt=example_prompt,\n", + " prefix=\"Give the antonym of every input\",\n", + " suffix=\"Input: {adjective}\\nOutput:\", \n", + " input_variables=[\"adjective\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d00b4385", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: tall\n", + "Output: short\n", + "\n", + "Input: energetic\n", + "Output: lethargic\n", + "\n", + "Input: sunny\n", + "Output: gloomy\n", + "\n", + "Input: windy\n", + "Output: calm\n", + "\n", + "Input: big\n", + "Output:\n" + ] + } + ], + "source": [ + "# An example with small input, so it selects all examples.\n", + "print(dynamic_prompt.format(adjective=\"big\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "878bcde9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else\n", + "Output:\n" + ] + } + ], + "source": [ + "# An example with long input, so it selects only one example.\n", + "long_string = \"big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else\"\n", + "print(dynamic_prompt.format(adjective=long_string))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e4bebcd9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: tall\n", + "Output: short\n", + "\n", + "Input: energetic\n", + "Output: lethargic\n", + "\n", + "Input: sunny\n", + "Output: gloomy\n", + "\n", + "Input: windy\n", + "Output: calm\n", + "\n", + "Input: big\n", + "Output: small\n", + "\n", + "Input: enthusiastic\n", + "Output:\n" + ] + } + ], + "source": [ + "# You can add an example to an example selector as well.\n", + "new_example = {\"input\": \"big\", \"output\": \"small\"}\n", + "dynamic_prompt.example_selector.add_example(new_example)\n", + "print(dynamic_prompt.format(adjective=\"enthusiastic\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39f30097", + "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 +} diff --git a/docs/modules/prompts/example_selectors/examples/mmr.ipynb b/docs/modules/prompts/example_selectors/examples/mmr.ipynb new file mode 100644 index 00000000..3d461e41 --- /dev/null +++ b/docs/modules/prompts/example_selectors/examples/mmr.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bc35afd0", + "metadata": {}, + "source": [ + "# Maximal Marginal Relevance ExampleSelector\n", + "\n", + "The MaxMarginalRelevanceExampleSelector selects examples based on a combination of which examples are most similar to the inputs, while also optimizing for diversity. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs, and then iteratively adding them while penalizing them for closeness to already selected examples.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ac95c968", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector\n", + "from langchain.vectorstores import FAISS\n", + "from langchain.embeddings import OpenAIEmbeddings\n", + "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n", + "\n", + "example_prompt = PromptTemplate(\n", + " input_variables=[\"input\", \"output\"],\n", + " template=\"Input: {input}\\nOutput: {output}\",\n", + ")\n", + "\n", + "# These are a lot of examples of a pretend task of creating antonyms.\n", + "examples = [\n", + " {\"input\": \"happy\", \"output\": \"sad\"},\n", + " {\"input\": \"tall\", \"output\": \"short\"},\n", + " {\"input\": \"energetic\", \"output\": \"lethargic\"},\n", + " {\"input\": \"sunny\", \"output\": \"gloomy\"},\n", + " {\"input\": \"windy\", \"output\": \"calm\"},\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "db579bea", + "metadata": {}, + "outputs": [], + "source": [ + "example_selector = MaxMarginalRelevanceExampleSelector.from_examples(\n", + " # This is the list of examples available to select from.\n", + " examples, \n", + " # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n", + " OpenAIEmbeddings(), \n", + " # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n", + " FAISS, \n", + " # This is the number of examples to produce.\n", + " k=2\n", + ")\n", + "mmr_prompt = FewShotPromptTemplate(\n", + " # We provide an ExampleSelector instead of examples.\n", + " example_selector=example_selector,\n", + " example_prompt=example_prompt,\n", + " prefix=\"Give the antonym of every input\",\n", + " suffix=\"Input: {adjective}\\nOutput:\", \n", + " input_variables=[\"adjective\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cd76e344", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: windy\n", + "Output: calm\n", + "\n", + "Input: worried\n", + "Output:\n" + ] + } + ], + "source": [ + "# Input is a feeling, so should select the happy/sad example as the first one\n", + "print(mmr_prompt.format(adjective=\"worried\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "cf82956b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: windy\n", + "Output: calm\n", + "\n", + "Input: worried\n", + "Output:\n" + ] + } + ], + "source": [ + "# Let's compare this to what we would just get if we went solely off of similarity\n", + "similar_prompt = FewShotPromptTemplate(\n", + " # We provide an ExampleSelector instead of examples.\n", + " example_selector=example_selector,\n", + " example_prompt=example_prompt,\n", + " prefix=\"Give the antonym of every input\",\n", + " suffix=\"Input: {adjective}\\nOutput:\", \n", + " input_variables=[\"adjective\"],\n", + ")\n", + "similar_prompt.example_selector.k = 2\n", + "print(similar_prompt.format(adjective=\"worried\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39f30097", + "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 +} diff --git a/docs/modules/prompts/example_selectors/examples/ngram_overlap.ipynb b/docs/modules/prompts/example_selectors/examples/ngram_overlap.ipynb new file mode 100644 index 00000000..96ee8ab4 --- /dev/null +++ b/docs/modules/prompts/example_selectors/examples/ngram_overlap.ipynb @@ -0,0 +1,280 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4aaeed2f", + "metadata": {}, + "source": [ + "# NGram Overlap ExampleSelector\n", + "\n", + "The NGramOverlapExampleSelector selects and orders examples based on which examples are most similar to the input, according to an ngram overlap score. The ngram overlap score is a float between 0.0 and 1.0, inclusive. \n", + "\n", + "The selector allows for a threshold score to be set. Examples with an ngram overlap score less than or equal to the threshold are excluded. The threshold is set to -1.0, by default, so will not exclude any examples, only reorder them. Setting the threshold to 0.0 will exclude examples that have no ngram overlaps with the input.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9cbc0acc", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import PromptTemplate\n", + "from langchain.prompts.example_selector.ngram_overlap import NGramOverlapExampleSelector\n", + "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n", + "\n", + "example_prompt = PromptTemplate(\n", + " input_variables=[\"input\", \"output\"],\n", + " template=\"Input: {input}\\nOutput: {output}\",\n", + ")\n", + "\n", + "# These are a lot of examples of a pretend task of creating antonyms.\n", + "examples = [\n", + " {\"input\": \"happy\", \"output\": \"sad\"},\n", + " {\"input\": \"tall\", \"output\": \"short\"},\n", + " {\"input\": \"energetic\", \"output\": \"lethargic\"},\n", + " {\"input\": \"sunny\", \"output\": \"gloomy\"},\n", + " {\"input\": \"windy\", \"output\": \"calm\"},\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4f318f4b", + "metadata": {}, + "outputs": [], + "source": [ + "# These are examples of a fictional translation task.\n", + "examples = [\n", + " {\"input\": \"See Spot run.\", \"output\": \"Ver correr a Spot.\"},\n", + " {\"input\": \"My dog barks.\", \"output\": \"Mi perro ladra.\"},\n", + " {\"input\": \"Spot can run.\", \"output\": \"Spot puede correr.\"},\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "bf75e0fe", + "metadata": {}, + "outputs": [], + "source": [ + "example_prompt = PromptTemplate(\n", + " input_variables=[\"input\", \"output\"],\n", + " template=\"Input: {input}\\nOutput: {output}\",\n", + ")\n", + "example_selector = NGramOverlapExampleSelector(\n", + " # These are the examples it has available to choose from.\n", + " examples=examples, \n", + " # This is the PromptTemplate being used to format the examples.\n", + " example_prompt=example_prompt, \n", + " # This is the threshold, at which selector stops.\n", + " # It is set to -1.0 by default.\n", + " threshold=-1.0,\n", + " # For negative threshold:\n", + " # Selector sorts examples by ngram overlap score, and excludes none.\n", + " # For threshold greater than 1.0:\n", + " # Selector excludes all examples, and returns an empty list.\n", + " # For threshold equal to 0.0:\n", + " # Selector sorts examples by ngram overlap score,\n", + " # and excludes those with no ngram overlap with input.\n", + ")\n", + "dynamic_prompt = FewShotPromptTemplate(\n", + " # We provide an ExampleSelector instead of examples.\n", + " example_selector=example_selector,\n", + " example_prompt=example_prompt,\n", + " prefix=\"Give the Spanish translation of every input\",\n", + " suffix=\"Input: {sentence}\\nOutput:\", \n", + " input_variables=[\"sentence\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "83fb218a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the Spanish translation of every input\n", + "\n", + "Input: Spot can run.\n", + "Output: Spot puede correr.\n", + "\n", + "Input: See Spot run.\n", + "Output: Ver correr a Spot.\n", + "\n", + "Input: My dog barks.\n", + "Output: Mi perro ladra.\n", + "\n", + "Input: Spot can run fast.\n", + "Output:\n" + ] + } + ], + "source": [ + "# An example input with large ngram overlap with \"Spot can run.\"\n", + "# and no overlap with \"My dog barks.\"\n", + "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "485f5307", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the Spanish translation of every input\n", + "\n", + "Input: Spot can run.\n", + "Output: Spot puede correr.\n", + "\n", + "Input: See Spot run.\n", + "Output: Ver correr a Spot.\n", + "\n", + "Input: Spot plays fetch.\n", + "Output: Spot juega a buscar.\n", + "\n", + "Input: My dog barks.\n", + "Output: Mi perro ladra.\n", + "\n", + "Input: Spot can run fast.\n", + "Output:\n" + ] + } + ], + "source": [ + "# You can add examples to NGramOverlapExampleSelector as well.\n", + "new_example = {\"input\": \"Spot plays fetch.\", \"output\": \"Spot juega a buscar.\"}\n", + "\n", + "example_selector.add_example(new_example)\n", + "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "606ce697", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the Spanish translation of every input\n", + "\n", + "Input: Spot can run.\n", + "Output: Spot puede correr.\n", + "\n", + "Input: See Spot run.\n", + "Output: Ver correr a Spot.\n", + "\n", + "Input: Spot plays fetch.\n", + "Output: Spot juega a buscar.\n", + "\n", + "Input: Spot can run fast.\n", + "Output:\n" + ] + } + ], + "source": [ + "# You can set a threshold at which examples are excluded.\n", + "# For example, setting threshold equal to 0.0\n", + "# excludes examples with no ngram overlaps with input.\n", + "# Since \"My dog barks.\" has no ngram overlaps with \"Spot can run fast.\"\n", + "# it is excluded.\n", + "example_selector.threshold=0.0\n", + "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "7f8d72f7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the Spanish translation of every input\n", + "\n", + "Input: Spot can run.\n", + "Output: Spot puede correr.\n", + "\n", + "Input: Spot plays fetch.\n", + "Output: Spot juega a buscar.\n", + "\n", + "Input: Spot can play fetch.\n", + "Output:\n" + ] + } + ], + "source": [ + "# Setting small nonzero threshold\n", + "example_selector.threshold=0.09\n", + "print(dynamic_prompt.format(sentence=\"Spot can play fetch.\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "09633aa8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the Spanish translation of every input\n", + "\n", + "Input: Spot can play fetch.\n", + "Output:\n" + ] + } + ], + "source": [ + "# Setting threshold greater than 1.0\n", + "example_selector.threshold=1.0+1e-9\n", + "print(dynamic_prompt.format(sentence=\"Spot can play fetch.\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39f30097", + "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 +} diff --git a/docs/modules/prompts/example_selectors/examples/similarity.ipynb b/docs/modules/prompts/example_selectors/examples/similarity.ipynb new file mode 100644 index 00000000..683c5089 --- /dev/null +++ b/docs/modules/prompts/example_selectors/examples/similarity.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2d007b0a", + "metadata": {}, + "source": [ + "# Similarity ExampleSelector\n", + "\n", + "The SemanticSimilarityExampleSelector selects examples based on which examples are most similar to the inputs. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "241bfe80", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n", + "from langchain.vectorstores import Chroma\n", + "from langchain.embeddings import OpenAIEmbeddings\n", + "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n", + "\n", + "example_prompt = PromptTemplate(\n", + " input_variables=[\"input\", \"output\"],\n", + " template=\"Input: {input}\\nOutput: {output}\",\n", + ")\n", + "\n", + "# These are a lot of examples of a pretend task of creating antonyms.\n", + "examples = [\n", + " {\"input\": \"happy\", \"output\": \"sad\"},\n", + " {\"input\": \"tall\", \"output\": \"short\"},\n", + " {\"input\": \"energetic\", \"output\": \"lethargic\"},\n", + " {\"input\": \"sunny\", \"output\": \"gloomy\"},\n", + " {\"input\": \"windy\", \"output\": \"calm\"},\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "50d0a701", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Chroma using direct local API.\n", + "Using DuckDB in-memory for database. Data will be transient.\n" + ] + } + ], + "source": [ + "example_selector = SemanticSimilarityExampleSelector.from_examples(\n", + " # This is the list of examples available to select from.\n", + " examples, \n", + " # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n", + " OpenAIEmbeddings(), \n", + " # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n", + " Chroma, \n", + " # This is the number of examples to produce.\n", + " k=1\n", + ")\n", + "similar_prompt = FewShotPromptTemplate(\n", + " # We provide an ExampleSelector instead of examples.\n", + " example_selector=example_selector,\n", + " example_prompt=example_prompt,\n", + " prefix=\"Give the antonym of every input\",\n", + " suffix=\"Input: {adjective}\\nOutput:\", \n", + " input_variables=[\"adjective\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4c8fdf45", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: worried\n", + "Output:\n" + ] + } + ], + "source": [ + "# Input is a feeling, so should select the happy/sad example\n", + "print(similar_prompt.format(adjective=\"worried\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "829af21a", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: fat\n", + "Output:\n" + ] + } + ], + "source": [ + "# Input is a measurement, so should select the tall/short example\n", + "print(similar_prompt.format(adjective=\"fat\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "3c16fe23", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Give the antonym of every input\n", + "\n", + "Input: happy\n", + "Output: sad\n", + "\n", + "Input: joyful\n", + "Output:\n" + ] + } + ], + "source": [ + "# You can add new examples to the SemanticSimilarityExampleSelector as well\n", + "similar_prompt.example_selector.add_example({\"input\": \"enthusiastic\", \"output\": \"apathetic\"})\n", + "print(similar_prompt.format(adjective=\"joyful\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39f30097", + "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 +} diff --git a/docs/modules/prompts/examples/example_selectors.ipynb b/docs/modules/prompts/examples/example_selectors.ipynb deleted file mode 100644 index 76fdef15..00000000 --- a/docs/modules/prompts/examples/example_selectors.ipynb +++ /dev/null @@ -1,711 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "bf038596", - "metadata": {}, - "source": [ - "# Example Selectors\n", - "If you have a large number of examples, you may need to select which ones to include in the prompt. The ExampleSelector is the class responsible for doing so. The base interface is defined as below.\n", - "\n", - "```python\n", - "class BaseExampleSelector(ABC):\n", - " \"\"\"Interface for selecting examples to include in prompts.\"\"\"\n", - "\n", - " @abstractmethod\n", - " def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:\n", - " \"\"\"Select which examples to use based on the inputs.\"\"\"\n", - "\n", - "```\n", - "\n", - "The only method it needs to expose is a `select_examples` method. This takes in the input variables and then returns a list of examples. It is up to each specific implementation as to how those examples are selected. Let's take a look at some below." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "8244ff60", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import FewShotPromptTemplate" - ] - }, - { - "cell_type": "markdown", - "id": "861a4d1f", - "metadata": {}, - "source": [ - "## LengthBased ExampleSelector\n", - "\n", - "This ExampleSelector selects which examples to use based on length. This is useful when you are worried about constructing a prompt that will go over the length of the context window. For longer inputs, it will select fewer examples to include, while for shorter inputs it will select more.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7c469c95", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import PromptTemplate\n", - "from langchain.prompts.example_selector import LengthBasedExampleSelector" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "0ec6d950", - "metadata": {}, - "outputs": [], - "source": [ - "# These are a lot of examples of a pretend task of creating antonyms.\n", - "examples = [\n", - " {\"input\": \"happy\", \"output\": \"sad\"},\n", - " {\"input\": \"tall\", \"output\": \"short\"},\n", - " {\"input\": \"energetic\", \"output\": \"lethargic\"},\n", - " {\"input\": \"sunny\", \"output\": \"gloomy\"},\n", - " {\"input\": \"windy\", \"output\": \"calm\"},\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "207e55f7", - "metadata": {}, - "outputs": [], - "source": [ - "example_prompt = PromptTemplate(\n", - " input_variables=[\"input\", \"output\"],\n", - " template=\"Input: {input}\\nOutput: {output}\",\n", - ")\n", - "example_selector = LengthBasedExampleSelector(\n", - " # These are the examples it has available to choose from.\n", - " examples=examples, \n", - " # This is the PromptTemplate being used to format the examples.\n", - " example_prompt=example_prompt, \n", - " # This is the maximum length that the formatted examples should be.\n", - " # Length is measured by the get_text_length function below.\n", - " max_length=25,\n", - " # This is the function used to get the length of a string, which is used\n", - " # to determine which examples to include. It is commented out because\n", - " # it is provided as a default value if none is specified.\n", - " # get_text_length: Callable[[str], int] = lambda x: len(re.split(\"\\n| \", x))\n", - ")\n", - "dynamic_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the antonym of every input\",\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " input_variables=[\"adjective\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d00b4385", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: tall\n", - "Output: short\n", - "\n", - "Input: energetic\n", - "Output: lethargic\n", - "\n", - "Input: sunny\n", - "Output: gloomy\n", - "\n", - "Input: windy\n", - "Output: calm\n", - "\n", - "Input: big\n", - "Output:\n" - ] - } - ], - "source": [ - "# An example with small input, so it selects all examples.\n", - "print(dynamic_prompt.format(adjective=\"big\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "878bcde9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else\n", - "Output:\n" - ] - } - ], - "source": [ - "# An example with long input, so it selects only one example.\n", - "long_string = \"big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else\"\n", - "print(dynamic_prompt.format(adjective=long_string))" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "e4bebcd9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: tall\n", - "Output: short\n", - "\n", - "Input: energetic\n", - "Output: lethargic\n", - "\n", - "Input: sunny\n", - "Output: gloomy\n", - "\n", - "Input: windy\n", - "Output: calm\n", - "\n", - "Input: big\n", - "Output: small\n", - "\n", - "Input: enthusiastic\n", - "Output:\n" - ] - } - ], - "source": [ - "# You can add an example to an example selector as well.\n", - "new_example = {\"input\": \"big\", \"output\": \"small\"}\n", - "dynamic_prompt.example_selector.add_example(new_example)\n", - "print(dynamic_prompt.format(adjective=\"enthusiastic\"))" - ] - }, - { - "cell_type": "markdown", - "id": "2d007b0a", - "metadata": {}, - "source": [ - "## Similarity ExampleSelector\n", - "\n", - "The SemanticSimilarityExampleSelector selects examples based on which examples are most similar to the inputs. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "241bfe80", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n", - "from langchain.vectorstores import Chroma\n", - "from langchain.embeddings import OpenAIEmbeddings" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "50d0a701", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running Chroma using direct local API.\n", - "Using DuckDB in-memory for database. Data will be transient.\n" - ] - } - ], - "source": [ - "example_selector = SemanticSimilarityExampleSelector.from_examples(\n", - " # This is the list of examples available to select from.\n", - " examples, \n", - " # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n", - " OpenAIEmbeddings(), \n", - " # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n", - " Chroma, \n", - " # This is the number of examples to produce.\n", - " k=1\n", - ")\n", - "similar_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the antonym of every input\",\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " input_variables=[\"adjective\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "4c8fdf45", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: worried\n", - "Output:\n" - ] - } - ], - "source": [ - "# Input is a feeling, so should select the happy/sad example\n", - "print(similar_prompt.format(adjective=\"worried\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "829af21a", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: fat\n", - "Output:\n" - ] - } - ], - "source": [ - "# Input is a measurement, so should select the tall/short example\n", - "print(similar_prompt.format(adjective=\"fat\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "3c16fe23", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: joyful\n", - "Output:\n" - ] - } - ], - "source": [ - "# You can add new examples to the SemanticSimilarityExampleSelector as well\n", - "similar_prompt.example_selector.add_example({\"input\": \"enthusiastic\", \"output\": \"apathetic\"})\n", - "print(similar_prompt.format(adjective=\"joyful\"))" - ] - }, - { - "cell_type": "markdown", - "id": "bc35afd0", - "metadata": {}, - "source": [ - "## Maximal Marginal Relevance ExampleSelector\n", - "\n", - "The MaxMarginalRelevanceExampleSelector selects examples based on a combination of which examples are most similar to the inputs, while also optimizing for diversity. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs, and then iteratively adding them while penalizing them for closeness to already selected examples.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "ac95c968", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector\n", - "from langchain.vectorstores import FAISS" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "db579bea", - "metadata": {}, - "outputs": [], - "source": [ - "example_selector = MaxMarginalRelevanceExampleSelector.from_examples(\n", - " # This is the list of examples available to select from.\n", - " examples, \n", - " # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n", - " OpenAIEmbeddings(), \n", - " # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n", - " FAISS, \n", - " # This is the number of examples to produce.\n", - " k=2\n", - ")\n", - "mmr_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the antonym of every input\",\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " input_variables=[\"adjective\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "cd76e344", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: windy\n", - "Output: calm\n", - "\n", - "Input: worried\n", - "Output:\n" - ] - } - ], - "source": [ - "# Input is a feeling, so should select the happy/sad example as the first one\n", - "print(mmr_prompt.format(adjective=\"worried\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "cf82956b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: enthusiastic\n", - "Output: apathetic\n", - "\n", - "Input: worried\n", - "Output:\n" - ] - } - ], - "source": [ - "# Let's compare this to what we would just get if we went solely off of similarity\n", - "similar_prompt.example_selector.k = 2\n", - "print(similar_prompt.format(adjective=\"worried\"))" - ] - }, - { - "cell_type": "markdown", - "id": "4aaeed2f", - "metadata": {}, - "source": [ - "## NGram Overlap ExampleSelector\n", - "\n", - "The NGramOverlapExampleSelector selects and orders examples based on which examples are most similar to the input, according to an ngram overlap score. The ngram overlap score is a float between 0.0 and 1.0, inclusive. \n", - "\n", - "The selector allows for a threshold score to be set. Examples with an ngram overlap score less than or equal to the threshold are excluded. The threshold is set to -1.0, by default, so will not exclude any examples, only reorder them. Setting the threshold to 0.0 will exclude examples that have no ngram overlaps with the input.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "9cbc0acc", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import PromptTemplate\n", - "from langchain.prompts.example_selector.ngram_overlap import NGramOverlapExampleSelector" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "4f318f4b", - "metadata": {}, - "outputs": [], - "source": [ - "# These are examples of a fictional translation task.\n", - "examples = [\n", - " {\"input\": \"See Spot run.\", \"output\": \"Ver correr a Spot.\"},\n", - " {\"input\": \"My dog barks.\", \"output\": \"Mi perro ladra.\"},\n", - " {\"input\": \"Spot can run.\", \"output\": \"Spot puede correr.\"},\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "bf75e0fe", - "metadata": {}, - "outputs": [], - "source": [ - "example_prompt = PromptTemplate(\n", - " input_variables=[\"input\", \"output\"],\n", - " template=\"Input: {input}\\nOutput: {output}\",\n", - ")\n", - "example_selector = NGramOverlapExampleSelector(\n", - " # These are the examples it has available to choose from.\n", - " examples=examples, \n", - " # This is the PromptTemplate being used to format the examples.\n", - " example_prompt=example_prompt, \n", - " # This is the threshold, at which selector stops.\n", - " # It is set to -1.0 by default.\n", - " threshold=-1.0,\n", - " # For negative threshold:\n", - " # Selector sorts examples by ngram overlap score, and excludes none.\n", - " # For threshold greater than 1.0:\n", - " # Selector excludes all examples, and returns an empty list.\n", - " # For threshold equal to 0.0:\n", - " # Selector sorts examples by ngram overlap score,\n", - " # and excludes those with no ngram overlap with input.\n", - ")\n", - "dynamic_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the Spanish translation of every input\",\n", - " suffix=\"Input: {sentence}\\nOutput:\", \n", - " input_variables=[\"sentence\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "83fb218a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the Spanish translation of every input\n", - "\n", - "Input: Spot can run.\n", - "Output: Spot puede correr.\n", - "\n", - "Input: See Spot run.\n", - "Output: Ver correr a Spot.\n", - "\n", - "Input: My dog barks.\n", - "Output: Mi perro ladra.\n", - "\n", - "Input: Spot can run fast.\n", - "Output:\n" - ] - } - ], - "source": [ - "# An example input with large ngram overlap with \"Spot can run.\"\n", - "# and no overlap with \"My dog barks.\"\n", - "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "485f5307", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the Spanish translation of every input\n", - "\n", - "Input: Spot can run.\n", - "Output: Spot puede correr.\n", - "\n", - "Input: See Spot run.\n", - "Output: Ver correr a Spot.\n", - "\n", - "Input: Spot plays fetch.\n", - "Output: Spot juega a buscar.\n", - "\n", - "Input: My dog barks.\n", - "Output: Mi perro ladra.\n", - "\n", - "Input: Spot can run fast.\n", - "Output:\n" - ] - } - ], - "source": [ - "# You can add examples to NGramOverlapExampleSelector as well.\n", - "new_example = {\"input\": \"Spot plays fetch.\", \"output\": \"Spot juega a buscar.\"}\n", - "\n", - "example_selector.add_example(new_example)\n", - "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "606ce697", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the Spanish translation of every input\n", - "\n", - "Input: Spot can run.\n", - "Output: Spot puede correr.\n", - "\n", - "Input: See Spot run.\n", - "Output: Ver correr a Spot.\n", - "\n", - "Input: Spot plays fetch.\n", - "Output: Spot juega a buscar.\n", - "\n", - "Input: Spot can run fast.\n", - "Output:\n" - ] - } - ], - "source": [ - "# You can set a threshold at which examples are excluded.\n", - "# For example, setting threshold equal to 0.0\n", - "# excludes examples with no ngram overlaps with input.\n", - "# Since \"My dog barks.\" has no ngram overlaps with \"Spot can run fast.\"\n", - "# it is excluded.\n", - "example_selector.threshold=0.0\n", - "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 87, - "id": "7f8d72f7", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the Spanish translation of every input\n", - "\n", - "Input: Spot can run.\n", - "Output: Spot puede correr.\n", - "\n", - "Input: Spot plays fetch.\n", - "Output: Spot juega a buscar.\n", - "\n", - "Input: Spot can play fetch.\n", - "Output:\n" - ] - } - ], - "source": [ - "# Setting small nonzero threshold\n", - "example_selector.threshold=0.09\n", - "print(dynamic_prompt.format(sentence=\"Spot can play fetch.\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "id": "09633aa8", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the Spanish translation of every input\n", - "\n", - "Input: Spot can play fetch.\n", - "Output:\n" - ] - } - ], - "source": [ - "# Setting threshold greater than 1.0\n", - "example_selector.threshold=1.0+1e-9\n", - "print(dynamic_prompt.format(sentence=\"Spot can play fetch.\"))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "39f30097", - "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 -} diff --git a/docs/modules/prompts/examples/output_parsers.ipynb b/docs/modules/prompts/examples/output_parsers.ipynb deleted file mode 100644 index 449d0f4f..00000000 --- a/docs/modules/prompts/examples/output_parsers.ipynb +++ /dev/null @@ -1,764 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "084ee2f0", - "metadata": {}, - "source": [ - "# Output Parsers\n", - "\n", - "Language models output text. But many times you may want to get more structured information than just text back. This is where output parsers come in.\n", - "\n", - "Output parsers are classes that help structure language model responses. There are two main methods an output parser must implement:\n", - "\n", - "- `get_format_instructions() -> str`: A method which returns a string containing instructions for how the output of a language model should be formatted.\n", - "- `parse(str) -> Any`: A method which takes in a string (assumed to be the response from a language model) and parses it into some structure.\n", - "\n", - "And then one optional one:\n", - "\n", - "- `parse_with_prompt(str) -> Any`: A method which takes in a string (assumed to be the response from a language model) and a prompt (assumed to the prompt that generated such a response) and parses it into some structure. The prompt is largely provided in the event the OutputParser wants to retry or fix the output in some way, and needs information from the prompt to do so.\n", - "\n", - "\n", - "Below we go over some examples of output parsers." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "5f0c8a33", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", - "from langchain.llms import OpenAI\n", - "from langchain.chat_models import ChatOpenAI" - ] - }, - { - "cell_type": "markdown", - "id": "a1ae632a", - "metadata": {}, - "source": [ - "## PydanticOutputParser\n", - "This output parser allows users to specify an arbitrary JSON schema and query LLMs for JSON outputs that conform to that schema.\n", - "\n", - "Keep in mind that large language models are leaky abstractions! You'll have to use an LLM with sufficient capacity to generate well-formed JSON. In the OpenAI family, DaVinci can do reliably but Curie's ability already drops off dramatically. \n", - "\n", - "Use Pydantic to declare your data model. Pydantic's BaseModel like a Python dataclass, but with actual type checking + coercion." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "cba6d8e3", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.output_parsers import PydanticOutputParser\n", - "from pydantic import BaseModel, Field, validator\n", - "from typing import List" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0a203100", - "metadata": {}, - "outputs": [], - "source": [ - "model_name = 'text-davinci-003'\n", - "temperature = 0.0\n", - "model = OpenAI(model_name=model_name, temperature=temperature)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "b3f16168", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Define your desired data structure.\n", - "class Joke(BaseModel):\n", - " setup: str = Field(description=\"question to set up a joke\")\n", - " punchline: str = Field(description=\"answer to resolve the joke\")\n", - " \n", - " # You can add custom validation logic easily with Pydantic.\n", - " @validator('setup')\n", - " def question_ends_with_question_mark(cls, field):\n", - " if field[-1] != '?':\n", - " raise ValueError(\"Badly formed question!\")\n", - " return field\n", - "\n", - "# And a query intented to prompt a language model to populate the data structure.\n", - "joke_query = \"Tell me a joke.\"\n", - "\n", - "# Set up a parser + inject instructions into the prompt template.\n", - "parser = PydanticOutputParser(pydantic_object=Joke)\n", - "\n", - "prompt = PromptTemplate(\n", - " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", - " input_variables=[\"query\"],\n", - " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", - ")\n", - "\n", - "_input = prompt.format_prompt(query=joke_query)\n", - "\n", - "output = model(_input.to_string())\n", - "\n", - "parser.parse(output)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "03049f88", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Actor(name='Tom Hanks', film_names=['Forrest Gump', 'Saving Private Ryan', 'The Green Mile', 'Cast Away', 'Toy Story'])" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Here's another example, but with a compound typed field.\n", - "class Actor(BaseModel):\n", - " name: str = Field(description=\"name of an actor\")\n", - " film_names: List[str] = Field(description=\"list of names of films they starred in\")\n", - " \n", - "actor_query = \"Generate the filmography for a random actor.\"\n", - "\n", - "parser = PydanticOutputParser(pydantic_object=Actor)\n", - "\n", - "prompt = PromptTemplate(\n", - " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", - " input_variables=[\"query\"],\n", - " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", - ")\n", - "\n", - "_input = prompt.format_prompt(query=actor_query)\n", - "\n", - "output = model(_input.to_string())\n", - "\n", - "parser.parse(output)" - ] - }, - { - "cell_type": "markdown", - "id": "4d6c0c86", - "metadata": {}, - "source": [ - "## Fixing Output Parsing Mistakes\n", - "\n", - "The above guardrail simply tries to parse the LLM response. If it does not parse correctly, then it errors.\n", - "\n", - "But we can do other things besides throw errors. Specifically, we can pass the misformatted output, along with the formatted instructions, to the model and ask it to fix it.\n", - "\n", - "For this example, we'll use the above OutputParser. Here's what happens if we pass it a result that does not comply with the schema:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "73beb20d", - "metadata": {}, - "outputs": [], - "source": [ - "misformatted = \"{'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}\"" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "f0e5ba80", - "metadata": {}, - "outputs": [ - { - "ename": "OutputParserException", - "evalue": "Failed to parse Actor from completion {'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}. Got: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)", - "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:23\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 22\u001b[0m json_str \u001b[38;5;241m=\u001b[39m match\u001b[38;5;241m.\u001b[39mgroup()\n\u001b[0;32m---> 23\u001b[0m json_object \u001b[38;5;241m=\u001b[39m \u001b[43mjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[43mjson_str\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpydantic_object\u001b[38;5;241m.\u001b[39mparse_obj(json_object)\n", - "File \u001b[0;32m~/.pyenv/versions/3.9.1/lib/python3.9/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 344\u001b[0m parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 345\u001b[0m parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", - "File \u001b[0;32m~/.pyenv/versions/3.9.1/lib/python3.9/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m 333\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m 334\u001b[0m \u001b[38;5;124;03mcontaining a JSON document).\u001b[39;00m\n\u001b[1;32m 335\u001b[0m \n\u001b[1;32m 336\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n", - "File \u001b[0;32m~/.pyenv/versions/3.9.1/lib/python3.9/json/decoder.py:353\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m 352\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 353\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mscan_once\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n", - "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)", - "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[0;31mOutputParserException\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[7], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mparser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmisformatted\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:29\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 27\u001b[0m name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpydantic_object\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[1;32m 28\u001b[0m msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFailed to parse \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m from completion \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m. Got: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 29\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(msg)\n", - "\u001b[0;31mOutputParserException\u001b[0m: Failed to parse Actor from completion {'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}. Got: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)" - ] - } - ], - "source": [ - "parser.parse(misformatted)" - ] - }, - { - "cell_type": "markdown", - "id": "6c7c82b6", - "metadata": {}, - "source": [ - "Now we can construct and use a `OutputFixingParser`. This output parser takes as an argument another output parser but also an LLM with which to try to correct any formatting mistakes." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "39b1a5ce", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.output_parsers import OutputFixingParser\n", - "\n", - "new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "0fd96d68", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Actor(name='Tom Hanks', film_names=['Forrest Gump'])" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "new_parser.parse(misformatted)" - ] - }, - { - "cell_type": "markdown", - "id": "ea34eeaa", - "metadata": {}, - "source": [ - "## Fixing Output Parsing Mistakes with the original prompt\n", - "\n", - "While in some cases it is possible to fix any parsing mistakes by only looking at the output, in other cases it can't. An example of this is when the output is not just in the incorrect format, but is partially complete. Consider the below example." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "67c5e1ac", - "metadata": {}, - "outputs": [], - "source": [ - "template = \"\"\"Based on the user question, provide an Action and Action Input for what step should be taken.\n", - "{format_instructions}\n", - "Question: {query}\n", - "Response:\"\"\"\n", - "class Action(BaseModel):\n", - " action: str = Field(description=\"action to take\")\n", - " action_input: str = Field(description=\"input to the action\")\n", - " \n", - "parser = PydanticOutputParser(pydantic_object=Action)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "007aa87f", - "metadata": {}, - "outputs": [], - "source": [ - "prompt = PromptTemplate(\n", - " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", - " input_variables=[\"query\"],\n", - " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "10d207ff", - "metadata": {}, - "outputs": [], - "source": [ - "prompt_value = prompt.format_prompt(query=\"who is leo di caprios gf?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "68622837", - "metadata": {}, - "outputs": [], - "source": [ - "bad_response = '{\"action\": \"search\"}'" - ] - }, - { - "cell_type": "markdown", - "id": "25631465", - "metadata": {}, - "source": [ - "If we try to parse this response as is, we will get an error" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "894967c1", - "metadata": {}, - "outputs": [ - { - "ename": "OutputParserException", - "evalue": "Failed to parse Action from completion {\"action\": \"search\"}. Got: 1 validation error for Action\naction_input\n field required (type=value_error.missing)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)", - "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:24\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 23\u001b[0m json_object \u001b[38;5;241m=\u001b[39m json\u001b[38;5;241m.\u001b[39mloads(json_str)\n\u001b[0;32m---> 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpydantic_object\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_obj\u001b[49m\u001b[43m(\u001b[49m\u001b[43mjson_object\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (json\u001b[38;5;241m.\u001b[39mJSONDecodeError, ValidationError) \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/.pyenv/versions/3.9.1/envs/langchain/lib/python3.9/site-packages/pydantic/main.py:527\u001b[0m, in \u001b[0;36mpydantic.main.BaseModel.parse_obj\u001b[0;34m()\u001b[0m\n", - "File \u001b[0;32m~/.pyenv/versions/3.9.1/envs/langchain/lib/python3.9/site-packages/pydantic/main.py:342\u001b[0m, in \u001b[0;36mpydantic.main.BaseModel.__init__\u001b[0;34m()\u001b[0m\n", - "\u001b[0;31mValidationError\u001b[0m: 1 validation error for Action\naction_input\n field required (type=value_error.missing)", - "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[0;31mOutputParserException\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[15], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mparser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbad_response\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:29\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 27\u001b[0m name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpydantic_object\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[1;32m 28\u001b[0m msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFailed to parse \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m from completion \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m. Got: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 29\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(msg)\n", - "\u001b[0;31mOutputParserException\u001b[0m: Failed to parse Action from completion {\"action\": \"search\"}. Got: 1 validation error for Action\naction_input\n field required (type=value_error.missing)" - ] - } - ], - "source": [ - "parser.parse(bad_response)" - ] - }, - { - "cell_type": "markdown", - "id": "f6b64696", - "metadata": {}, - "source": [ - "If we try to use the `OutputFixingParser` to fix this error, it will be confused - namely, it doesn't know what to actually put for action input." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "78b2b40d", - "metadata": {}, - "outputs": [], - "source": [ - "fix_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "4fe1301d", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Action(action='search', action_input='keyword')" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fix_parser.parse(bad_response)" - ] - }, - { - "cell_type": "markdown", - "id": "9bd9ea7d", - "metadata": {}, - "source": [ - "Instead, we can use the RetryOutputParser, which passes in the prompt (as well as the original output) to try again to get a better response." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "7e8a8a28", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.output_parsers import RetryWithErrorOutputParser" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "5c86e141", - "metadata": {}, - "outputs": [], - "source": [ - "retry_parser = RetryWithErrorOutputParser.from_llm(parser=parser, llm=ChatOpenAI())" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "9c04f731", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Action(action='search', action_input='leo di caprios girlfriend')" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "retry_parser.parse_with_prompt(bad_response, prompt_value)" - ] - }, - { - "cell_type": "markdown", - "id": "61f67890", - "metadata": {}, - "source": [ - "
\n", - "
\n", - "
\n", - "
\n", - "
\n", - "
\n", - "
\n", - "
\n", - "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "id": "64bf525a", - "metadata": {}, - "source": [ - "# Older, less powerful parsers" - ] - }, - { - "cell_type": "markdown", - "id": "91871002", - "metadata": {}, - "source": [ - "## Structured Output Parser\n", - "\n", - "While the Pydantic/JSON parser is more powerful, we initially experimented data structures having text fields only." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "b492997a", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.output_parsers import StructuredOutputParser, ResponseSchema" - ] - }, - { - "cell_type": "markdown", - "id": "09473dce", - "metadata": {}, - "source": [ - "Here we define the response schema we want to receive." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "432ac44a", - "metadata": {}, - "outputs": [], - "source": [ - "response_schemas = [\n", - " ResponseSchema(name=\"answer\", description=\"answer to the user's question\"),\n", - " ResponseSchema(name=\"source\", description=\"source used to answer the user's question, should be a website.\")\n", - "]\n", - "output_parser = StructuredOutputParser.from_response_schemas(response_schemas)" - ] - }, - { - "cell_type": "markdown", - "id": "7b92ce96", - "metadata": {}, - "source": [ - "We now get a string that contains instructions for how the response should be formatted, and we then insert that into our prompt." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "593cfc25", - "metadata": {}, - "outputs": [], - "source": [ - "format_instructions = output_parser.get_format_instructions()\n", - "prompt = PromptTemplate(\n", - " template=\"answer the users question as best as possible.\\n{format_instructions}\\n{question}\",\n", - " input_variables=[\"question\"],\n", - " partial_variables={\"format_instructions\": format_instructions}\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "0943e783", - "metadata": {}, - "source": [ - "We can now use this to format a prompt to send to the language model, and then parse the returned result." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "106f1ba6", - "metadata": {}, - "outputs": [], - "source": [ - "model = OpenAI(temperature=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "86d9d24f", - "metadata": {}, - "outputs": [], - "source": [ - "_input = prompt.format_prompt(question=\"what's the capital of france\")\n", - "output = model(_input.to_string())" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "956bdc99", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'answer': 'Paris', 'source': 'https://en.wikipedia.org/wiki/Paris'}" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "output_parser.parse(output)" - ] - }, - { - "cell_type": "markdown", - "id": "da639285", - "metadata": {}, - "source": [ - "And here's an example of using this in a chat model" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "8f483d7d", - "metadata": {}, - "outputs": [], - "source": [ - "chat_model = ChatOpenAI(temperature=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "f761cbf1", - "metadata": {}, - "outputs": [], - "source": [ - "prompt = ChatPromptTemplate(\n", - " messages=[\n", - " HumanMessagePromptTemplate.from_template(\"answer the users question as best as possible.\\n{format_instructions}\\n{question}\") \n", - " ],\n", - " input_variables=[\"question\"],\n", - " partial_variables={\"format_instructions\": format_instructions}\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "edd73ae3", - "metadata": {}, - "outputs": [], - "source": [ - "_input = prompt.format_prompt(question=\"what's the capital of france\")\n", - "output = chat_model(_input.to_messages())" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "a3c8b91e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'answer': 'Paris', 'source': 'https://en.wikipedia.org/wiki/Paris'}" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "output_parser.parse(output.content)" - ] - }, - { - "cell_type": "markdown", - "id": "9936fa27", - "metadata": {}, - "source": [ - "## CommaSeparatedListOutputParser\n", - "\n", - "Here's another parser strictly less powerful than Pydantic/JSON parsing." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "872246d7", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.output_parsers import CommaSeparatedListOutputParser" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "c3f9aee6", - "metadata": {}, - "outputs": [], - "source": [ - "output_parser = CommaSeparatedListOutputParser()" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "e77871b7", - "metadata": {}, - "outputs": [], - "source": [ - "format_instructions = output_parser.get_format_instructions()\n", - "prompt = PromptTemplate(\n", - " template=\"List five {subject}.\\n{format_instructions}\",\n", - " input_variables=[\"subject\"],\n", - " partial_variables={\"format_instructions\": format_instructions}\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "a71cb5d3", - "metadata": {}, - "outputs": [], - "source": [ - "model = OpenAI(temperature=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "783d7d98", - "metadata": {}, - "outputs": [], - "source": [ - "_input = prompt.format(subject=\"ice cream flavors\")\n", - "output = model(_input)" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "fcb81344", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['Vanilla',\n", - " 'Chocolate',\n", - " 'Strawberry',\n", - " 'Mint Chocolate Chip',\n", - " 'Cookies and Cream']" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "output_parser.parse(output)" - ] - } - ], - "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 -} diff --git a/docs/modules/prompts/examples/prompt_management.ipynb b/docs/modules/prompts/examples/prompt_management.ipynb deleted file mode 100644 index 7b7c6814..00000000 --- a/docs/modules/prompts/examples/prompt_management.ipynb +++ /dev/null @@ -1,886 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "43fb16cb", - "metadata": {}, - "source": [ - "# Getting Started\n", - "\n", - "Managing your prompts is annoying and tedious, with everyone writing their own slightly different variants of the same ideas. But it shouldn't be this way. \n", - "\n", - "LangChain provides a standard and flexible way for specifying and managing all your prompts, as well as clear and specific terminology around them. This notebook goes through the core components of working with prompts, showing how to use them as well as explaining what they do.\n", - "\n", - "This notebook covers how to work with prompts in Python. If you are interested in how to work with serialized versions of prompts and load them from disk, see [this notebook](prompt_serialization.ipynb)." - ] - }, - { - "cell_type": "markdown", - "id": "890aad4d", - "metadata": {}, - "source": [ - "### The BasePromptTemplate Interface\n", - "\n", - "A prompt template is a mechanism for constructing a prompt to pass to the language model given some user input. Below is the interface that all different types of prompt templates should expose.\n", - "\n", - "```python\n", - "class BasePromptTemplate(ABC):\n", - "\n", - " input_variables: List[str]\n", - " \"\"\"A list of the names of the variables the prompt template expects.\"\"\"\n", - "\n", - " @abstractmethod\n", - " def format(self, **kwargs: Any) -> str:\n", - " \"\"\"Format the prompt with the inputs.\n", - "\n", - " Args:\n", - " kwargs: Any arguments to be passed to the prompt template.\n", - "\n", - " Returns:\n", - " A formatted string.\n", - "\n", - " Example:\n", - "\n", - " .. code-block:: python\n", - "\n", - " prompt.format(variable1=\"foo\")\n", - " \"\"\"\n", - "```\n", - "\n", - "The only two things that define a prompt are:\n", - "\n", - "1. `input_variables`: The user inputted variables that are needed to format the prompt.\n", - "2. `format`: A method which takes in keyword arguments and returns a formatted prompt. The keys are expected to be the input variables\n", - " \n", - "The rest of the logic of how the prompt is constructed is left up to different implementations. Let's take a look at some below." - ] - }, - { - "cell_type": "markdown", - "id": "cddb465e", - "metadata": {}, - "source": [ - "### PromptTemplate\n", - "\n", - "This is the most simple type of prompt template, consisting of a string template that takes any number of input variables. The template should be formatted as a Python f-string, although we will support other formats (Jinja, Mako, etc) in the future. \n", - "\n", - "If you just want to use a hardcoded prompt template, you should use this implementation.\n", - "\n", - "Let's walk through a few examples." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "094229f4", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import PromptTemplate" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "ab46bd2a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Tell me a joke.'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# An example prompt with no input variables\n", - "no_input_prompt = PromptTemplate(input_variables=[], template=\"Tell me a joke.\")\n", - "no_input_prompt.format()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "c3ad0fa8", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Tell me a funny joke.'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# An example prompt with one input variable\n", - "one_input_prompt = PromptTemplate(input_variables=[\"adjective\"], template=\"Tell me a {adjective} joke.\")\n", - "one_input_prompt.format(adjective=\"funny\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ba577dcf", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Tell me a funny joke about chickens.'" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# An example prompt with multiple input variables\n", - "multiple_input_prompt = PromptTemplate(\n", - " input_variables=[\"adjective\", \"content\"], \n", - " template=\"Tell me a {adjective} joke about {content}.\"\n", - ")\n", - "multiple_input_prompt.format(adjective=\"funny\", content=\"chickens\")" - ] - }, - { - "cell_type": "markdown", - "id": "cc991ad2", - "metadata": {}, - "source": [ - "## From Template\n", - "You can also easily load a prompt template by just specifying the template, and not worrying about the input variables." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d0a0756c", - "metadata": {}, - "outputs": [], - "source": [ - "template = \"Tell me a {adjective} joke about {content}.\"\n", - "multiple_input_prompt = PromptTemplate.from_template(template)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "59046640", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "PromptTemplate(input_variables=['adjective', 'content'], output_parser=None, template='Tell me a {adjective} joke about {content}.', template_format='f-string', validate_template=True)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "multiple_input_prompt" - ] - }, - { - "cell_type": "markdown", - "id": "b2dd6154", - "metadata": {}, - "source": [ - "## Alternative formats\n", - "\n", - "This section shows how to use alternative formats besides \"f-string\" to format prompts." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "53b41b6a", - "metadata": {}, - "outputs": [], - "source": [ - "# Jinja2\n", - "template = \"\"\"\n", - "{% for item in items %}\n", - "Question: {{ item.question }}\n", - "Answer: {{ item.answer }}\n", - "{% endfor %}\n", - "\"\"\"\n", - "items=[{\"question\": \"foo\", \"answer\": \"bar\"},{\"question\": \"1\", \"answer\": \"2\"}]\n", - "jinja2_prompt = PromptTemplate(\n", - " input_variables=[\"items\"], \n", - " template=template,\n", - " template_format=\"jinja2\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "ba8aabd3", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'\\n\\nQuestion: foo\\nAnswer: bar\\n\\nQuestion: 1\\nAnswer: 2\\n'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "jinja2_prompt.format(items=items)" - ] - }, - { - "cell_type": "markdown", - "id": "1492b49d", - "metadata": {}, - "source": [ - "### Few Shot Prompts\n", - "\n", - "A FewShotPromptTemplate is a prompt template that includes some examples. If you have collected some examples of how the task should be done, you can insert them into prompt using this class.\n", - "\n", - "Examples are datapoints that can be included in the prompt in order to give the model more context what to do. Examples are represented as a dictionary of key-value pairs, with the key being the input (or label) name, and the value being the input (or label) value. \n", - "\n", - "In addition to the example, we also need to specify how the example should be formatted when it's inserted in the prompt. We can do this using the above `PromptTemplate`!" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "3eb36972", - "metadata": {}, - "outputs": [], - "source": [ - "# These are some examples of a pretend task of creating antonyms.\n", - "examples = [\n", - " {\"input\": \"happy\", \"output\": \"sad\"},\n", - " {\"input\": \"tall\", \"output\": \"short\"},\n", - "]\n", - "# This how we specify how the example should be formatted.\n", - "example_prompt = PromptTemplate(\n", - " input_variables=[\"input\",\"output\"],\n", - " template=\"Input: {input}\\nOutput: {output}\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "80a91d96", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import FewShotPromptTemplate" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "7931e5f2", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: tall\n", - "Output: short\n", - "\n", - "Input: big\n", - "Output:\n" - ] - } - ], - "source": [ - "prompt_from_string_examples = FewShotPromptTemplate(\n", - " # These are the examples we want to insert into the prompt.\n", - " examples=examples,\n", - " # This is how we want to format the examples when we insert them into the prompt.\n", - " example_prompt=example_prompt,\n", - " # The prefix is some text that goes before the examples in the prompt.\n", - " # Usually, this consists of intructions.\n", - " prefix=\"Give the antonym of every input\",\n", - " # The suffix is some text that goes after the examples in the prompt.\n", - " # Usually, this is where the user input will go\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " # The input variables are the variables that the overall prompt expects.\n", - " input_variables=[\"adjective\"],\n", - " # The example_separator is the string we will use to join the prefix, examples, and suffix together with.\n", - " example_separator=\"\\n\\n\"\n", - " \n", - ")\n", - "print(prompt_from_string_examples.format(adjective=\"big\"))" - ] - }, - { - "cell_type": "markdown", - "id": "874b7575", - "metadata": {}, - "source": [ - "## Few Shot Prompts with Templates\n", - "We can also construct few shot prompt templates where the prefix and suffix themselves are prompt templates" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "e710115f", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts import FewShotPromptWithTemplates" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "5bf23a65", - "metadata": {}, - "outputs": [], - "source": [ - "prefix = PromptTemplate(input_variables=[\"content\"], template=\"This is a test about {content}.\")\n", - "suffix = PromptTemplate(input_variables=[\"new_content\"], template=\"Now you try to talk about {new_content}.\")\n", - "\n", - "prompt = FewShotPromptWithTemplates(\n", - " suffix=suffix,\n", - " prefix=prefix,\n", - " input_variables=[\"content\", \"new_content\"],\n", - " examples=examples,\n", - " example_prompt=example_prompt,\n", - " example_separator=\"\\n\",\n", - ")\n", - "output = prompt.format(content=\"animals\", new_content=\"party\")" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "d4036351", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This is a test about animals.\n", - "Input: happy\n", - "Output: sad\n", - "Input: tall\n", - "Output: short\n", - "Now you try to talk about party.\n" - ] - } - ], - "source": [ - "print(output)" - ] - }, - { - "cell_type": "markdown", - "id": "bf038596", - "metadata": {}, - "source": [ - "### ExampleSelector\n", - "If you have a large number of examples, you may need to select which ones to include in the prompt. The ExampleSelector is the class responsible for doing so. The base interface is defined as below.\n", - "\n", - "```python\n", - "class BaseExampleSelector(ABC):\n", - " \"\"\"Interface for selecting examples to include in prompts.\"\"\"\n", - "\n", - " @abstractmethod\n", - " def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:\n", - " \"\"\"Select which examples to use based on the inputs.\"\"\"\n", - "\n", - "```\n", - "\n", - "The only method it needs to expose is a `select_examples` method. This takes in the input variables and then returns a list of examples. It is up to each specific implementation as to how those examples are selected. Let's take a look at some below." - ] - }, - { - "cell_type": "markdown", - "id": "861a4d1f", - "metadata": {}, - "source": [ - "### LengthBased ExampleSelector\n", - "\n", - "This ExampleSelector selects which examples to use based on length. This is useful when you are worried about constructing a prompt that will go over the length of the context window. For longer inputs, it will select fewer examples to include, while for shorter inputs it will select more.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "7c469c95", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts.example_selector import LengthBasedExampleSelector" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "0ec6d950", - "metadata": {}, - "outputs": [], - "source": [ - "# These are a lot of examples of a pretend task of creating antonyms.\n", - "examples = [\n", - " {\"input\": \"happy\", \"output\": \"sad\"},\n", - " {\"input\": \"tall\", \"output\": \"short\"},\n", - " {\"input\": \"energetic\", \"output\": \"lethargic\"},\n", - " {\"input\": \"sunny\", \"output\": \"gloomy\"},\n", - " {\"input\": \"windy\", \"output\": \"calm\"},\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "207e55f7", - "metadata": {}, - "outputs": [], - "source": [ - "example_selector = LengthBasedExampleSelector(\n", - " # These are the examples is has available to choose from.\n", - " examples=examples, \n", - " # This is the PromptTemplate being used to format the examples.\n", - " example_prompt=example_prompt, \n", - " # This is the maximum length that the formatted examples should be.\n", - " # Length is measured by the get_text_length function below.\n", - " max_length=25,\n", - " # This is the function used to get the length of a string, which is used\n", - " # to determine which examples to include. It is commented out because\n", - " # it is provided as a default value if none is specified.\n", - " # get_text_length: Callable[[str], int] = lambda x: len(re.split(\"\\n| \", x))\n", - ")\n", - "dynamic_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the antonym of every input\",\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " input_variables=[\"adjective\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "d00b4385", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: tall\n", - "Output: short\n", - "\n", - "Input: energetic\n", - "Output: lethargic\n", - "\n", - "Input: sunny\n", - "Output: gloomy\n", - "\n", - "Input: windy\n", - "Output: calm\n", - "\n", - "Input: big\n", - "Output:\n" - ] - } - ], - "source": [ - "# An example with small input, so it selects all examples.\n", - "print(dynamic_prompt.format(adjective=\"big\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "878bcde9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else\n", - "Output:\n" - ] - } - ], - "source": [ - "# An example with long input, so it selects only one example.\n", - "long_string = \"big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else\"\n", - "print(dynamic_prompt.format(adjective=long_string))" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "e4bebcd9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: tall\n", - "Output: short\n", - "\n", - "Input: energetic\n", - "Output: lethargic\n", - "\n", - "Input: sunny\n", - "Output: gloomy\n", - "\n", - "Input: windy\n", - "Output: calm\n", - "\n", - "Input: big\n", - "Output: small\n", - "\n", - "Input: enthusiastic\n", - "Output:\n" - ] - } - ], - "source": [ - "# You can add an example to an example selector as well.\n", - "new_example = {\"input\": \"big\", \"output\": \"small\"}\n", - "dynamic_prompt.example_selector.add_example(new_example)\n", - "print(dynamic_prompt.format(adjective=\"enthusiastic\"))" - ] - }, - { - "cell_type": "markdown", - "id": "2d007b0a", - "metadata": {}, - "source": [ - "### Similarity ExampleSelector\n", - "\n", - "The SemanticSimilarityExampleSelector selects examples based on which examples are most similar to the inputs. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "241bfe80", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n", - "from langchain.vectorstores import Chroma\n", - "from langchain.embeddings import OpenAIEmbeddings" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "50d0a701", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running Chroma using direct local API.\n", - "Using DuckDB in-memory for database. Data will be transient.\n" - ] - } - ], - "source": [ - "example_selector = SemanticSimilarityExampleSelector.from_examples(\n", - " # This is the list of examples available to select from.\n", - " examples, \n", - " # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n", - " OpenAIEmbeddings(), \n", - " # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n", - " Chroma, \n", - " # This is the number of examples to produce.\n", - " k=1\n", - ")\n", - "similar_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the antonym of every input\",\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " input_variables=[\"adjective\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "4c8fdf45", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: worried\n", - "Output:\n" - ] - } - ], - "source": [ - "# Input is a feeling, so should select the happy/sad example\n", - "print(similar_prompt.format(adjective=\"worried\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "829af21a", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: fat\n", - "Output:\n" - ] - } - ], - "source": [ - "# Input is a measurement, so should select the tall/short example\n", - "print(similar_prompt.format(adjective=\"fat\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "3c16fe23", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: joyful\n", - "Output:\n" - ] - } - ], - "source": [ - "# You can add new examples to the SemanticSimilarityExampleSelector as well\n", - "similar_prompt.example_selector.add_example({\"input\": \"enthusiastic\", \"output\": \"apathetic\"})\n", - "print(similar_prompt.format(adjective=\"joyful\"))" - ] - }, - { - "cell_type": "markdown", - "id": "bc35afd0", - "metadata": {}, - "source": [ - "### Maximal Marginal Relevance ExampleSelector\n", - "\n", - "The MaxMarginalRelevanceExampleSelector selects examples based on a combination of which examples are most similar to the inputs, while also optimizing for diversity. It does this by finding the examples with the embeddings that have the greatest cosine similarity with the inputs, and then iteratively adding them while penalizing them for closeness to already selected examples.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "ac95c968", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector\n", - "from langchain.vectorstores import FAISS" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "db579bea", - "metadata": {}, - "outputs": [], - "source": [ - "example_selector = MaxMarginalRelevanceExampleSelector.from_examples(\n", - " # This is the list of examples available to select from.\n", - " examples, \n", - " # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n", - " OpenAIEmbeddings(), \n", - " # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n", - " FAISS, \n", - " # This is the number of examples to produce.\n", - " k=2\n", - ")\n", - "mmr_prompt = FewShotPromptTemplate(\n", - " # We provide an ExampleSelector instead of examples.\n", - " example_selector=example_selector,\n", - " example_prompt=example_prompt,\n", - " prefix=\"Give the antonym of every input\",\n", - " suffix=\"Input: {adjective}\\nOutput:\", \n", - " input_variables=[\"adjective\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "cd76e344", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: windy\n", - "Output: calm\n", - "\n", - "Input: worried\n", - "Output:\n" - ] - } - ], - "source": [ - "# Input is a feeling, so should select the happy/sad example as the first one\n", - "print(mmr_prompt.format(adjective=\"worried\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "cf82956b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Give the antonym of every input\n", - "\n", - "Input: happy\n", - "Output: sad\n", - "\n", - "Input: enthusiastic\n", - "Output: apathetic\n", - "\n", - "Input: worried\n", - "Output:\n" - ] - } - ], - "source": [ - "# Let's compare this to what we would just get if we went solely off of similarity\n", - "similar_prompt.example_selector.k = 2\n", - "print(similar_prompt.format(adjective=\"worried\"))" - ] - }, - { - "cell_type": "markdown", - "id": "dbc32551", - "metadata": {}, - "source": [ - "### Serialization\n", - "\n", - "PromptTemplates and examples can be serialized and loaded from disk, making it easy to share and store prompts. For a detailed walkthrough on how to do that, see [this notebook](prompt_serialization.ipynb)." - ] - }, - { - "cell_type": "markdown", - "id": "1e1e13c6", - "metadata": {}, - "source": [ - "### Customizability\n", - "The above covers all the ways currently supported in LangChain to represent prompts and example selectors. However, due to the simple interface that the base classes (`BasePromptTemplate`, `BaseExampleSelector`) expose, it should be easy to subclass them and write your own implementation in your own codebase. And of course, if you'd like to contribute that back to LangChain, we'd love that :)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c746d6f4", - "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" - }, - "vscode": { - "interpreter": { - "hash": "b1677b440931f40d89ef8be7bf03acb108ce003de0ac9b18e8d43753ea2e7103" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/modules/prompts/how_to_guides.rst b/docs/modules/prompts/how_to_guides.rst deleted file mode 100644 index 9adb862e..00000000 --- a/docs/modules/prompts/how_to_guides.rst +++ /dev/null @@ -1,35 +0,0 @@ -How-To Guides -============= - -If you're new to the library, you may want to start with the `Quickstart <./getting_started.html>`_. - -The user guide here shows more advanced workflows and how to use the library in different ways. - -`Custom Prompt Template <./examples/custom_prompt_template.html>`_: How to create and use a custom PromptTemplate, the logic that decides how input variables get formatted into a prompt. - -`Custom Example Selector <./examples/custom_example_selector.html>`_: How to create and use a custom ExampleSelector (the class responsible for choosing which examples to use in a prompt). - -`Few Shot Prompt Templates <./examples/few_shot_examples.html>`_: How to include examples in the prompt. - -`Example Selectors <./examples/example_selectors.html>`_: How to use different types of example selectors. - -`Prompt Serialization <./examples/prompt_serialization.html>`_: A walkthrough of how to serialize prompts to and from disk. - -`Few Shot Prompt Examples <./examples/few_shot_examples.html>`_: Examples of Few Shot Prompt Templates. - -`Partial Prompt Template <./examples/partial.html>`_: How to partial Prompt Templates. - - - -.. toctree:: - :maxdepth: 1 - :glob: - :hidden: - - ./examples/custom_prompt_template.md - ./examples/custom_example_selector.md - ./examples/few_shot_examples.ipynb - ./examples/prompt_serialization.ipynb - ./examples/few_shot_examples_data.ipynb - ./examples/example_selectors.ipynb - ./examples/output_parsers.ipynb diff --git a/docs/modules/prompts/key_concepts.md b/docs/modules/prompts/key_concepts.md deleted file mode 100644 index 8ecb0340..00000000 --- a/docs/modules/prompts/key_concepts.md +++ /dev/null @@ -1,75 +0,0 @@ -# Key Concepts - -## Prompts - -A prompt is the input to a language model. It is a string of text that is used to generate a response from the language model. - -## Prompt Templates - -`PromptTemplates` are a way to create prompts in a reproducible way. They contain a template string, and a set of input variables. The template string can be formatted with the input variables to generate a prompt. The template string often contains instructions to the language model, a few shot examples, and a question to the language model. - -`PromptTemplates` generically have a `format` method that takes in variables and returns a formatted string. -The most simple implementation of this is to have a template string with some variables in it, and then format it with the incoming variables. -More complex iterations dynamically construct the template string from few shot examples, etc. - -To learn more about `PromptTemplates`, see [Prompt Templates](getting_started.md). - -As an example, consider the following template string: - -```python -""" -Predict the capital of a country. - -Country: {country} -Capital: -""" -``` - -### Input Variables - -Input variables are the variables that are used to fill in the template string. In the example above, the input variable is `country`. - -Given an input variable, the `PromptTemplate` can generate a prompt by filling in the template string with the input variable. For example, if the input variable is `United States`, the template string can be formatted to generate the following prompt: - -```python -""" -Predict the capital of a country. - -Country: United States -Capital: -""" -``` - -## Few Shot Examples - -Few shot examples refer to in-context examples that are provided to a language model as part of a prompt. The examples can be used to help the language model understand the context of the prompt, and as a result generate a better response. Few shot examples can contain both positive and negative examples about the expected response. - -Below, we list out some few shot examples that may be relevant for the task of predicting the capital of a country. - -``` -Country: United States -Capital: Washington, D.C. - -Country: Canada -Capital: Ottawa -``` - -To learn more about how to provide few shot examples, see [Few Shot Examples](examples/few_shot_examples.ipynb). - - - -## Example selection - -If there are multiple examples that are relevant to a prompt, it is important to select the most relevant examples. Generally, the quality of the response from the LLM can be significantly improved by selecting the most relevant examples. This is because the language model will be able to better understand the context of the prompt, and also potentially learn failure modes to avoid. - -To help the user with selecting the most relevant examples, we provide example selectors that select the most relevant based on different criteria, such as length, semantic similarity, etc. The example selector takes in a list of examples and returns a list of selected examples, formatted as a string. The user can also provide their own example selector. To learn more about example selectors, see [Example Selectors](examples/example_selectors.ipynb). - - - -## Serialization - -To make it easy to share `PromptTemplates`, we provide a `serialize` method that returns a JSON string. The JSON string can be saved to a file, and then loaded back into a `PromptTemplate` using the `deserialize` method. This allows users to share `PromptTemplates` with others, and also to save them for later use. - -To learn more about serialization, see [Serialization](examples/prompt_serialization.ipynb). - - diff --git a/docs/modules/prompts/output_parsers.rst b/docs/modules/prompts/output_parsers.rst new file mode 100644 index 00000000..a71bd067 --- /dev/null +++ b/docs/modules/prompts/output_parsers.rst @@ -0,0 +1,32 @@ +Output Parsers +========================== + +.. note:: + `Conceptual Guide `_ + + +Language models output text. But many times you may want to get more structured information than just text back. This is where output parsers come in. + +Output parsers are classes that help structure language model responses. There are two main methods an output parser must implement: + +- ``get_format_instructions() -> str``: A method which returns a string containing instructions for how the output of a language model should be formatted. +- ``parse(str) -> Any``: A method which takes in a string (assumed to be the response from a language model) and parses it into some structure. + +And then one optional one: + +- ``parse_with_prompt(str) -> Any``: A method which takes in a string (assumed to be the response from a language model) and a prompt (assumed to the prompt that generated such a response) and parses it into some structure. The prompt is largely provided in the event the OutputParser wants to retry or fix the output in some way, and needs information from the prompt to do so. + +To start, we recommend familiarizing yourself with the Getting Started section + +.. toctree:: + :maxdepth: 1 + + ./output_parsers/getting_started.md + +After that, we provide deep dives on all the different types of output parsers. + +.. toctree:: + :maxdepth: 1 + :glob: + + ./output_parsers/examples/* \ No newline at end of file diff --git a/docs/modules/prompts/output_parsers/examples/comma_separated.ipynb b/docs/modules/prompts/output_parsers/examples/comma_separated.ipynb new file mode 100644 index 00000000..3a9c7627 --- /dev/null +++ b/docs/modules/prompts/output_parsers/examples/comma_separated.ipynb @@ -0,0 +1,127 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9936fa27", + "metadata": {}, + "source": [ + "# CommaSeparatedListOutputParser\n", + "\n", + "Here's another parser strictly less powerful than Pydantic/JSON parsing." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "872246d7", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.output_parsers import CommaSeparatedListOutputParser\n", + "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", + "from langchain.llms import OpenAI\n", + "from langchain.chat_models import ChatOpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c3f9aee6", + "metadata": {}, + "outputs": [], + "source": [ + "output_parser = CommaSeparatedListOutputParser()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e77871b7", + "metadata": {}, + "outputs": [], + "source": [ + "format_instructions = output_parser.get_format_instructions()\n", + "prompt = PromptTemplate(\n", + " template=\"List five {subject}.\\n{format_instructions}\",\n", + " input_variables=[\"subject\"],\n", + " partial_variables={\"format_instructions\": format_instructions}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a71cb5d3", + "metadata": {}, + "outputs": [], + "source": [ + "model = OpenAI(temperature=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "783d7d98", + "metadata": {}, + "outputs": [], + "source": [ + "_input = prompt.format(subject=\"ice cream flavors\")\n", + "output = model(_input)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "fcb81344", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Vanilla',\n", + " 'Chocolate',\n", + " 'Strawberry',\n", + " 'Mint Chocolate Chip',\n", + " 'Cookies and Cream']" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "output_parser.parse(output)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca5a23c5", + "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 +} diff --git a/docs/modules/prompts/output_parsers/examples/output_fixing_parser.ipynb b/docs/modules/prompts/output_parsers/examples/output_fixing_parser.ipynb new file mode 100644 index 00000000..f638d5b6 --- /dev/null +++ b/docs/modules/prompts/output_parsers/examples/output_fixing_parser.ipynb @@ -0,0 +1,153 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4d6c0c86", + "metadata": {}, + "source": [ + "# OutputFixingParser\n", + "\n", + "This output parser wraps another output parser and tries to fix any mmistakes\n", + "\n", + "The Pydantic guardrail simply tries to parse the LLM response. If it does not parse correctly, then it errors.\n", + "\n", + "But we can do other things besides throw errors. Specifically, we can pass the misformatted output, along with the formatted instructions, to the model and ask it to fix it.\n", + "\n", + "For this example, we'll use the above OutputParser. Here's what happens if we pass it a result that does not comply with the schema:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "50048777", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", + "from langchain.llms import OpenAI\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.output_parsers import PydanticOutputParser\n", + "from pydantic import BaseModel, Field, validator\n", + "from typing import List" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4f1b563f", + "metadata": {}, + "outputs": [], + "source": [ + "class Actor(BaseModel):\n", + " name: str = Field(description=\"name of an actor\")\n", + " film_names: List[str] = Field(description=\"list of names of films they starred in\")\n", + " \n", + "actor_query = \"Generate the filmography for a random actor.\"\n", + "\n", + "parser = PydanticOutputParser(pydantic_object=Actor)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "73beb20d", + "metadata": {}, + "outputs": [], + "source": [ + "misformatted = \"{'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}\"" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f0e5ba80", + "metadata": {}, + "outputs": [ + { + "ename": "OutputParserException", + "evalue": "Failed to parse Actor from completion {'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}. Got: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:23\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 22\u001b[0m json_str \u001b[38;5;241m=\u001b[39m match\u001b[38;5;241m.\u001b[39mgroup()\n\u001b[0;32m---> 23\u001b[0m json_object \u001b[38;5;241m=\u001b[39m \u001b[43mjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[43mjson_str\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpydantic_object\u001b[38;5;241m.\u001b[39mparse_obj(json_object)\n", + "File \u001b[0;32m~/.pyenv/versions/3.9.1/lib/python3.9/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 344\u001b[0m parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 345\u001b[0m parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "File \u001b[0;32m~/.pyenv/versions/3.9.1/lib/python3.9/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m 333\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m 334\u001b[0m \u001b[38;5;124;03mcontaining a JSON document).\u001b[39;00m\n\u001b[1;32m 335\u001b[0m \n\u001b[1;32m 336\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n", + "File \u001b[0;32m~/.pyenv/versions/3.9.1/lib/python3.9/json/decoder.py:353\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m 352\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 353\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mscan_once\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n", + "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mOutputParserException\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mparser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmisformatted\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:29\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 27\u001b[0m name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpydantic_object\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[1;32m 28\u001b[0m msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFailed to parse \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m from completion \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m. Got: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 29\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(msg)\n", + "\u001b[0;31mOutputParserException\u001b[0m: Failed to parse Actor from completion {'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}. Got: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)" + ] + } + ], + "source": [ + "parser.parse(misformatted)" + ] + }, + { + "cell_type": "markdown", + "id": "6c7c82b6", + "metadata": {}, + "source": [ + "Now we can construct and use a `OutputFixingParser`. This output parser takes as an argument another output parser but also an LLM with which to try to correct any formatting mistakes." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "39b1a5ce", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.output_parsers import OutputFixingParser\n", + "\n", + "new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "0fd96d68", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Actor(name='Tom Hanks', film_names=['Forrest Gump'])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_parser.parse(misformatted)" + ] + } + ], + "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 +} diff --git a/docs/modules/prompts/output_parsers/examples/pydantic.ipynb b/docs/modules/prompts/output_parsers/examples/pydantic.ipynb new file mode 100644 index 00000000..94628aaa --- /dev/null +++ b/docs/modules/prompts/output_parsers/examples/pydantic.ipynb @@ -0,0 +1,163 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a1ae632a", + "metadata": {}, + "source": [ + "# PydanticOutputParser\n", + "This output parser allows users to specify an arbitrary JSON schema and query LLMs for JSON outputs that conform to that schema.\n", + "\n", + "Keep in mind that large language models are leaky abstractions! You'll have to use an LLM with sufficient capacity to generate well-formed JSON. In the OpenAI family, DaVinci can do reliably but Curie's ability already drops off dramatically. \n", + "\n", + "Use Pydantic to declare your data model. Pydantic's BaseModel like a Python dataclass, but with actual type checking + coercion." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b322c447", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", + "from langchain.llms import OpenAI\n", + "from langchain.chat_models import ChatOpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cba6d8e3", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.output_parsers import PydanticOutputParser\n", + "from pydantic import BaseModel, Field, validator\n", + "from typing import List" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0a203100", + "metadata": {}, + "outputs": [], + "source": [ + "model_name = 'text-davinci-003'\n", + "temperature = 0.0\n", + "model = OpenAI(model_name=model_name, temperature=temperature)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "b3f16168", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Define your desired data structure.\n", + "class Joke(BaseModel):\n", + " setup: str = Field(description=\"question to set up a joke\")\n", + " punchline: str = Field(description=\"answer to resolve the joke\")\n", + " \n", + " # You can add custom validation logic easily with Pydantic.\n", + " @validator('setup')\n", + " def question_ends_with_question_mark(cls, field):\n", + " if field[-1] != '?':\n", + " raise ValueError(\"Badly formed question!\")\n", + " return field\n", + "\n", + "# And a query intented to prompt a language model to populate the data structure.\n", + "joke_query = \"Tell me a joke.\"\n", + "\n", + "# Set up a parser + inject instructions into the prompt template.\n", + "parser = PydanticOutputParser(pydantic_object=Joke)\n", + "\n", + "prompt = PromptTemplate(\n", + " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", + " input_variables=[\"query\"],\n", + " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", + ")\n", + "\n", + "_input = prompt.format_prompt(query=joke_query)\n", + "\n", + "output = model(_input.to_string())\n", + "\n", + "parser.parse(output)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "03049f88", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Actor(name='Tom Hanks', film_names=['Forrest Gump', 'Saving Private Ryan', 'The Green Mile', 'Cast Away', 'Toy Story'])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Here's another example, but with a compound typed field.\n", + "class Actor(BaseModel):\n", + " name: str = Field(description=\"name of an actor\")\n", + " film_names: List[str] = Field(description=\"list of names of films they starred in\")\n", + " \n", + "actor_query = \"Generate the filmography for a random actor.\"\n", + "\n", + "parser = PydanticOutputParser(pydantic_object=Actor)\n", + "\n", + "prompt = PromptTemplate(\n", + " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", + " input_variables=[\"query\"],\n", + " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", + ")\n", + "\n", + "_input = prompt.format_prompt(query=actor_query)\n", + "\n", + "output = model(_input.to_string())\n", + "\n", + "parser.parse(output)" + ] + } + ], + "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 +} diff --git a/docs/modules/prompts/output_parsers/examples/retry.ipynb b/docs/modules/prompts/output_parsers/examples/retry.ipynb new file mode 100644 index 00000000..3215cebd --- /dev/null +++ b/docs/modules/prompts/output_parsers/examples/retry.ipynb @@ -0,0 +1,227 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4d6c0c86", + "metadata": {}, + "source": [ + "# RetryOutputParser\n", + "\n", + "While in some cases it is possible to fix any parsing mistakes by only looking at the output, in other cases it can't. An example of this is when the output is not just in the incorrect format, but is partially complete. Consider the below example." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f28526bd", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", + "from langchain.llms import OpenAI\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.output_parsers import PydanticOutputParser, OutputFixingParser, RetryOutputParser\n", + "from pydantic import BaseModel, Field, validator\n", + "from typing import List" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "67c5e1ac", + "metadata": {}, + "outputs": [], + "source": [ + "template = \"\"\"Based on the user question, provide an Action and Action Input for what step should be taken.\n", + "{format_instructions}\n", + "Question: {query}\n", + "Response:\"\"\"\n", + "class Action(BaseModel):\n", + " action: str = Field(description=\"action to take\")\n", + " action_input: str = Field(description=\"input to the action\")\n", + " \n", + "parser = PydanticOutputParser(pydantic_object=Action)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "007aa87f", + "metadata": {}, + "outputs": [], + "source": [ + "prompt = PromptTemplate(\n", + " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", + " input_variables=[\"query\"],\n", + " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "10d207ff", + "metadata": {}, + "outputs": [], + "source": [ + "prompt_value = prompt.format_prompt(query=\"who is leo di caprios gf?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "68622837", + "metadata": {}, + "outputs": [], + "source": [ + "bad_response = '{\"action\": \"search\"}'" + ] + }, + { + "cell_type": "markdown", + "id": "25631465", + "metadata": {}, + "source": [ + "If we try to parse this response as is, we will get an error" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "894967c1", + "metadata": {}, + "outputs": [ + { + "ename": "OutputParserException", + "evalue": "Failed to parse Action from completion {\"action\": \"search\"}. Got: 1 validation error for Action\naction_input\n field required (type=value_error.missing)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:24\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 23\u001b[0m json_object \u001b[38;5;241m=\u001b[39m json\u001b[38;5;241m.\u001b[39mloads(json_str)\n\u001b[0;32m---> 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpydantic_object\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_obj\u001b[49m\u001b[43m(\u001b[49m\u001b[43mjson_object\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (json\u001b[38;5;241m.\u001b[39mJSONDecodeError, ValidationError) \u001b[38;5;28;01mas\u001b[39;00m e:\n", + "File \u001b[0;32m~/.pyenv/versions/3.9.1/envs/langchain/lib/python3.9/site-packages/pydantic/main.py:527\u001b[0m, in \u001b[0;36mpydantic.main.BaseModel.parse_obj\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32m~/.pyenv/versions/3.9.1/envs/langchain/lib/python3.9/site-packages/pydantic/main.py:342\u001b[0m, in \u001b[0;36mpydantic.main.BaseModel.__init__\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mValidationError\u001b[0m: 1 validation error for Action\naction_input\n field required (type=value_error.missing)", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mOutputParserException\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mparser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbad_response\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/workplace/langchain/langchain/output_parsers/pydantic.py:29\u001b[0m, in \u001b[0;36mPydanticOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 27\u001b[0m name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpydantic_object\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[1;32m 28\u001b[0m msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFailed to parse \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m from completion \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m. Got: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 29\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(msg)\n", + "\u001b[0;31mOutputParserException\u001b[0m: Failed to parse Action from completion {\"action\": \"search\"}. Got: 1 validation error for Action\naction_input\n field required (type=value_error.missing)" + ] + } + ], + "source": [ + "parser.parse(bad_response)" + ] + }, + { + "cell_type": "markdown", + "id": "f6b64696", + "metadata": {}, + "source": [ + "If we try to use the `OutputFixingParser` to fix this error, it will be confused - namely, it doesn't know what to actually put for action input." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "78b2b40d", + "metadata": {}, + "outputs": [], + "source": [ + "fix_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4fe1301d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Action(action='search', action_input='')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fix_parser.parse(bad_response)" + ] + }, + { + "cell_type": "markdown", + "id": "9bd9ea7d", + "metadata": {}, + "source": [ + "Instead, we can use the RetryOutputParser, which passes in the prompt (as well as the original output) to try again to get a better response." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7e8a8a28", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.output_parsers import RetryWithErrorOutputParser" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "5c86e141", + "metadata": {}, + "outputs": [], + "source": [ + "retry_parser = RetryWithErrorOutputParser.from_llm(parser=parser, llm=OpenAI(temperature=0))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "9c04f731", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Action(action='search', action_input='who is leo di caprios gf?')" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "retry_parser.parse_with_prompt(bad_response, prompt_value)" + ] + } + ], + "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 +} diff --git a/docs/modules/prompts/output_parsers/examples/structured.ipynb b/docs/modules/prompts/output_parsers/examples/structured.ipynb new file mode 100644 index 00000000..076cbada --- /dev/null +++ b/docs/modules/prompts/output_parsers/examples/structured.ipynb @@ -0,0 +1,209 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "91871002", + "metadata": {}, + "source": [ + "# Structured Output Parser\n", + "\n", + "While the Pydantic/JSON parser is more powerful, we initially experimented data structures having text fields only." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b492997a", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.output_parsers import StructuredOutputParser, ResponseSchema\n", + "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", + "from langchain.llms import OpenAI\n", + "from langchain.chat_models import ChatOpenAI" + ] + }, + { + "cell_type": "markdown", + "id": "09473dce", + "metadata": {}, + "source": [ + "Here we define the response schema we want to receive." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "432ac44a", + "metadata": {}, + "outputs": [], + "source": [ + "response_schemas = [\n", + " ResponseSchema(name=\"answer\", description=\"answer to the user's question\"),\n", + " ResponseSchema(name=\"source\", description=\"source used to answer the user's question, should be a website.\")\n", + "]\n", + "output_parser = StructuredOutputParser.from_response_schemas(response_schemas)" + ] + }, + { + "cell_type": "markdown", + "id": "7b92ce96", + "metadata": {}, + "source": [ + "We now get a string that contains instructions for how the response should be formatted, and we then insert that into our prompt." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "593cfc25", + "metadata": {}, + "outputs": [], + "source": [ + "format_instructions = output_parser.get_format_instructions()\n", + "prompt = PromptTemplate(\n", + " template=\"answer the users question as best as possible.\\n{format_instructions}\\n{question}\",\n", + " input_variables=[\"question\"],\n", + " partial_variables={\"format_instructions\": format_instructions}\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "0943e783", + "metadata": {}, + "source": [ + "We can now use this to format a prompt to send to the language model, and then parse the returned result." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "106f1ba6", + "metadata": {}, + "outputs": [], + "source": [ + "model = OpenAI(temperature=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "86d9d24f", + "metadata": {}, + "outputs": [], + "source": [ + "_input = prompt.format_prompt(question=\"what's the capital of france\")\n", + "output = model(_input.to_string())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "956bdc99", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'answer': 'Paris', 'source': 'https://en.wikipedia.org/wiki/Paris'}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "output_parser.parse(output)" + ] + }, + { + "cell_type": "markdown", + "id": "da639285", + "metadata": {}, + "source": [ + "And here's an example of using this in a chat model" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8f483d7d", + "metadata": {}, + "outputs": [], + "source": [ + "chat_model = ChatOpenAI(temperature=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f761cbf1", + "metadata": {}, + "outputs": [], + "source": [ + "prompt = ChatPromptTemplate(\n", + " messages=[\n", + " HumanMessagePromptTemplate.from_template(\"answer the users question as best as possible.\\n{format_instructions}\\n{question}\") \n", + " ],\n", + " input_variables=[\"question\"],\n", + " partial_variables={\"format_instructions\": format_instructions}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "edd73ae3", + "metadata": {}, + "outputs": [], + "source": [ + "_input = prompt.format_prompt(question=\"what's the capital of france\")\n", + "output = chat_model(_input.to_messages())" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a3c8b91e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'answer': 'Paris', 'source': 'https://en.wikipedia.org/wiki/Paris'}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "output_parser.parse(output.content)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/modules/prompts/output_parsers/getting_started.ipynb b/docs/modules/prompts/output_parsers/getting_started.ipynb new file mode 100644 index 00000000..a837c55d --- /dev/null +++ b/docs/modules/prompts/output_parsers/getting_started.ipynb @@ -0,0 +1,163 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "084ee2f0", + "metadata": {}, + "source": [ + "# Output Parsers\n", + "\n", + "Language models output text. But many times you may want to get more structured information than just text back. This is where output parsers come in.\n", + "\n", + "Output parsers are classes that help structure language model responses. There are two main methods an output parser must implement:\n", + "\n", + "- `get_format_instructions() -> str`: A method which returns a string containing instructions for how the output of a language model should be formatted.\n", + "- `parse(str) -> Any`: A method which takes in a string (assumed to be the response from a language model) and parses it into some structure.\n", + "\n", + "And then one optional one:\n", + "\n", + "- `parse_with_prompt(str) -> Any`: A method which takes in a string (assumed to be the response from a language model) and a prompt (assumed to the prompt that generated such a response) and parses it into some structure. The prompt is largely provided in the event the OutputParser wants to retry or fix the output in some way, and needs information from the prompt to do so.\n", + "\n", + "\n", + "Below we go over the main type of output parser, the `PydanticOutputParser`. See the `examples` folder for other options." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5f0c8a33", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\n", + "from langchain.llms import OpenAI\n", + "from langchain.chat_models import ChatOpenAI\n", + "\n", + "from langchain.output_parsers import PydanticOutputParser\n", + "from pydantic import BaseModel, Field, validator\n", + "from typing import List" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0a203100", + "metadata": {}, + "outputs": [], + "source": [ + "model_name = 'text-davinci-003'\n", + "temperature = 0.0\n", + "model = OpenAI(model_name=model_name, temperature=temperature)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "fd3cbfc5", + "metadata": {}, + "outputs": [], + "source": [ + "# Define your desired data structure.\n", + "class Joke(BaseModel):\n", + " setup: str = Field(description=\"question to set up a joke\")\n", + " punchline: str = Field(description=\"answer to resolve the joke\")\n", + " \n", + " # You can add custom validation logic easily with Pydantic.\n", + " @validator('setup')\n", + " def question_ends_with_question_mark(cls, field):\n", + " if field[-1] != '?':\n", + " raise ValueError(\"Badly formed question!\")\n", + " return field" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e03e1576", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up a parser + inject instructions into the prompt template.\n", + "parser = PydanticOutputParser(pydantic_object=Joke)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5ec3fa44", + "metadata": {}, + "outputs": [], + "source": [ + "prompt = PromptTemplate(\n", + " template=\"Answer the user query.\\n{format_instructions}\\n{query}\\n\",\n", + " input_variables=[\"query\"],\n", + " partial_variables={\"format_instructions\": parser.get_format_instructions()}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "00139255", + "metadata": {}, + "outputs": [], + "source": [ + "# And a query intented to prompt a language model to populate the data structure.\n", + "joke_query = \"Tell me a joke.\"\n", + "_input = prompt.format_prompt(query=joke_query)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f1aac756", + "metadata": {}, + "outputs": [], + "source": [ + "output = model(_input.to_string())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b3f16168", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "parser.parse(output)" + ] + } + ], + "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 +} diff --git a/docs/modules/prompts/output_parsers/how_to_guides.rst b/docs/modules/prompts/output_parsers/how_to_guides.rst new file mode 100644 index 00000000..7a28e36d --- /dev/null +++ b/docs/modules/prompts/output_parsers/how_to_guides.rst @@ -0,0 +1,8 @@ +How-To Guides +============= + +If you're new to the library, you may want to start with the `Quickstart <./getting_started.html>`_. + +The user guide here shows different types of output parsers. + + diff --git a/docs/modules/prompts/prompt_templates.rst b/docs/modules/prompts/prompt_templates.rst new file mode 100644 index 00000000..b3e4ae64 --- /dev/null +++ b/docs/modules/prompts/prompt_templates.rst @@ -0,0 +1,30 @@ +Prompt Templates +========================== + +.. note:: + `Conceptual Guide `_ + + +Language models take text as input - that text is commonly referred to as a prompt. +Typically this is not simply a hardcoded string but rather a combination of a template, some examples, and user input. +LangChain provides several classes and functions to make constructing and working with prompts easy. + +The following sections of documentation are provided: + +- `Getting Started <./prompt_templates/getting_started.html>`_: An overview of all the functionality LangChain provides for working with and constructing prompts. + +- `How-To Guides <./prompt_templates/how_to_guides.html>`_: A collection of how-to guides. These highlight how to accomplish various objectives with our prompt class. + +- `Reference <../../reference/prompts.html>`_: API reference documentation for all prompt classes. + + + +.. toctree:: + :maxdepth: 1 + :caption: Prompt Templates + :name: Prompt Templates + :hidden: + + ./prompt_templates/getting_started.md + ./prompt_templates/how_to_guides.rst + Reference<../../reference/prompts.rst> \ No newline at end of file diff --git a/docs/modules/prompts/examples/custom_prompt_template.ipynb b/docs/modules/prompts/prompt_templates/examples/custom_prompt_template.ipynb similarity index 98% rename from docs/modules/prompts/examples/custom_prompt_template.ipynb rename to docs/modules/prompts/prompt_templates/examples/custom_prompt_template.ipynb index 64c43f0f..6155b854 100644 --- a/docs/modules/prompts/examples/custom_prompt_template.ipynb +++ b/docs/modules/prompts/prompt_templates/examples/custom_prompt_template.ipynb @@ -5,7 +5,7 @@ "id": "c75efab3", "metadata": {}, "source": [ - "# Create a custom prompt template\n", + "# How to create a custom prompt template\n", "\n", "Let's suppose we want the LLM to generate English language explanations of a function given its name. To achieve this task, we will create a custom prompt template that takes in the function name as input, and formats the prompt template to provide the source code of the function.\n", "\n", @@ -161,7 +161,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.1" } }, "nbformat": 4, diff --git a/docs/modules/prompts/examples/example_prompt.json b/docs/modules/prompts/prompt_templates/examples/example_prompt.json similarity index 100% rename from docs/modules/prompts/examples/example_prompt.json rename to docs/modules/prompts/prompt_templates/examples/example_prompt.json diff --git a/docs/modules/prompts/examples/examples.json b/docs/modules/prompts/prompt_templates/examples/examples.json similarity index 100% rename from docs/modules/prompts/examples/examples.json rename to docs/modules/prompts/prompt_templates/examples/examples.json diff --git a/docs/modules/prompts/examples/examples.yaml b/docs/modules/prompts/prompt_templates/examples/examples.yaml similarity index 100% rename from docs/modules/prompts/examples/examples.yaml rename to docs/modules/prompts/prompt_templates/examples/examples.yaml diff --git a/docs/modules/prompts/examples/few_shot_examples.ipynb b/docs/modules/prompts/prompt_templates/examples/few_shot_examples.ipynb similarity index 99% rename from docs/modules/prompts/examples/few_shot_examples.ipynb rename to docs/modules/prompts/prompt_templates/examples/few_shot_examples.ipynb index f765d6c7..38b45020 100644 --- a/docs/modules/prompts/examples/few_shot_examples.ipynb +++ b/docs/modules/prompts/prompt_templates/examples/few_shot_examples.ipynb @@ -5,7 +5,7 @@ "id": "f8b01b97", "metadata": {}, "source": [ - "# Provide few shot examples to a prompt\n", + "# How to create a prompt template that uses few shot examples\n", "\n", "In this tutorial, we'll learn how to create a prompt template that uses few shot examples.\n", "\n", diff --git a/docs/modules/prompts/examples/few_shot_prompt.json b/docs/modules/prompts/prompt_templates/examples/few_shot_prompt.json similarity index 100% rename from docs/modules/prompts/examples/few_shot_prompt.json rename to docs/modules/prompts/prompt_templates/examples/few_shot_prompt.json diff --git a/docs/modules/prompts/examples/few_shot_prompt.yaml b/docs/modules/prompts/prompt_templates/examples/few_shot_prompt.yaml similarity index 100% rename from docs/modules/prompts/examples/few_shot_prompt.yaml rename to docs/modules/prompts/prompt_templates/examples/few_shot_prompt.yaml diff --git a/docs/modules/prompts/examples/few_shot_prompt_example_prompt.json b/docs/modules/prompts/prompt_templates/examples/few_shot_prompt_example_prompt.json similarity index 100% rename from docs/modules/prompts/examples/few_shot_prompt_example_prompt.json rename to docs/modules/prompts/prompt_templates/examples/few_shot_prompt_example_prompt.json diff --git a/docs/modules/prompts/examples/few_shot_prompt_examples_in.json b/docs/modules/prompts/prompt_templates/examples/few_shot_prompt_examples_in.json similarity index 100% rename from docs/modules/prompts/examples/few_shot_prompt_examples_in.json rename to docs/modules/prompts/prompt_templates/examples/few_shot_prompt_examples_in.json diff --git a/docs/modules/prompts/examples/few_shot_prompt_yaml_examples.yaml b/docs/modules/prompts/prompt_templates/examples/few_shot_prompt_yaml_examples.yaml similarity index 100% rename from docs/modules/prompts/examples/few_shot_prompt_yaml_examples.yaml rename to docs/modules/prompts/prompt_templates/examples/few_shot_prompt_yaml_examples.yaml diff --git a/docs/modules/prompts/examples/partial.ipynb b/docs/modules/prompts/prompt_templates/examples/partial.ipynb similarity index 99% rename from docs/modules/prompts/examples/partial.ipynb rename to docs/modules/prompts/prompt_templates/examples/partial.ipynb index f7a15b35..c4d03d16 100644 --- a/docs/modules/prompts/examples/partial.ipynb +++ b/docs/modules/prompts/prompt_templates/examples/partial.ipynb @@ -5,7 +5,7 @@ "id": "9355a547", "metadata": {}, "source": [ - "# Partial Prompt Templates\n", + "# How to work with partial Prompt Templates\n", "\n", "A prompt template is a class with a `.format` method which takes in a key-value map and returns a string (a prompt) to pass to the language model. Like other methods, it can make sense to \"partial\" a prompt template - eg pass in a subset of the required values, as to create a new prompt template which expects only the remaining subset of values.\n", "\n", diff --git a/docs/modules/prompts/examples/prompt_serialization.ipynb b/docs/modules/prompts/prompt_templates/examples/prompt_serialization.ipynb similarity index 99% rename from docs/modules/prompts/examples/prompt_serialization.ipynb rename to docs/modules/prompts/prompt_templates/examples/prompt_serialization.ipynb index f56f57ca..4f2ef340 100644 --- a/docs/modules/prompts/examples/prompt_serialization.ipynb +++ b/docs/modules/prompts/prompt_templates/examples/prompt_serialization.ipynb @@ -5,7 +5,7 @@ "id": "43fb16cb", "metadata": {}, "source": [ - "# Prompt Serialization\n", + "# How to serialize prompts\n", "\n", "It is often preferrable to store prompts not as python code but as files. This can make it easy to share, store, and version prompts. This notebook covers how to do that in LangChain, walking through all the different types of prompts and the different serialization options.\n", "\n", @@ -649,7 +649,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.9.1" }, "vscode": { "interpreter": { diff --git a/docs/modules/prompts/examples/simple_prompt.json b/docs/modules/prompts/prompt_templates/examples/simple_prompt.json similarity index 100% rename from docs/modules/prompts/examples/simple_prompt.json rename to docs/modules/prompts/prompt_templates/examples/simple_prompt.json diff --git a/docs/modules/prompts/examples/simple_prompt.yaml b/docs/modules/prompts/prompt_templates/examples/simple_prompt.yaml similarity index 100% rename from docs/modules/prompts/examples/simple_prompt.yaml rename to docs/modules/prompts/prompt_templates/examples/simple_prompt.yaml diff --git a/docs/modules/prompts/examples/simple_prompt_with_template_file.json b/docs/modules/prompts/prompt_templates/examples/simple_prompt_with_template_file.json similarity index 100% rename from docs/modules/prompts/examples/simple_prompt_with_template_file.json rename to docs/modules/prompts/prompt_templates/examples/simple_prompt_with_template_file.json diff --git a/docs/modules/prompts/examples/simple_template.txt b/docs/modules/prompts/prompt_templates/examples/simple_template.txt similarity index 100% rename from docs/modules/prompts/examples/simple_template.txt rename to docs/modules/prompts/prompt_templates/examples/simple_template.txt diff --git a/docs/modules/prompts/getting_started.md b/docs/modules/prompts/prompt_templates/getting_started.md similarity index 97% rename from docs/modules/prompts/getting_started.md rename to docs/modules/prompts/prompt_templates/getting_started.md index 1a20ae78..1c6649bb 100644 --- a/docs/modules/prompts/getting_started.md +++ b/docs/modules/prompts/prompt_templates/getting_started.md @@ -236,6 +236,6 @@ print(dynamic_prompt.format(input=long_string)) ``` -LangChain comes with a few example selectors that you can use. For more details on how to use them, see [Example Selectors](./examples/example_selectors.ipynb). +LangChain comes with a few example selectors that you can use. For more details on how to use them, see [Example Selectors](../example_selectors.rst). -You can create custom example selectors that select examples based on any criteria you want. For more details on how to do this, see [Creating a custom example selector](examples/custom_example_selector.ipynb). +You can create custom example selectors that select examples based on any criteria you want. For more details on how to do this, see [Creating a custom example selector](prompt_templates/examples/custom_example_selector.ipynb). diff --git a/docs/modules/prompts/prompt_templates/how_to_guides.rst b/docs/modules/prompts/prompt_templates/how_to_guides.rst new file mode 100644 index 00000000..39bdc823 --- /dev/null +++ b/docs/modules/prompts/prompt_templates/how_to_guides.rst @@ -0,0 +1,13 @@ +How-To Guides +============= + +If you're new to the library, you may want to start with the `Quickstart <./getting_started.html>`_. + +The user guide here shows more advanced workflows and how to use the library in different ways. + + +.. toctree:: + :maxdepth: 1 + :glob: + + ./examples/* diff --git a/docs/modules/utils.rst b/docs/modules/utils.rst deleted file mode 100644 index 70b563c4..00000000 --- a/docs/modules/utils.rst +++ /dev/null @@ -1,26 +0,0 @@ -Utils -========================== - -While LLMs are powerful on their own, they are more powerful when connected with other sources of knowledge or computation. -This section highlights those sources of knowledge or computation, -and goes over how to easily use them from within LangChain. - -The following sections of documentation are provided: - -- `Key Concepts <./utils/key_concepts.html>`_: A conceptual guide going over the various types of utils. - -- `How-To Guides <./utils/how_to_guides.html>`_: A collection of how-to guides. These highlight how to use various types of utils. - -- `Reference <../reference/utils.html>`_: API reference documentation for all Util classes. - - - -.. toctree:: - :maxdepth: 1 - :caption: Utils - :name: Utils - :hidden: - - ./utils/key_concepts.md - ./utils/how_to_guides.rst - Reference <../reference/utils.rst> diff --git a/docs/modules/utils/how_to_guides.rst b/docs/modules/utils/how_to_guides.rst deleted file mode 100644 index 3fa1ccb8..00000000 --- a/docs/modules/utils/how_to_guides.rst +++ /dev/null @@ -1,30 +0,0 @@ -Generic Utilities -================= - -There are a lot of different utilities that LangChain provides integrations for -These guides go over how to use them. -The utilities listed here are all generic utilities. - -`Bash <./examples/bash.html>`_: How to use a bash wrapper to execute bash commands. - -`Python REPL <./examples/python.html>`_: How to use a Python wrapper to execute python commands. - -`Requests <./examples/requests.html>`_: How to use a requests wrapper to interact with the web. - -`Google Search <./examples/google_search.html>`_: How to use the google search wrapper to search the web. - -`SerpAPI <./examples/serpapi.html>`_: How to use the SerpAPI wrapper to search the web. - -`SearxNG Search API <./examples/searx_search.html>`_: Hot to use the SearxNG meta search wrapper to search the web. - -`Bing Search <./examples/bing_search.html>`_: How to use the Bing search wrapper to search the web. - -`Wolfram Alpha <./examples/wolfram_alpha.html>`_: How to use the Wolfram Alpha wrapper to interact with Wolfram Alpha. - - -.. toctree:: - :maxdepth: 1 - :glob: - :hidden: - - ./examples/* \ No newline at end of file diff --git a/docs/modules/utils/key_concepts.md b/docs/modules/utils/key_concepts.md deleted file mode 100644 index 7b2e3d37..00000000 --- a/docs/modules/utils/key_concepts.md +++ /dev/null @@ -1,35 +0,0 @@ -# Key Concepts - -## Python REPL - -Sometimes, for complex calculations, rather than have an LLM generate the answer directly, -it can be better to have the LLM generate code to calculate the answer, and then run that code to get the answer. -In order to easily do that, we provide a simple Python REPL to execute commands in. -This interface will only return things that are printed - -therefore, if you want to use it to calculate an answer, make sure to have it print out the answer. - -## Bash - -It can often be useful to have an LLM generate bash commands, and then run them. -A common use case for this is letting the LLM interact with your local file system. -We provide an easy component to execute bash commands. - -## Requests Wrapper - -The web contains a lot of information that LLMs do not have access to. -In order to easily let LLMs interact with that information, -we provide a wrapper around the Python Requests module that takes in a URL and fetches data from that URL. - -## Google Search - -This uses the official Google Search API to look up information on the web. - -## SerpAPI - -This uses SerpAPI, a third party search API engine, to interact with Google Search. - -## Searx Search - -This uses the Searx (SearxNG fork) meta search engine API to lookup information -on the web. It supports 139 search engines and is easy to self-host -which makes it a good choice for privacy-conscious users. diff --git a/docs/use_cases/agents.md b/docs/use_cases/agents.md deleted file mode 100644 index b30ea5b7..00000000 --- a/docs/use_cases/agents.md +++ /dev/null @@ -1,12 +0,0 @@ -# Agents - -Agents are systems that use a language model to interact with other tools. -These can be used to do more grounded question/answering, interact with APIs, or even take actions. -These agents can be used to power the next generation of personal assistants - -systems that intelligently understand what you mean, and then can take actions to help you accomplish your goal. - -Agents are a core use of LangChain - so much so that there is a whole module dedicated to them. -Therefore, we recommend that you check out that documentation for detailed instruction on how to work -with them. - -- [Agent Documentation](../modules/agents.rst) diff --git a/docs/use_cases/apis.md b/docs/use_cases/apis.md new file mode 100644 index 00000000..cd459828 --- /dev/null +++ b/docs/use_cases/apis.md @@ -0,0 +1,24 @@ +# Interacting with APIs + +.. note:: + `Conceptual Guide `_ + + +Lots of data and information is stored behind APIs. +This page covers all resources available in LangChain for working with APIs. + +## Chains + +If you are just getting started, and you have relatively apis, you should get started with chains. +Chains are a sequence of predetermined steps, so they are good to get started with as they give you more control and let you +understand what is happening better. + +- [API Chain](../modules/chains/examples/api.ipynb) + +## Agents + +Agents are more complex, and involve multiple queries to the LLM to understand what to do. +The downside of agents are that you have less control. The upside is that they are more powerful, +which allows you to use them on larger and more complex schemas. + +- [OpenAPI Agent](../modules/agents/toolkits/examples/openapi.ipynb) diff --git a/docs/use_cases/chatbots.md b/docs/use_cases/chatbots.md index e2196b36..2a735103 100644 --- a/docs/use_cases/chatbots.md +++ b/docs/use_cases/chatbots.md @@ -1,15 +1,19 @@ # Chatbots +.. note:: + `Conceptual Guide `_ + + Since language models are good at producing text, that makes them ideal for creating chatbots. Aside from the base prompts/LLMs, an important concept to know for Chatbots is `memory`. Most chat based applications rely on remembering what happened in previous interactions, which is `memory` is designed to help with. The following resources exist: -- [ChatGPT Clone](../modules/memory/examples/chatgpt_clone.ipynb): A notebook walking through how to recreate a ChatGPT-like experience with LangChain. +- [ChatGPT Clone](../modules/agents/agent_executors/examples/chatgpt_clone.ipynb): A notebook walking through how to recreate a ChatGPT-like experience with LangChain. - [Conversation Memory](../modules/memory/getting_started.ipynb): A notebook walking through how to use different types of conversational memory. -- [Conversation Agent](../modules/memory/examples/conversational_agent.ipynb): A notebook walking through how to create an agent optimized for conversation. +- [Conversation Agent](../modules/agents/agents/examples/conversational_agent.ipynb): A notebook walking through how to create an agent optimized for conversation. Additional related resources include: -- [Memory Key Concepts](../modules/memory/key_concepts.md): Explanation of key concepts related to memory. +- [Memory Key Concepts](../modules/memory.rst): Explanation of key concepts related to memory. - [Memory Examples](../modules/memory/how_to_guides.rst): A collection of how-to examples for working with memory. diff --git a/docs/use_cases/combine_docs.md b/docs/use_cases/combine_docs.md deleted file mode 100644 index 604c34d8..00000000 --- a/docs/use_cases/combine_docs.md +++ /dev/null @@ -1,96 +0,0 @@ -# Data Augmented Generation - -## Overview - -Language models are trained on large amounts of unstructured data, which makes them fantastic at general purpose text generation. However, there are many instances where you may want the language model to generate text based not on generic data but rather on specific data. Some common examples of this include: - -- Summarization of a specific piece of text (a website, a private document, etc.) -- Question answering over a specific piece of text (a website, a private document, etc.) -- Question answering over multiple pieces of text (multiple websites, multiple private documents, etc.) -- Using the results of some external call to an API (results from a SQL query, etc.) - -All of these examples are instances when you do not want the LLM to generate text based solely on the data it was trained over, but rather you want it to incorporate other external data in some way. At a high level, this process can be broken down into two steps: - -1. Fetching: Fetching the relevant data to include. -2. Augmenting: Passing the data in as context to the LLM. - -This guide is intended to provide an overview of how to do this. This includes an overview of the literature, as well as common tools, abstractions and chains for doing this. - -## Related Literature -There are a lot of related papers in this area. Most of them are focused on end-to-end methods that optimize the fetching of the relevant data as well as passing it in as context. These are a few of the papers that are particularly relevant: - -**[RAG](https://arxiv.org/abs/2005.11401):** Retrieval Augmented Generation. -This paper introduces RAG models where the parametric memory is a pre-trained seq2seq model and the non-parametric memory is a dense vector index of Wikipedia, accessed with a pre-trained neural retriever. - -**[REALM](https://arxiv.org/abs/2002.08909):** Retrieval-Augmented Language Model Pre-Training. -To capture knowledge in a more modular and interpretable way, this paper augments language model pre-training with a latent knowledge retriever, which allows the model to retrieve and attend over documents from a large corpus such as Wikipedia, used during pre-training, fine-tuning and inference. - -**[HayStack](https://haystack.deepset.ai/):** This is not a paper, but rather an open source library aimed at semantic search, question answering, summarization, and document ranking for a wide range of NLP applications. The underpinnings of this library are focused on the same `fetching` and `augmenting` concepts discussed here, and incorporate some methods in the above papers. - -These papers/open-source projects are centered around retrieval of documents, which is important for question-answering tasks over a large corpus of documents (which is how they are evaluated). However, we use the terminology of `Data Augmented Generation` to highlight that retrieval from some document store is only one possible way of fetching relevant data to include. Other methods to fetch relevant data could involve hitting an API, querying a database, or just working with user provided data (eg a specific document that they want to summarize). - -Let's now deep dive on the two steps involved: fetching and augmenting. - -## Fetching -There are many ways to fetch relevant data to pass in as context to a LM, and these methods largely depend -on the use case. - -**User provided:** In some cases, the user may provide the relevant data, and no algorithm for fetching is needed. -An example of this is for summarization of specific documents: the user will provide the document to be summarized, -and task the language model with summarizing it. - -**Document Retrieval:** One of the more common use cases involves fetching relevant documents or pieces of text from -a large corpus of data. A common example of this is question answering over a private collection of documents. - -**API Querying:** Another common way to fetch data is from an API query. One example of this is WebGPT like system, -where you first query Google (or another search API) for relevant information, and then those results are used in -the generation step. Another example could be querying a structured database (like SQL) and then using a language model -to synthesize those results. - -There are two big issues to deal with in fetching: - -1. Fetching small enough pieces of information -2. Not fetching too many pieces of information (e.g. fetching only the most relevant pieces) - -### Text Splitting -One big issue with all of these methods is how to make sure you are working with pieces of text that are not too large. -This is important because most language models have a context length, and so you cannot (yet) just pass a -large document in as context. Therefore, it is important to not only fetch relevant data but also make sure it is in -small enough chunks. - -LangChain provides some utilities to help with splitting up larger pieces of data. This comes in the form of the TextSplitter class. -The class takes in a document and splits it up into chunks, with several parameters that control the -size of the chunks as well as the overlap in the chunks (important for maintaining context). -See [this walkthrough](../modules/indexes/examples/textsplitter.ipynb) for more information. - -### Relevant Documents -A second large issue related fetching data is to make sure you are not fetching too many documents, and are only fetching -the documents that are relevant to the query/question at hand. There are a few ways to deal with this. - -One concrete example of this is vector stores for document retrieval, often used for semantic search or question answering. -With this method, larger documents are split up into -smaller chunks and then each chunk of text is passed to an embedding function which creates an embedding for that piece of text. -Those are embeddings are then stored in a database. When a new search query or question comes in, an embedding is -created for that query/question and then documents with embeddings most similar to that embedding are fetched. -Examples of vector database companies include [Pinecone](https://www.pinecone.io/) and [Weaviate](https://weaviate.io/). - -Although this is perhaps the most common way of document retrieval, people are starting to think about alternative -data structures and indexing techniques specifically for working with language models. For a leading example of this, -check out [LlamaIndex](https://github.com/jerryjliu/llama_index) - a collection of data structures created by and optimized -for language models. - -## Augmenting -So you've fetched your relevant data - now what? How do you pass them to the language model in a format it can understand? -For a detailed overview of the different ways of doing so, and the tradeoffs between them, please see -[this documentation](../modules/indexes/combine_docs.md) - -## Use Cases -LangChain supports the above three methods of augmenting LLMs with external data. -These methods can be used to underpin several common use cases, and they are discussed below. -For all three of these use cases, all three methods are supported. -It is important to note that a large part of these implementations is the prompts -that are used. We provide default prompts for all three use cases, but these can be configured. -This is in case you discover a prompt that works better for your specific application. - -- [Question-Answering](question_answering.md) -- [Summarization](summarization.md) diff --git a/docs/use_cases/evaluation.rst b/docs/use_cases/evaluation.rst index 49c53b55..3e152516 100644 --- a/docs/use_cases/evaluation.rst +++ b/docs/use_cases/evaluation.rst @@ -1,6 +1,10 @@ Evaluation ============== +.. note:: + `Conceptual Guide `_ + + This section of documentation covers how we approach and think about evaluation in LangChain. Both evaluation of internal chains/agents, but also how we would recommend people building on top of LangChain approach evaluation. diff --git a/docs/use_cases/extraction.md b/docs/use_cases/extraction.md index a6dfe286..aa252201 100644 --- a/docs/use_cases/extraction.md +++ b/docs/use_cases/extraction.md @@ -1,5 +1,9 @@ # Extraction +.. note:: + `Conceptual Guide `_ + + Most APIs and databases still deal with structured information. Therefore, in order to better work with those, it can be useful to extract structured information from text. Examples of this include: @@ -8,7 +12,7 @@ Examples of this include: - Extracting multiple rows to insert into a database from a long document - Extracting the correct API parameters from a user query -This work is extremely related to [output parsing](../modules/prompts/examples/output_parsers.ipynb). +This work is extremely related to [output parsing](../modules/prompts/output_parsers.rst). Output parsers are responsible for instructing the LLM to respond in a specific format. In this case, the output parsers specify the format of the data you would like to extract from the document. Then, in addition to the output format instructions, the prompt should also contain the data you would like to extract information from. diff --git a/docs/use_cases/generate_examples.ipynb b/docs/use_cases/generate_examples.ipynb deleted file mode 100644 index 540fb472..00000000 --- a/docs/use_cases/generate_examples.ipynb +++ /dev/null @@ -1,157 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "f5d249ee", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "# Generate Examples\n", - "\n", - "This notebook shows how to use LangChain to generate more examples similar to the ones you already have." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "1685fa2f", - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "from langchain.llms.openai import OpenAI\n", - "from langchain.example_generator import generate_example\n", - "from langchain.prompts import PromptTemplate" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "334ef4f7", - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# Use examples from ReAct\n", - "examples = [\n", - " {\n", - " \"question\": \"What is the elevation range for the area that the eastern sector of the Colorado orogeny extends into?\",\n", - " \"answer\": \"Thought 1: I need to search Colorado orogeny, find the area that the eastern sector of the Colorado orogeny extends into, then find the elevation range of that area.\\nAction 1: Search[Colorado orogeny]\\nObservation 1: The Colorado orogeny was an episode of mountain building (an orogeny) in Colorado and surrounding areas.\\nThought 2: It does not mention the eastern sector. So I need to look up eastern sector.\\nAction 2: Lookup[eastern sector]\\nObservation 2: (Result 1 / 1) The eastern sector extends into the High Plains and is called the Central Plains orogeny.\\nThought 3: The eastern sector of Colorado orogeny extends into the High Plains. So I need to search High Plains and find its elevation range.\\nAction 3: Search[High Plains]\\nObservation 3: High Plains refers to one of two distinct land regions\\nThought 4: I need to instead search High Plains (United States).\\nAction 4: Search[High Plains (United States)]\\nObservation 4: The High Plains are a subregion of the Great Plains. From east to west, the High Plains rise in elevation from around 1,800 to 7,000 ft (550 to 2,130 m).[3]\\nThought 5: High Plains rise in elevation from around 1,800 to 7,000 ft, so the answer is 1,800 to 7,000 ft.\\nAction 5: Finish[1,800 to 7,000 ft]\"\n", - " },\n", - " {\n", - " \"question\": \"Musician and satirist Allie Goertz wrote a song about the \\\"The Simpsons\\\" character Milhouse, who Matt Groening named after who?\",\n", - " \"answer\": \"Thought 1: The question simplifies to \\\"The Simpsons\\\" character Milhouse is named after who. I only need to search Milhouse and find who it is named after.\\nAction 1: Search[Milhouse]\\nObservation 1: Milhouse Mussolini Van Houten is a recurring character in the Fox animated television series The Simpsons voiced by Pamela Hayden and created by Matt Groening.\\nThought 2: The paragraph does not tell who Milhouse is named after, maybe I can look up \\\"named after\\\".\\nAction 2: Lookup[named after]\\nObservation 2: (Result 1 / 1) Milhouse was named after U.S. president Richard Nixon, whose middle name was Milhous.\\nThought 3: Milhouse was named after U.S. president Richard Nixon, so the answer is Richard Nixon.\\nAction 3: Finish[Richard Nixon]\"\n", - " },\n", - " {\n", - " \"question\": \"Which documentary is about Finnish rock groups, Adam Clayton Powell or The Saimaa Gesture?\",\n", - " \"answer\": \"Thought 1: I need to search Adam Clayton Powell and The Saimaa Gesture, and find which documentary is about Finnish rock groups.\\nAction 1: Search[Adam Clayton Powell]\\nObservation 1 Could not find [Adam Clayton Powell]. Similar: [’Adam Clayton Powell III’, ’Seventh Avenue (Manhattan)’, ’Adam Clayton Powell Jr. State Office Building’, ’Isabel Washington Powell’, ’Adam Powell’, ’Adam Clayton Powell (film)’, ’Giancarlo Esposito’].\\nThought 2: To find the documentary, I can search Adam Clayton Powell (film).\\nAction 2: Search[Adam Clayton Powell (film)]\\nObservation 2: Adam Clayton Powell is a 1989 American documentary film directed by Richard Kilberg. The film is about the rise and fall of influential African-American politician Adam Clayton Powell Jr.[3][4] It was later aired as part of the PBS series The American Experience.\\nThought 3: Adam Clayton Powell (film) is a documentary about an African-American politician, not Finnish rock groups. So the documentary about Finnish rock groups must instead be The Saimaa Gesture.\\nAction 3: Finish[The Saimaa Gesture]\"\n", - " },\n", - " {\n", - " \"question\": \"What profession does Nicholas Ray and Elia Kazan have in common?\",\n", - " \"answer\": \"Thought 1: I need to search Nicholas Ray and Elia Kazan, find their professions, then find the profession they have in common.\\nAction 1: Search[Nicholas Ray]\\nObservation 1: Nicholas Ray (born Raymond Nicholas Kienzle Jr., August 7, 1911 - June 16, 1979) was an American film director, screenwriter, and actor best known for the 1955 film Rebel Without a Cause.\\nThought 2: Professions of Nicholas Ray are director, screenwriter, and actor. I need to search Elia Kazan next and find his professions.\\nAction 2: Search[Elia Kazan]\\nObservation 2: Elia Kazan was an American film and theatre director, producer, screenwriter and actor.\\nThought 3: Professions of Elia Kazan are director, producer, screenwriter, and actor. So profession Nicholas Ray and Elia Kazan have in common is director, screenwriter, and actor.\\nAction 3: Finish[director, screenwriter, actor]\"\n", - " },\n", - " {\n", - " \"question\": \"Which magazine was started first Arthur’s Magazine or First for Women?\",\n", - " \"answer\": \"Thought 1: I need to search Arthur’s Magazine and First for Women, and find which was started first.\\nAction 1: Search[Arthur’s Magazine]\\nObservation 1: Arthur’s Magazine (1844-1846) was an American literary periodical published in Philadelphia in the 19th century.\\nThought 2: Arthur’s Magazine was started in 1844. I need to search First for Women next.\\nAction 2: Search[First for Women]\\nObservation 2: First for Women is a woman’s magazine published by Bauer Media Group in the USA.[1] The magazine was started in 1989.\\nThought 3: First for Women was started in 1989. 1844 (Arthur’s Magazine) < 1989 (First for Women), so Arthur’s Magazine was started first.\\nAction 3: Finish[Arthur’s Magazine]\"\n", - " },\n", - " {\n", - " \"question\": \"Were Pavel Urysohn and Leonid Levin known for the same type of work?\",\n", - " \"answer\": \"Thought 1: I need to search Pavel Urysohn and Leonid Levin, find their types of work, then find if they are the same.\\nAction 1: Search[Pavel Urysohn]\\nObservation 1: Pavel Samuilovich Urysohn (February 3, 1898 - August 17, 1924) was a Soviet mathematician who is best known for his contributions in dimension theory.\\nThought 2: Pavel Urysohn is a mathematician. I need to search Leonid Levin next and find its type of work.\\nAction 2: Search[Leonid Levin]\\nObservation 2: Leonid Anatolievich Levin is a Soviet-American mathematician and computer scientist.\\nThought 3: Leonid Levin is a mathematician and computer scientist. So Pavel Urysohn and Leonid Levin have the same type of work.\\nAction 3: Finish[yes]\"\n", - " }\n", - "]\n", - "example_template = PromptTemplate(template=\"Question: {question}\\n{answer}\", input_variables=[\"question\", \"answer\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "a7bd36bc", - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "new_example = generate_example(examples, OpenAI(), example_template)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "e1efb008", - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "['',\n", - " '',\n", - " 'Question: What is the difference between the Illinois and Missouri orogeny?',\n", - " 'Thought 1: I need to search Illinois and Missouri orogeny, and find the difference between them.',\n", - " 'Action 1: Search[Illinois orogeny]',\n", - " 'Observation 1: The Illinois orogeny is a hypothesized orogenic event that occurred in the Late Paleozoic either in the Pennsylvanian or Permian period.',\n", - " 'Thought 2: The Illinois orogeny is a hypothesized orogenic event. I need to search Missouri orogeny next and find its details.',\n", - " 'Action 2: Search[Missouri orogeny]',\n", - " 'Observation 2: The Missouri orogeny was a major tectonic event that occurred in the late Pennsylvanian and early Permian period (about 300 million years ago).',\n", - " 'Thought 3: The Illinois orogeny is hypothesized and occurred in the Late Paleozoic and the Missouri orogeny was a major tectonic event that occurred in the late Pennsylvanian and early Permian period. So the difference between the Illinois and Missouri orogeny is that the Illinois orogeny is hypothesized and occurred in the Late Paleozoic while the Missouri orogeny was a major']" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "new_example.split('\\n')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1ed01ba2", - "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.9" - }, - "vscode": { - "interpreter": { - "hash": "b1677b440931f40d89ef8be7bf03acb108ce003de0ac9b18e8d43753ea2e7103" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/use_cases/personal_assistants.md b/docs/use_cases/personal_assistants.md new file mode 100644 index 00000000..7e9b2c80 --- /dev/null +++ b/docs/use_cases/personal_assistants.md @@ -0,0 +1,19 @@ +# Personal Assistants + +.. note:: + `Conceptual Guide `_ + + +We use "personal assistant" here in a very broad sense. +Personal assistants have a few characteristics: + +- They can interact with the outside world +- They have knowledge of your data +- They remember your interactions + +Really all of the functionality in LangChain is relevant for building a personal assistant. +Highlighting specific parts: + +- [Agent Documentation](../modules/agents.rst) (for interacting with the outside world) +- [Index Documentation](../modules/indexes.rst) (for giving them knowledge of your data) +- [Memory](../modules/memory.rst) (for helping them remember interactions) diff --git a/docs/use_cases/question_answering.md b/docs/use_cases/question_answering.md index 4632b5b8..56c62665 100644 --- a/docs/use_cases/question_answering.md +++ b/docs/use_cases/question_answering.md @@ -1,7 +1,11 @@ -# Question Answering +# Question Answering over Docs + +.. note:: + `Conceptual Guide `_ + Question answering in this context refers to question answering over your document data. -For question answering over other types of data, like [SQL databases](../modules/chains/examples/sqlite.html) or [APIs](../modules/chains/examples/api.html), please see [here](../modules/chains/utility_how_to.html) +For question answering over other types of data, please see other sources documentation like [SQL database Question Answering](./tabular.md) or [Interacting with APIs](./apis.md). For question answering over many documents, you almost always want to create an index over the data. This can be used to smartly access the most relevant documents for a given question, allowing you to avoid having to pass all the documents to the LLM (saving you time and money). @@ -72,4 +76,3 @@ The following resources exist: Additional related resources include: - [Utilities for working with Documents](/modules/utils/how_to_guides.rst): Guides on how to use several of the utilities which will prove helpful for this task, including Text Splitters (for splitting up long documents) and Embeddings & Vectorstores (useful for the above Vector DB example). - [CombineDocuments Chains](/modules/indexes/combine_docs.md): A conceptual overview of specific types of chains by which you can accomplish this task. -- [Data Augmented Generation](combine_docs.md): An overview of data augmented generation, which is the general concept of combining external data with LLMs (of which this is a subset). diff --git a/docs/use_cases/summarization.md b/docs/use_cases/summarization.md index 00f96bb5..2eed59e9 100644 --- a/docs/use_cases/summarization.md +++ b/docs/use_cases/summarization.md @@ -1,5 +1,9 @@ # Summarization +.. note:: + `Conceptual Guide `_ + + Summarization involves creating a smaller summary of multiple longer documents. This can be useful for distilling long documents into the core pieces of information. @@ -12,9 +16,7 @@ chain.run(docs) ``` The following resources exist: -- [Summarization Notebook](../modules/indexes/chain_examples/summarize.ipynb): A notebook walking through how to accomplish this task. +- [Summarization Notebook](../modules/chains/index_examples/summarize.ipynb): A notebook walking through how to accomplish this task. Additional related resources include: - [Utilities for working with Documents](../reference/utils.rst): Guides on how to use several of the utilities which will prove helpful for this task, including Text Splitters (for splitting up long documents). -- [CombineDocuments Chains](../modules/indexes/combine_docs.md): A conceptual overview of specific types of chains by which you can accomplish this task. -- [Data Augmented Generation](./combine_docs.md): An overview of data augmented generation, which is the general concept of combining external data with LLMs (of which this is a subset). diff --git a/docs/use_cases/tabular.md b/docs/use_cases/tabular.md index c4dd0dd2..7ccf5ac5 100644 --- a/docs/use_cases/tabular.md +++ b/docs/use_cases/tabular.md @@ -1,12 +1,16 @@ # Querying Tabular Data +.. note:: + `Conceptual Guide `_ + + Lots of data and information is stored in tabular data, whether it be csvs, excel sheets, or SQL tables. This page covers all resources available in LangChain for working with data in this format. ## Document Loading If you have text data stored in a tabular format, you may want to load the data into a Document and then index it as you would -other text/unstructured data. For this, you should use a document loader like the [CSVLoader](../modules/document_loaders/examples/csv.ipynb) -and then you should [create an index](../modules/indexes.rst) over that data, and [query it that way](../modules/indexes/chain_examples/vector_db_qa.ipynb). +other text/unstructured data. For this, you should use a document loader like the [CSVLoader](../modules/indexes/document_loaders/examples/csv.ipynb) +and then you should [create an index](../modules/indexes.rst) over that data, and [query it that way](../modules/chains/index_examples/vector_db_qa.ipynb). ## Querying If you have more numeric tabular data, or have a large amount of data and don't want to index it, you should get started @@ -26,6 +30,6 @@ Agents are more complex, and involve multiple queries to the LLM to understand w The downside of agents are that you have less control. The upside is that they are more powerful, which allows you to use them on larger databases and more complex schemas. -- [SQL Agent](../modules/agents/agent_toolkits/sql_database.ipynb) -- [Pandas Agent](../modules/agents/agent_toolkits/pandas.ipynb) -- [CSV Agent](../modules/agents/agent_toolkits/csv.ipynb) +- [SQL Agent](../modules/agents/toolkits/examples/sql_database.ipynb) +- [Pandas Agent](../modules/agents/toolkits/examples/pandas.ipynb) +- [CSV Agent](../modules/agents/toolkits/examples/csv.ipynb) diff --git a/tests/unit_tests/prompts/test_loading.py b/tests/unit_tests/prompts/test_loading.py index 16d60bde..717eecb8 100644 --- a/tests/unit_tests/prompts/test_loading.py +++ b/tests/unit_tests/prompts/test_loading.py @@ -15,7 +15,7 @@ def change_directory() -> Iterator: """Change the working directory to the right folder.""" origin = Path().absolute() try: - os.chdir("docs/modules/prompts/examples") + os.chdir("docs/modules/prompts/prompt_templates/examples") yield finally: os.chdir(origin)