langchain 0.3.26__py3-none-any.whl → 0.3.27__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of langchain might be problematic. Click here for more details.
- langchain/__init__.py +110 -96
- langchain/_api/__init__.py +2 -2
- langchain/_api/deprecation.py +3 -3
- langchain/_api/module_import.py +51 -46
- langchain/_api/path.py +1 -1
- langchain/adapters/openai.py +8 -8
- langchain/agents/__init__.py +15 -12
- langchain/agents/agent.py +160 -133
- langchain/agents/agent_iterator.py +31 -14
- langchain/agents/agent_toolkits/__init__.py +7 -6
- langchain/agents/agent_toolkits/ainetwork/toolkit.py +1 -1
- langchain/agents/agent_toolkits/amadeus/toolkit.py +1 -1
- langchain/agents/agent_toolkits/azure_cognitive_services.py +1 -1
- langchain/agents/agent_toolkits/clickup/toolkit.py +1 -1
- langchain/agents/agent_toolkits/conversational_retrieval/openai_functions.py +6 -4
- langchain/agents/agent_toolkits/csv/__init__.py +4 -2
- langchain/agents/agent_toolkits/file_management/__init__.py +1 -1
- langchain/agents/agent_toolkits/file_management/toolkit.py +1 -1
- langchain/agents/agent_toolkits/github/toolkit.py +9 -9
- langchain/agents/agent_toolkits/gitlab/toolkit.py +1 -1
- langchain/agents/agent_toolkits/json/base.py +1 -1
- langchain/agents/agent_toolkits/multion/toolkit.py +1 -1
- langchain/agents/agent_toolkits/office365/toolkit.py +1 -1
- langchain/agents/agent_toolkits/openapi/base.py +1 -1
- langchain/agents/agent_toolkits/openapi/planner.py +2 -2
- langchain/agents/agent_toolkits/openapi/planner_prompt.py +10 -10
- langchain/agents/agent_toolkits/openapi/prompt.py +1 -1
- langchain/agents/agent_toolkits/openapi/toolkit.py +1 -1
- langchain/agents/agent_toolkits/pandas/__init__.py +4 -2
- langchain/agents/agent_toolkits/playwright/__init__.py +1 -1
- langchain/agents/agent_toolkits/playwright/toolkit.py +1 -1
- langchain/agents/agent_toolkits/powerbi/base.py +1 -1
- langchain/agents/agent_toolkits/powerbi/chat_base.py +1 -1
- langchain/agents/agent_toolkits/powerbi/prompt.py +2 -2
- langchain/agents/agent_toolkits/powerbi/toolkit.py +1 -1
- langchain/agents/agent_toolkits/python/__init__.py +4 -2
- langchain/agents/agent_toolkits/spark/__init__.py +4 -2
- langchain/agents/agent_toolkits/spark_sql/base.py +1 -1
- langchain/agents/agent_toolkits/spark_sql/toolkit.py +1 -1
- langchain/agents/agent_toolkits/sql/prompt.py +1 -1
- langchain/agents/agent_toolkits/sql/toolkit.py +1 -1
- langchain/agents/agent_toolkits/vectorstore/base.py +2 -2
- langchain/agents/agent_toolkits/vectorstore/prompt.py +2 -4
- langchain/agents/agent_toolkits/vectorstore/toolkit.py +12 -11
- langchain/agents/agent_toolkits/xorbits/__init__.py +4 -2
- langchain/agents/agent_toolkits/zapier/toolkit.py +1 -1
- langchain/agents/agent_types.py +6 -6
- langchain/agents/chat/base.py +6 -12
- langchain/agents/chat/output_parser.py +9 -6
- langchain/agents/chat/prompt.py +3 -4
- langchain/agents/conversational/base.py +9 -5
- langchain/agents/conversational/output_parser.py +4 -2
- langchain/agents/conversational/prompt.py +2 -3
- langchain/agents/conversational_chat/base.py +7 -5
- langchain/agents/conversational_chat/output_parser.py +9 -11
- langchain/agents/conversational_chat/prompt.py +5 -6
- langchain/agents/format_scratchpad/__init__.py +3 -3
- langchain/agents/format_scratchpad/log_to_messages.py +1 -1
- langchain/agents/format_scratchpad/openai_functions.py +8 -6
- langchain/agents/format_scratchpad/tools.py +5 -3
- langchain/agents/format_scratchpad/xml.py +33 -2
- langchain/agents/initialize.py +16 -8
- langchain/agents/json_chat/base.py +18 -18
- langchain/agents/json_chat/prompt.py +2 -3
- langchain/agents/load_tools.py +2 -1
- langchain/agents/loading.py +28 -18
- langchain/agents/mrkl/base.py +9 -4
- langchain/agents/mrkl/output_parser.py +17 -13
- langchain/agents/mrkl/prompt.py +1 -2
- langchain/agents/openai_assistant/base.py +80 -70
- langchain/agents/openai_functions_agent/base.py +46 -37
- langchain/agents/openai_functions_multi_agent/base.py +39 -26
- langchain/agents/openai_tools/base.py +8 -8
- langchain/agents/output_parsers/__init__.py +3 -3
- langchain/agents/output_parsers/json.py +6 -6
- langchain/agents/output_parsers/openai_functions.py +15 -7
- langchain/agents/output_parsers/openai_tools.py +9 -4
- langchain/agents/output_parsers/react_json_single_input.py +10 -5
- langchain/agents/output_parsers/react_single_input.py +15 -11
- langchain/agents/output_parsers/self_ask.py +3 -2
- langchain/agents/output_parsers/tools.py +18 -13
- langchain/agents/output_parsers/xml.py +99 -28
- langchain/agents/react/agent.py +4 -4
- langchain/agents/react/base.py +22 -17
- langchain/agents/react/output_parser.py +5 -6
- langchain/agents/react/textworld_prompt.py +0 -1
- langchain/agents/react/wiki_prompt.py +14 -15
- langchain/agents/schema.py +3 -2
- langchain/agents/self_ask_with_search/base.py +19 -15
- langchain/agents/self_ask_with_search/prompt.py +0 -1
- langchain/agents/structured_chat/base.py +14 -11
- langchain/agents/structured_chat/output_parser.py +16 -18
- langchain/agents/structured_chat/prompt.py +3 -4
- langchain/agents/tool_calling_agent/base.py +7 -6
- langchain/agents/tools.py +2 -2
- langchain/agents/utils.py +2 -3
- langchain/agents/xml/base.py +5 -5
- langchain/agents/xml/prompt.py +1 -2
- langchain/cache.py +12 -12
- langchain/callbacks/__init__.py +11 -11
- langchain/callbacks/aim_callback.py +2 -2
- langchain/callbacks/argilla_callback.py +1 -1
- langchain/callbacks/arize_callback.py +1 -1
- langchain/callbacks/arthur_callback.py +1 -1
- langchain/callbacks/base.py +7 -7
- langchain/callbacks/clearml_callback.py +1 -1
- langchain/callbacks/comet_ml_callback.py +1 -1
- langchain/callbacks/confident_callback.py +1 -1
- langchain/callbacks/context_callback.py +1 -1
- langchain/callbacks/flyte_callback.py +1 -1
- langchain/callbacks/human.py +2 -2
- langchain/callbacks/infino_callback.py +1 -1
- langchain/callbacks/labelstudio_callback.py +1 -1
- langchain/callbacks/llmonitor_callback.py +1 -1
- langchain/callbacks/manager.py +5 -5
- langchain/callbacks/mlflow_callback.py +2 -2
- langchain/callbacks/openai_info.py +1 -1
- langchain/callbacks/promptlayer_callback.py +1 -1
- langchain/callbacks/sagemaker_callback.py +1 -1
- langchain/callbacks/streaming_aiter.py +4 -1
- langchain/callbacks/streaming_aiter_final_only.py +5 -3
- langchain/callbacks/streaming_stdout_final_only.py +5 -3
- langchain/callbacks/streamlit/__init__.py +3 -2
- langchain/callbacks/streamlit/mutable_expander.py +1 -1
- langchain/callbacks/streamlit/streamlit_callback_handler.py +3 -3
- langchain/callbacks/tracers/__init__.py +1 -1
- langchain/callbacks/tracers/comet.py +1 -1
- langchain/callbacks/tracers/evaluation.py +1 -1
- langchain/callbacks/tracers/log_stream.py +1 -1
- langchain/callbacks/tracers/logging.py +1 -1
- langchain/callbacks/tracers/stdout.py +1 -1
- langchain/callbacks/trubrics_callback.py +1 -1
- langchain/callbacks/utils.py +4 -4
- langchain/callbacks/wandb_callback.py +1 -1
- langchain/callbacks/whylabs_callback.py +1 -1
- langchain/chains/api/base.py +36 -22
- langchain/chains/api/news_docs.py +1 -2
- langchain/chains/api/open_meteo_docs.py +1 -2
- langchain/chains/api/openapi/requests_chain.py +1 -1
- langchain/chains/api/openapi/response_chain.py +1 -1
- langchain/chains/api/podcast_docs.py +1 -2
- langchain/chains/api/prompt.py +1 -2
- langchain/chains/api/tmdb_docs.py +1 -2
- langchain/chains/base.py +88 -54
- langchain/chains/chat_vector_db/prompts.py +2 -3
- langchain/chains/combine_documents/__init__.py +1 -1
- langchain/chains/combine_documents/base.py +23 -10
- langchain/chains/combine_documents/map_reduce.py +38 -30
- langchain/chains/combine_documents/map_rerank.py +33 -20
- langchain/chains/combine_documents/reduce.py +47 -26
- langchain/chains/combine_documents/refine.py +26 -17
- langchain/chains/combine_documents/stuff.py +19 -12
- langchain/chains/constitutional_ai/base.py +4 -4
- langchain/chains/constitutional_ai/principles.py +22 -25
- langchain/chains/constitutional_ai/prompts.py +25 -28
- langchain/chains/conversation/base.py +5 -3
- langchain/chains/conversation/memory.py +5 -5
- langchain/chains/conversation/prompt.py +5 -5
- langchain/chains/conversational_retrieval/base.py +41 -20
- langchain/chains/conversational_retrieval/prompts.py +2 -3
- langchain/chains/elasticsearch_database/base.py +8 -9
- langchain/chains/elasticsearch_database/prompts.py +2 -3
- langchain/chains/ernie_functions/__init__.py +2 -2
- langchain/chains/example_generator.py +3 -1
- langchain/chains/flare/base.py +26 -12
- langchain/chains/graph_qa/cypher.py +2 -2
- langchain/chains/graph_qa/falkordb.py +1 -1
- langchain/chains/graph_qa/gremlin.py +1 -1
- langchain/chains/graph_qa/neptune_sparql.py +1 -1
- langchain/chains/graph_qa/prompts.py +2 -2
- langchain/chains/history_aware_retriever.py +2 -1
- langchain/chains/hyde/base.py +6 -5
- langchain/chains/hyde/prompts.py +5 -6
- langchain/chains/llm.py +77 -61
- langchain/chains/llm_bash/__init__.py +2 -1
- langchain/chains/llm_checker/base.py +7 -5
- langchain/chains/llm_checker/prompt.py +3 -4
- langchain/chains/llm_math/base.py +16 -9
- langchain/chains/llm_math/prompt.py +1 -2
- langchain/chains/llm_summarization_checker/base.py +9 -6
- langchain/chains/llm_symbolic_math/__init__.py +2 -1
- langchain/chains/loading.py +151 -95
- langchain/chains/mapreduce.py +4 -3
- langchain/chains/moderation.py +8 -9
- langchain/chains/natbot/base.py +8 -8
- langchain/chains/natbot/crawler.py +73 -76
- langchain/chains/natbot/prompt.py +2 -3
- langchain/chains/openai_functions/__init__.py +7 -7
- langchain/chains/openai_functions/base.py +13 -10
- langchain/chains/openai_functions/citation_fuzzy_match.py +12 -11
- langchain/chains/openai_functions/extraction.py +19 -19
- langchain/chains/openai_functions/openapi.py +35 -35
- langchain/chains/openai_functions/qa_with_structure.py +19 -12
- langchain/chains/openai_functions/tagging.py +2 -4
- langchain/chains/openai_tools/extraction.py +7 -8
- langchain/chains/qa_generation/base.py +4 -3
- langchain/chains/qa_generation/prompt.py +5 -5
- langchain/chains/qa_with_sources/base.py +14 -6
- langchain/chains/qa_with_sources/loading.py +16 -8
- langchain/chains/qa_with_sources/map_reduce_prompt.py +8 -9
- langchain/chains/qa_with_sources/refine_prompts.py +0 -1
- langchain/chains/qa_with_sources/retrieval.py +14 -5
- langchain/chains/qa_with_sources/stuff_prompt.py +6 -7
- langchain/chains/qa_with_sources/vector_db.py +17 -6
- langchain/chains/query_constructor/base.py +34 -33
- langchain/chains/query_constructor/ir.py +4 -4
- langchain/chains/query_constructor/parser.py +37 -32
- langchain/chains/query_constructor/prompt.py +5 -6
- langchain/chains/question_answering/chain.py +21 -10
- langchain/chains/question_answering/map_reduce_prompt.py +14 -14
- langchain/chains/question_answering/map_rerank_prompt.py +3 -3
- langchain/chains/question_answering/refine_prompts.py +2 -5
- langchain/chains/question_answering/stuff_prompt.py +5 -5
- langchain/chains/retrieval.py +1 -3
- langchain/chains/retrieval_qa/base.py +34 -27
- langchain/chains/retrieval_qa/prompt.py +1 -2
- langchain/chains/router/__init__.py +3 -3
- langchain/chains/router/base.py +24 -20
- langchain/chains/router/embedding_router.py +12 -8
- langchain/chains/router/llm_router.py +17 -16
- langchain/chains/router/multi_prompt.py +2 -2
- langchain/chains/router/multi_retrieval_qa.py +10 -5
- langchain/chains/sequential.py +30 -18
- langchain/chains/sql_database/prompt.py +14 -16
- langchain/chains/sql_database/query.py +6 -5
- langchain/chains/structured_output/__init__.py +1 -1
- langchain/chains/structured_output/base.py +75 -67
- langchain/chains/summarize/chain.py +11 -5
- langchain/chains/summarize/map_reduce_prompt.py +0 -1
- langchain/chains/summarize/stuff_prompt.py +0 -1
- langchain/chains/transform.py +5 -6
- langchain/chat_loaders/facebook_messenger.py +1 -1
- langchain/chat_loaders/langsmith.py +1 -1
- langchain/chat_loaders/utils.py +3 -3
- langchain/chat_models/__init__.py +20 -19
- langchain/chat_models/anthropic.py +1 -1
- langchain/chat_models/azureml_endpoint.py +1 -1
- langchain/chat_models/baidu_qianfan_endpoint.py +1 -1
- langchain/chat_models/base.py +160 -123
- langchain/chat_models/bedrock.py +1 -1
- langchain/chat_models/fake.py +1 -1
- langchain/chat_models/meta.py +1 -1
- langchain/chat_models/pai_eas_endpoint.py +1 -1
- langchain/chat_models/promptlayer_openai.py +1 -1
- langchain/chat_models/volcengine_maas.py +1 -1
- langchain/docstore/base.py +1 -1
- langchain/document_loaders/__init__.py +9 -9
- langchain/document_loaders/airbyte.py +3 -3
- langchain/document_loaders/assemblyai.py +1 -1
- langchain/document_loaders/azure_blob_storage_container.py +1 -1
- langchain/document_loaders/azure_blob_storage_file.py +1 -1
- langchain/document_loaders/baiducloud_bos_file.py +1 -1
- langchain/document_loaders/base.py +1 -1
- langchain/document_loaders/blob_loaders/__init__.py +1 -1
- langchain/document_loaders/blockchain.py +1 -1
- langchain/document_loaders/chatgpt.py +1 -1
- langchain/document_loaders/college_confidential.py +1 -1
- langchain/document_loaders/confluence.py +1 -1
- langchain/document_loaders/email.py +1 -1
- langchain/document_loaders/facebook_chat.py +1 -1
- langchain/document_loaders/markdown.py +1 -1
- langchain/document_loaders/notebook.py +1 -1
- langchain/document_loaders/org_mode.py +1 -1
- langchain/document_loaders/parsers/__init__.py +1 -1
- langchain/document_loaders/parsers/docai.py +1 -1
- langchain/document_loaders/parsers/generic.py +1 -1
- langchain/document_loaders/parsers/html/__init__.py +1 -1
- langchain/document_loaders/parsers/html/bs4.py +1 -1
- langchain/document_loaders/parsers/language/cobol.py +1 -1
- langchain/document_loaders/parsers/language/python.py +1 -1
- langchain/document_loaders/parsers/msword.py +1 -1
- langchain/document_loaders/parsers/pdf.py +5 -5
- langchain/document_loaders/parsers/registry.py +1 -1
- langchain/document_loaders/pdf.py +8 -8
- langchain/document_loaders/powerpoint.py +1 -1
- langchain/document_loaders/pyspark_dataframe.py +1 -1
- langchain/document_loaders/telegram.py +2 -2
- langchain/document_loaders/tencent_cos_directory.py +1 -1
- langchain/document_loaders/unstructured.py +5 -5
- langchain/document_loaders/url_playwright.py +1 -1
- langchain/document_loaders/whatsapp_chat.py +1 -1
- langchain/document_loaders/youtube.py +2 -2
- langchain/document_transformers/__init__.py +3 -3
- langchain/document_transformers/beautiful_soup_transformer.py +1 -1
- langchain/document_transformers/doctran_text_extract.py +1 -1
- langchain/document_transformers/doctran_text_qa.py +1 -1
- langchain/document_transformers/doctran_text_translate.py +1 -1
- langchain/document_transformers/embeddings_redundant_filter.py +3 -3
- langchain/document_transformers/google_translate.py +1 -1
- langchain/document_transformers/html2text.py +1 -1
- langchain/document_transformers/nuclia_text_transform.py +1 -1
- langchain/embeddings/__init__.py +5 -5
- langchain/embeddings/base.py +33 -24
- langchain/embeddings/cache.py +36 -31
- langchain/embeddings/fake.py +1 -1
- langchain/embeddings/huggingface.py +2 -2
- langchain/evaluation/__init__.py +22 -22
- langchain/evaluation/agents/trajectory_eval_chain.py +23 -23
- langchain/evaluation/agents/trajectory_eval_prompt.py +6 -9
- langchain/evaluation/comparison/__init__.py +1 -1
- langchain/evaluation/comparison/eval_chain.py +20 -13
- langchain/evaluation/comparison/prompt.py +1 -2
- langchain/evaluation/criteria/__init__.py +1 -1
- langchain/evaluation/criteria/eval_chain.py +20 -11
- langchain/evaluation/criteria/prompt.py +2 -3
- langchain/evaluation/embedding_distance/base.py +23 -20
- langchain/evaluation/loading.py +15 -11
- langchain/evaluation/parsing/base.py +4 -1
- langchain/evaluation/parsing/json_distance.py +5 -2
- langchain/evaluation/parsing/json_schema.py +12 -8
- langchain/evaluation/qa/__init__.py +1 -1
- langchain/evaluation/qa/eval_chain.py +12 -5
- langchain/evaluation/qa/eval_prompt.py +7 -8
- langchain/evaluation/qa/generate_chain.py +2 -1
- langchain/evaluation/qa/generate_prompt.py +2 -4
- langchain/evaluation/schema.py +38 -30
- langchain/evaluation/scoring/__init__.py +1 -1
- langchain/evaluation/scoring/eval_chain.py +22 -15
- langchain/evaluation/scoring/prompt.py +0 -1
- langchain/evaluation/string_distance/base.py +14 -9
- langchain/globals.py +12 -11
- langchain/graphs/__init__.py +6 -6
- langchain/graphs/graph_document.py +1 -1
- langchain/graphs/networkx_graph.py +2 -2
- langchain/hub.py +9 -11
- langchain/indexes/__init__.py +3 -3
- langchain/indexes/_sql_record_manager.py +63 -46
- langchain/indexes/prompts/entity_extraction.py +1 -2
- langchain/indexes/prompts/entity_summarization.py +1 -2
- langchain/indexes/prompts/knowledge_triplet_extraction.py +1 -3
- langchain/indexes/vectorstore.py +35 -19
- langchain/llms/__init__.py +13 -13
- langchain/llms/ai21.py +1 -1
- langchain/llms/azureml_endpoint.py +4 -4
- langchain/llms/base.py +15 -7
- langchain/llms/bedrock.py +1 -1
- langchain/llms/cloudflare_workersai.py +1 -1
- langchain/llms/gradient_ai.py +1 -1
- langchain/llms/loading.py +1 -1
- langchain/llms/openai.py +1 -1
- langchain/llms/sagemaker_endpoint.py +1 -1
- langchain/load/dump.py +1 -1
- langchain/load/load.py +1 -1
- langchain/load/serializable.py +3 -3
- langchain/memory/__init__.py +3 -3
- langchain/memory/buffer.py +9 -7
- langchain/memory/chat_memory.py +14 -8
- langchain/memory/chat_message_histories/__init__.py +1 -1
- langchain/memory/chat_message_histories/astradb.py +1 -1
- langchain/memory/chat_message_histories/cassandra.py +1 -1
- langchain/memory/chat_message_histories/cosmos_db.py +1 -1
- langchain/memory/chat_message_histories/dynamodb.py +1 -1
- langchain/memory/chat_message_histories/elasticsearch.py +1 -1
- langchain/memory/chat_message_histories/file.py +1 -1
- langchain/memory/chat_message_histories/firestore.py +1 -1
- langchain/memory/chat_message_histories/momento.py +1 -1
- langchain/memory/chat_message_histories/mongodb.py +1 -1
- langchain/memory/chat_message_histories/neo4j.py +1 -1
- langchain/memory/chat_message_histories/postgres.py +1 -1
- langchain/memory/chat_message_histories/redis.py +1 -1
- langchain/memory/chat_message_histories/rocksetdb.py +1 -1
- langchain/memory/chat_message_histories/singlestoredb.py +1 -1
- langchain/memory/chat_message_histories/streamlit.py +1 -1
- langchain/memory/chat_message_histories/upstash_redis.py +1 -1
- langchain/memory/chat_message_histories/xata.py +1 -1
- langchain/memory/chat_message_histories/zep.py +1 -1
- langchain/memory/combined.py +13 -12
- langchain/memory/entity.py +84 -61
- langchain/memory/prompt.py +10 -11
- langchain/memory/readonly.py +0 -2
- langchain/memory/simple.py +1 -3
- langchain/memory/summary.py +13 -11
- langchain/memory/summary_buffer.py +17 -8
- langchain/memory/utils.py +3 -2
- langchain/memory/vectorstore.py +12 -5
- langchain/memory/vectorstore_token_buffer_memory.py +5 -5
- langchain/model_laboratory.py +12 -11
- langchain/output_parsers/__init__.py +4 -4
- langchain/output_parsers/boolean.py +7 -4
- langchain/output_parsers/combining.py +10 -5
- langchain/output_parsers/datetime.py +32 -31
- langchain/output_parsers/enum.py +5 -3
- langchain/output_parsers/fix.py +52 -52
- langchain/output_parsers/format_instructions.py +6 -8
- langchain/output_parsers/json.py +2 -2
- langchain/output_parsers/list.py +2 -2
- langchain/output_parsers/loading.py +9 -9
- langchain/output_parsers/openai_functions.py +3 -3
- langchain/output_parsers/openai_tools.py +1 -1
- langchain/output_parsers/pandas_dataframe.py +43 -47
- langchain/output_parsers/prompts.py +1 -2
- langchain/output_parsers/rail_parser.py +1 -1
- langchain/output_parsers/regex.py +7 -8
- langchain/output_parsers/regex_dict.py +7 -10
- langchain/output_parsers/retry.py +77 -78
- langchain/output_parsers/structured.py +11 -6
- langchain/output_parsers/yaml.py +15 -11
- langchain/prompts/__init__.py +5 -3
- langchain/prompts/base.py +5 -5
- langchain/prompts/chat.py +8 -8
- langchain/prompts/example_selector/__init__.py +3 -1
- langchain/prompts/example_selector/semantic_similarity.py +2 -2
- langchain/prompts/few_shot.py +1 -1
- langchain/prompts/loading.py +3 -3
- langchain/prompts/prompt.py +1 -1
- langchain/retrievers/__init__.py +5 -5
- langchain/retrievers/bedrock.py +2 -2
- langchain/retrievers/bm25.py +1 -1
- langchain/retrievers/contextual_compression.py +14 -8
- langchain/retrievers/docarray.py +1 -1
- langchain/retrievers/document_compressors/__init__.py +5 -4
- langchain/retrievers/document_compressors/base.py +12 -6
- langchain/retrievers/document_compressors/chain_extract.py +2 -2
- langchain/retrievers/document_compressors/chain_extract_prompt.py +2 -3
- langchain/retrievers/document_compressors/chain_filter.py +9 -9
- langchain/retrievers/document_compressors/chain_filter_prompt.py +1 -2
- langchain/retrievers/document_compressors/cohere_rerank.py +15 -15
- langchain/retrievers/document_compressors/embeddings_filter.py +21 -17
- langchain/retrievers/document_compressors/flashrank_rerank.py +1 -1
- langchain/retrievers/document_compressors/listwise_rerank.py +7 -5
- langchain/retrievers/ensemble.py +28 -25
- langchain/retrievers/google_cloud_documentai_warehouse.py +1 -1
- langchain/retrievers/google_vertex_ai_search.py +2 -2
- langchain/retrievers/kendra.py +10 -10
- langchain/retrievers/llama_index.py +1 -1
- langchain/retrievers/merger_retriever.py +11 -11
- langchain/retrievers/milvus.py +1 -1
- langchain/retrievers/multi_query.py +32 -26
- langchain/retrievers/multi_vector.py +20 -8
- langchain/retrievers/parent_document_retriever.py +18 -9
- langchain/retrievers/re_phraser.py +6 -5
- langchain/retrievers/self_query/base.py +138 -127
- langchain/retrievers/time_weighted_retriever.py +18 -7
- langchain/retrievers/zilliz.py +1 -1
- langchain/runnables/openai_functions.py +6 -2
- langchain/schema/__init__.py +23 -23
- langchain/schema/cache.py +1 -1
- langchain/schema/callbacks/base.py +7 -7
- langchain/schema/callbacks/manager.py +19 -19
- langchain/schema/callbacks/tracers/base.py +1 -1
- langchain/schema/callbacks/tracers/evaluation.py +1 -1
- langchain/schema/callbacks/tracers/langchain.py +1 -1
- langchain/schema/callbacks/tracers/langchain_v1.py +1 -1
- langchain/schema/callbacks/tracers/log_stream.py +1 -1
- langchain/schema/callbacks/tracers/schemas.py +8 -8
- langchain/schema/callbacks/tracers/stdout.py +3 -3
- langchain/schema/document.py +1 -1
- langchain/schema/language_model.py +2 -2
- langchain/schema/messages.py +12 -12
- langchain/schema/output.py +3 -3
- langchain/schema/output_parser.py +3 -3
- langchain/schema/runnable/__init__.py +3 -3
- langchain/schema/runnable/base.py +9 -9
- langchain/schema/runnable/config.py +5 -5
- langchain/schema/runnable/configurable.py +1 -1
- langchain/schema/runnable/history.py +1 -1
- langchain/schema/runnable/passthrough.py +1 -1
- langchain/schema/runnable/utils.py +16 -16
- langchain/schema/vectorstore.py +1 -1
- langchain/smith/__init__.py +1 -1
- langchain/smith/evaluation/__init__.py +2 -2
- langchain/smith/evaluation/config.py +10 -7
- langchain/smith/evaluation/name_generation.py +3 -3
- langchain/smith/evaluation/progress.py +11 -2
- langchain/smith/evaluation/runner_utils.py +179 -127
- langchain/smith/evaluation/string_run_evaluator.py +75 -68
- langchain/storage/__init__.py +2 -2
- langchain/storage/_lc_store.py +4 -2
- langchain/storage/encoder_backed.py +6 -2
- langchain/storage/file_system.py +19 -16
- langchain/storage/in_memory.py +1 -1
- langchain/storage/upstash_redis.py +1 -1
- langchain/text_splitter.py +15 -15
- langchain/tools/__init__.py +28 -26
- langchain/tools/ainetwork/app.py +1 -1
- langchain/tools/ainetwork/base.py +1 -1
- langchain/tools/ainetwork/owner.py +1 -1
- langchain/tools/ainetwork/rule.py +1 -1
- langchain/tools/ainetwork/transfer.py +1 -1
- langchain/tools/ainetwork/value.py +1 -1
- langchain/tools/amadeus/closest_airport.py +1 -1
- langchain/tools/amadeus/flight_search.py +1 -1
- langchain/tools/azure_cognitive_services/__init__.py +1 -1
- langchain/tools/base.py +4 -4
- langchain/tools/bearly/tool.py +1 -1
- langchain/tools/bing_search/__init__.py +1 -1
- langchain/tools/bing_search/tool.py +1 -1
- langchain/tools/dataforseo_api_search/__init__.py +1 -1
- langchain/tools/dataforseo_api_search/tool.py +1 -1
- langchain/tools/ddg_search/tool.py +1 -1
- langchain/tools/e2b_data_analysis/tool.py +2 -2
- langchain/tools/edenai/__init__.py +1 -1
- langchain/tools/file_management/__init__.py +1 -1
- langchain/tools/file_management/copy.py +1 -1
- langchain/tools/file_management/delete.py +1 -1
- langchain/tools/gmail/__init__.py +2 -2
- langchain/tools/gmail/get_message.py +1 -1
- langchain/tools/gmail/search.py +1 -1
- langchain/tools/gmail/send_message.py +1 -1
- langchain/tools/google_finance/__init__.py +1 -1
- langchain/tools/google_finance/tool.py +1 -1
- langchain/tools/google_scholar/__init__.py +1 -1
- langchain/tools/google_scholar/tool.py +1 -1
- langchain/tools/google_search/__init__.py +1 -1
- langchain/tools/google_search/tool.py +1 -1
- langchain/tools/google_serper/__init__.py +1 -1
- langchain/tools/google_serper/tool.py +1 -1
- langchain/tools/google_trends/__init__.py +1 -1
- langchain/tools/google_trends/tool.py +1 -1
- langchain/tools/jira/tool.py +20 -1
- langchain/tools/json/tool.py +25 -3
- langchain/tools/memorize/tool.py +1 -1
- langchain/tools/multion/__init__.py +1 -1
- langchain/tools/multion/update_session.py +1 -1
- langchain/tools/office365/__init__.py +2 -2
- langchain/tools/office365/events_search.py +1 -1
- langchain/tools/office365/messages_search.py +1 -1
- langchain/tools/office365/send_event.py +1 -1
- langchain/tools/office365/send_message.py +1 -1
- langchain/tools/openapi/utils/api_models.py +6 -6
- langchain/tools/playwright/__init__.py +5 -5
- langchain/tools/playwright/click.py +1 -1
- langchain/tools/playwright/extract_hyperlinks.py +1 -1
- langchain/tools/playwright/get_elements.py +1 -1
- langchain/tools/playwright/navigate.py +1 -1
- langchain/tools/plugin.py +2 -2
- langchain/tools/powerbi/tool.py +1 -1
- langchain/tools/python/__init__.py +2 -1
- langchain/tools/reddit_search/tool.py +1 -1
- langchain/tools/render.py +2 -2
- langchain/tools/requests/tool.py +2 -2
- langchain/tools/searchapi/tool.py +1 -1
- langchain/tools/searx_search/tool.py +1 -1
- langchain/tools/slack/get_message.py +1 -1
- langchain/tools/spark_sql/tool.py +1 -1
- langchain/tools/sql_database/tool.py +1 -1
- langchain/tools/tavily_search/__init__.py +1 -1
- langchain/tools/tavily_search/tool.py +1 -1
- langchain/tools/zapier/__init__.py +1 -1
- langchain/tools/zapier/tool.py +24 -2
- langchain/utilities/__init__.py +4 -4
- langchain/utilities/arcee.py +4 -4
- langchain/utilities/clickup.py +4 -4
- langchain/utilities/dalle_image_generator.py +1 -1
- langchain/utilities/dataforseo_api_search.py +1 -1
- langchain/utilities/opaqueprompts.py +1 -1
- langchain/utilities/reddit_search.py +1 -1
- langchain/utilities/sql_database.py +1 -1
- langchain/utilities/tavily_search.py +1 -1
- langchain/utilities/vertexai.py +2 -2
- langchain/utils/__init__.py +1 -1
- langchain/utils/aiter.py +1 -1
- langchain/utils/html.py +3 -3
- langchain/utils/input.py +1 -1
- langchain/utils/iter.py +1 -1
- langchain/utils/json_schema.py +1 -3
- langchain/utils/strings.py +1 -1
- langchain/utils/utils.py +6 -6
- langchain/vectorstores/__init__.py +5 -5
- langchain/vectorstores/alibabacloud_opensearch.py +1 -1
- langchain/vectorstores/azure_cosmos_db.py +1 -1
- langchain/vectorstores/clickhouse.py +1 -1
- langchain/vectorstores/elastic_vector_search.py +1 -1
- langchain/vectorstores/elasticsearch.py +2 -2
- langchain/vectorstores/myscale.py +1 -1
- langchain/vectorstores/neo4j_vector.py +1 -1
- langchain/vectorstores/pgembedding.py +1 -1
- langchain/vectorstores/qdrant.py +1 -1
- langchain/vectorstores/redis/__init__.py +1 -1
- langchain/vectorstores/redis/base.py +1 -1
- langchain/vectorstores/redis/filters.py +4 -4
- langchain/vectorstores/redis/schema.py +6 -6
- langchain/vectorstores/sklearn.py +2 -2
- langchain/vectorstores/starrocks.py +1 -1
- langchain/vectorstores/utils.py +1 -1
- {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/METADATA +4 -4
- {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/RECORD +580 -580
- {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/WHEEL +1 -1
- {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/entry_points.txt +0 -0
- {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/licenses/LICENSE +0 -0
|
@@ -38,26 +38,29 @@ _FunctionsAgentAction = AgentActionMessageLog
|
|
|
38
38
|
def _parse_ai_message(message: BaseMessage) -> Union[list[AgentAction], AgentFinish]:
|
|
39
39
|
"""Parse an AI message."""
|
|
40
40
|
if not isinstance(message, AIMessage):
|
|
41
|
-
|
|
41
|
+
msg = f"Expected an AI message got {type(message)}"
|
|
42
|
+
raise TypeError(msg)
|
|
42
43
|
|
|
43
44
|
function_call = message.additional_kwargs.get("function_call", {})
|
|
44
45
|
|
|
45
46
|
if function_call:
|
|
46
47
|
try:
|
|
47
48
|
arguments = json.loads(function_call["arguments"], strict=False)
|
|
48
|
-
except JSONDecodeError:
|
|
49
|
-
|
|
49
|
+
except JSONDecodeError as e:
|
|
50
|
+
msg = (
|
|
50
51
|
f"Could not parse tool input: {function_call} because "
|
|
51
52
|
f"the `arguments` is not valid JSON."
|
|
52
53
|
)
|
|
54
|
+
raise OutputParserException(msg) from e
|
|
53
55
|
|
|
54
56
|
try:
|
|
55
57
|
tools = arguments["actions"]
|
|
56
|
-
except (TypeError, KeyError):
|
|
57
|
-
|
|
58
|
+
except (TypeError, KeyError) as e:
|
|
59
|
+
msg = (
|
|
58
60
|
f"Could not parse tool input: {function_call} because "
|
|
59
61
|
f"the `arguments` JSON does not contain `actions` key."
|
|
60
62
|
)
|
|
63
|
+
raise OutputParserException(msg) from e
|
|
61
64
|
|
|
62
65
|
final_tools: list[AgentAction] = []
|
|
63
66
|
for tool_schema in tools:
|
|
@@ -92,10 +95,14 @@ def _parse_ai_message(message: BaseMessage) -> Union[list[AgentAction], AgentFin
|
|
|
92
95
|
return final_tools
|
|
93
96
|
|
|
94
97
|
return AgentFinish(
|
|
95
|
-
return_values={"output": message.content},
|
|
98
|
+
return_values={"output": message.content},
|
|
99
|
+
log=str(message.content),
|
|
96
100
|
)
|
|
97
101
|
|
|
98
102
|
|
|
103
|
+
_NOT_SET = object()
|
|
104
|
+
|
|
105
|
+
|
|
99
106
|
@deprecated("0.1.0", alternative="create_openai_tools_agent", removal="1.0")
|
|
100
107
|
class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
101
108
|
"""Agent driven by OpenAIs function powered API.
|
|
@@ -121,10 +128,11 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
121
128
|
def validate_prompt(self) -> Self:
|
|
122
129
|
prompt: BasePromptTemplate = self.prompt
|
|
123
130
|
if "agent_scratchpad" not in prompt.input_variables:
|
|
124
|
-
|
|
131
|
+
msg = (
|
|
125
132
|
"`agent_scratchpad` should be one of the variables in the prompt, "
|
|
126
133
|
f"got {prompt.input_variables}"
|
|
127
134
|
)
|
|
135
|
+
raise ValueError(msg)
|
|
128
136
|
return self
|
|
129
137
|
|
|
130
138
|
@property
|
|
@@ -186,7 +194,7 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
186
194
|
},
|
|
187
195
|
"required": ["action_name", "action"],
|
|
188
196
|
},
|
|
189
|
-
}
|
|
197
|
+
},
|
|
190
198
|
},
|
|
191
199
|
"required": ["actions"],
|
|
192
200
|
},
|
|
@@ -218,10 +226,11 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
218
226
|
prompt = self.prompt.format_prompt(**full_inputs)
|
|
219
227
|
messages = prompt.to_messages()
|
|
220
228
|
predicted_message = self.llm.predict_messages(
|
|
221
|
-
messages,
|
|
229
|
+
messages,
|
|
230
|
+
functions=self.functions,
|
|
231
|
+
callbacks=callbacks,
|
|
222
232
|
)
|
|
223
|
-
|
|
224
|
-
return agent_decision
|
|
233
|
+
return _parse_ai_message(predicted_message)
|
|
225
234
|
|
|
226
235
|
async def aplan(
|
|
227
236
|
self,
|
|
@@ -248,17 +257,16 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
248
257
|
prompt = self.prompt.format_prompt(**full_inputs)
|
|
249
258
|
messages = prompt.to_messages()
|
|
250
259
|
predicted_message = await self.llm.apredict_messages(
|
|
251
|
-
messages,
|
|
260
|
+
messages,
|
|
261
|
+
functions=self.functions,
|
|
262
|
+
callbacks=callbacks,
|
|
252
263
|
)
|
|
253
|
-
|
|
254
|
-
return agent_decision
|
|
264
|
+
return _parse_ai_message(predicted_message)
|
|
255
265
|
|
|
256
266
|
@classmethod
|
|
257
267
|
def create_prompt(
|
|
258
268
|
cls,
|
|
259
|
-
system_message: Optional[SystemMessage] =
|
|
260
|
-
content="You are a helpful AI assistant."
|
|
261
|
-
),
|
|
269
|
+
system_message: Optional[SystemMessage] = _NOT_SET, # type: ignore[assignment]
|
|
262
270
|
extra_prompt_messages: Optional[list[BaseMessagePromptTemplate]] = None,
|
|
263
271
|
) -> BasePromptTemplate:
|
|
264
272
|
"""Create prompt for this agent.
|
|
@@ -273,18 +281,20 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
273
281
|
A prompt template to pass into this agent.
|
|
274
282
|
"""
|
|
275
283
|
_prompts = extra_prompt_messages or []
|
|
284
|
+
system_message_ = (
|
|
285
|
+
system_message
|
|
286
|
+
if system_message is not _NOT_SET
|
|
287
|
+
else SystemMessage(content="You are a helpful AI assistant.")
|
|
288
|
+
)
|
|
276
289
|
messages: list[Union[BaseMessagePromptTemplate, BaseMessage]]
|
|
277
|
-
if
|
|
278
|
-
messages = [system_message]
|
|
279
|
-
else:
|
|
280
|
-
messages = []
|
|
290
|
+
messages = [system_message_] if system_message_ else []
|
|
281
291
|
|
|
282
292
|
messages.extend(
|
|
283
293
|
[
|
|
284
294
|
*_prompts,
|
|
285
295
|
HumanMessagePromptTemplate.from_template("{input}"),
|
|
286
296
|
MessagesPlaceholder(variable_name="agent_scratchpad"),
|
|
287
|
-
]
|
|
297
|
+
],
|
|
288
298
|
)
|
|
289
299
|
return ChatPromptTemplate(messages=messages)
|
|
290
300
|
|
|
@@ -295,9 +305,7 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
295
305
|
tools: Sequence[BaseTool],
|
|
296
306
|
callback_manager: Optional[BaseCallbackManager] = None,
|
|
297
307
|
extra_prompt_messages: Optional[list[BaseMessagePromptTemplate]] = None,
|
|
298
|
-
system_message: Optional[SystemMessage] =
|
|
299
|
-
content="You are a helpful AI assistant."
|
|
300
|
-
),
|
|
308
|
+
system_message: Optional[SystemMessage] = _NOT_SET, # type: ignore[assignment]
|
|
301
309
|
**kwargs: Any,
|
|
302
310
|
) -> BaseMultiActionAgent:
|
|
303
311
|
"""Construct an agent from an LLM and tools.
|
|
@@ -311,9 +319,14 @@ class OpenAIMultiFunctionsAgent(BaseMultiActionAgent):
|
|
|
311
319
|
Default is a default system message.
|
|
312
320
|
kwargs: Additional arguments.
|
|
313
321
|
"""
|
|
322
|
+
system_message_ = (
|
|
323
|
+
system_message
|
|
324
|
+
if system_message is not _NOT_SET
|
|
325
|
+
else SystemMessage(content="You are a helpful AI assistant.")
|
|
326
|
+
)
|
|
314
327
|
prompt = cls.create_prompt(
|
|
315
328
|
extra_prompt_messages=extra_prompt_messages,
|
|
316
|
-
system_message=
|
|
329
|
+
system_message=system_message_,
|
|
317
330
|
)
|
|
318
331
|
return cls( # type: ignore[call-arg]
|
|
319
332
|
llm=llm,
|
|
@@ -17,7 +17,7 @@ def create_openai_tools_agent(
|
|
|
17
17
|
llm: BaseLanguageModel,
|
|
18
18
|
tools: Sequence[BaseTool],
|
|
19
19
|
prompt: ChatPromptTemplate,
|
|
20
|
-
strict: Optional[bool] = None,
|
|
20
|
+
strict: Optional[bool] = None, # noqa: FBT001
|
|
21
21
|
) -> Runnable:
|
|
22
22
|
"""Create an agent that uses OpenAI tools.
|
|
23
23
|
|
|
@@ -86,23 +86,23 @@ def create_openai_tools_agent(
|
|
|
86
86
|
)
|
|
87
87
|
"""
|
|
88
88
|
missing_vars = {"agent_scratchpad"}.difference(
|
|
89
|
-
prompt.input_variables + list(prompt.partial_variables)
|
|
89
|
+
prompt.input_variables + list(prompt.partial_variables),
|
|
90
90
|
)
|
|
91
91
|
if missing_vars:
|
|
92
|
-
|
|
92
|
+
msg = f"Prompt missing required variables: {missing_vars}"
|
|
93
|
+
raise ValueError(msg)
|
|
93
94
|
|
|
94
95
|
llm_with_tools = llm.bind(
|
|
95
|
-
tools=[convert_to_openai_tool(tool, strict=strict) for tool in tools]
|
|
96
|
+
tools=[convert_to_openai_tool(tool, strict=strict) for tool in tools],
|
|
96
97
|
)
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
return (
|
|
99
100
|
RunnablePassthrough.assign(
|
|
100
101
|
agent_scratchpad=lambda x: format_to_openai_tool_messages(
|
|
101
|
-
x["intermediate_steps"]
|
|
102
|
-
)
|
|
102
|
+
x["intermediate_steps"],
|
|
103
|
+
),
|
|
103
104
|
)
|
|
104
105
|
| prompt
|
|
105
106
|
| llm_with_tools
|
|
106
107
|
| OpenAIToolsAgentOutputParser()
|
|
107
108
|
)
|
|
108
|
-
return agent
|
|
@@ -25,11 +25,11 @@ from langchain.agents.output_parsers.tools import ToolsAgentOutputParser
|
|
|
25
25
|
from langchain.agents.output_parsers.xml import XMLAgentOutputParser
|
|
26
26
|
|
|
27
27
|
__all__ = [
|
|
28
|
+
"JSONAgentOutputParser",
|
|
29
|
+
"OpenAIFunctionsAgentOutputParser",
|
|
30
|
+
"ReActJsonSingleInputOutputParser",
|
|
28
31
|
"ReActSingleInputOutputParser",
|
|
29
32
|
"SelfAskOutputParser",
|
|
30
33
|
"ToolsAgentOutputParser",
|
|
31
|
-
"ReActJsonSingleInputOutputParser",
|
|
32
|
-
"OpenAIFunctionsAgentOutputParser",
|
|
33
34
|
"XMLAgentOutputParser",
|
|
34
|
-
"JSONAgentOutputParser",
|
|
35
35
|
]
|
|
@@ -49,13 +49,13 @@ class JSONAgentOutputParser(AgentOutputParser):
|
|
|
49
49
|
response = response[0]
|
|
50
50
|
if response["action"] == "Final Answer":
|
|
51
51
|
return AgentFinish({"output": response["action_input"]}, text)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return AgentAction(response["action"], action_input, text)
|
|
52
|
+
action_input = response.get("action_input", {})
|
|
53
|
+
if action_input is None:
|
|
54
|
+
action_input = {}
|
|
55
|
+
return AgentAction(response["action"], action_input, text)
|
|
57
56
|
except Exception as e:
|
|
58
|
-
|
|
57
|
+
msg = f"Could not parse LLM output: {text}"
|
|
58
|
+
raise OutputParserException(msg) from e
|
|
59
59
|
|
|
60
60
|
@property
|
|
61
61
|
def _type(self) -> str:
|
|
@@ -33,7 +33,8 @@ class OpenAIFunctionsAgentOutputParser(AgentOutputParser):
|
|
|
33
33
|
def _parse_ai_message(message: BaseMessage) -> Union[AgentAction, AgentFinish]:
|
|
34
34
|
"""Parse an AI message."""
|
|
35
35
|
if not isinstance(message, AIMessage):
|
|
36
|
-
|
|
36
|
+
msg = f"Expected an AI message got {type(message)}"
|
|
37
|
+
raise TypeError(msg)
|
|
37
38
|
|
|
38
39
|
function_call = message.additional_kwargs.get("function_call", {})
|
|
39
40
|
|
|
@@ -46,11 +47,12 @@ class OpenAIFunctionsAgentOutputParser(AgentOutputParser):
|
|
|
46
47
|
else:
|
|
47
48
|
# otherwise it returns a json object
|
|
48
49
|
_tool_input = json.loads(function_call["arguments"], strict=False)
|
|
49
|
-
except JSONDecodeError:
|
|
50
|
-
|
|
50
|
+
except JSONDecodeError as e:
|
|
51
|
+
msg = (
|
|
51
52
|
f"Could not parse tool input: {function_call} because "
|
|
52
53
|
f"the `arguments` is not valid JSON."
|
|
53
54
|
)
|
|
55
|
+
raise OutputParserException(msg) from e
|
|
54
56
|
|
|
55
57
|
# HACK HACK HACK:
|
|
56
58
|
# The code that encodes tool input into Open AI uses a special variable
|
|
@@ -73,16 +75,22 @@ class OpenAIFunctionsAgentOutputParser(AgentOutputParser):
|
|
|
73
75
|
)
|
|
74
76
|
|
|
75
77
|
return AgentFinish(
|
|
76
|
-
return_values={"output": message.content},
|
|
78
|
+
return_values={"output": message.content},
|
|
79
|
+
log=str(message.content),
|
|
77
80
|
)
|
|
78
81
|
|
|
79
82
|
def parse_result(
|
|
80
|
-
self,
|
|
83
|
+
self,
|
|
84
|
+
result: list[Generation],
|
|
85
|
+
*,
|
|
86
|
+
partial: bool = False,
|
|
81
87
|
) -> Union[AgentAction, AgentFinish]:
|
|
82
88
|
if not isinstance(result[0], ChatGeneration):
|
|
83
|
-
|
|
89
|
+
msg = "This output parser only works on ChatGeneration output"
|
|
90
|
+
raise ValueError(msg) # noqa: TRY004
|
|
84
91
|
message = result[0].message
|
|
85
92
|
return self._parse_ai_message(message)
|
|
86
93
|
|
|
87
94
|
def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
|
|
88
|
-
|
|
95
|
+
msg = "Can only parse messages"
|
|
96
|
+
raise ValueError(msg)
|
|
@@ -30,7 +30,7 @@ def parse_ai_message_to_openai_tool_action(
|
|
|
30
30
|
log=action.log,
|
|
31
31
|
message_log=action.message_log,
|
|
32
32
|
tool_call_id=action.tool_call_id,
|
|
33
|
-
)
|
|
33
|
+
),
|
|
34
34
|
)
|
|
35
35
|
else:
|
|
36
36
|
final_actions.append(action)
|
|
@@ -54,12 +54,17 @@ class OpenAIToolsAgentOutputParser(MultiActionAgentOutputParser):
|
|
|
54
54
|
return "openai-tools-agent-output-parser"
|
|
55
55
|
|
|
56
56
|
def parse_result(
|
|
57
|
-
self,
|
|
57
|
+
self,
|
|
58
|
+
result: list[Generation],
|
|
59
|
+
*,
|
|
60
|
+
partial: bool = False,
|
|
58
61
|
) -> Union[list[AgentAction], AgentFinish]:
|
|
59
62
|
if not isinstance(result[0], ChatGeneration):
|
|
60
|
-
|
|
63
|
+
msg = "This output parser only works on ChatGeneration output"
|
|
64
|
+
raise ValueError(msg) # noqa: TRY004
|
|
61
65
|
message = result[0].message
|
|
62
66
|
return parse_ai_message_to_openai_tool_action(message)
|
|
63
67
|
|
|
64
68
|
def parse(self, text: str) -> Union[list[AgentAction], AgentFinish]:
|
|
65
|
-
|
|
69
|
+
msg = "Can only parse messages"
|
|
70
|
+
raise ValueError(msg)
|
|
@@ -55,22 +55,27 @@ class ReActJsonSingleInputOutputParser(AgentOutputParser):
|
|
|
55
55
|
found = self.pattern.search(text)
|
|
56
56
|
if not found:
|
|
57
57
|
# Fast fail to parse Final Answer.
|
|
58
|
-
|
|
58
|
+
msg = "action not found"
|
|
59
|
+
raise ValueError(msg)
|
|
59
60
|
action = found.group(1)
|
|
60
61
|
response = json.loads(action.strip())
|
|
61
62
|
includes_action = "action" in response
|
|
62
63
|
if includes_answer and includes_action:
|
|
63
|
-
|
|
64
|
+
msg = (
|
|
64
65
|
"Parsing LLM output produced a final answer "
|
|
65
66
|
f"and a parse-able action: {text}"
|
|
66
67
|
)
|
|
68
|
+
raise OutputParserException(msg)
|
|
67
69
|
return AgentAction(
|
|
68
|
-
response["action"],
|
|
70
|
+
response["action"],
|
|
71
|
+
response.get("action_input", {}),
|
|
72
|
+
text,
|
|
69
73
|
)
|
|
70
74
|
|
|
71
|
-
except Exception:
|
|
75
|
+
except Exception as e:
|
|
72
76
|
if not includes_answer:
|
|
73
|
-
|
|
77
|
+
msg = f"Could not parse LLM output: {text}"
|
|
78
|
+
raise OutputParserException(msg) from e
|
|
74
79
|
output = text.split(FINAL_ANSWER_ACTION)[-1].strip()
|
|
75
80
|
return AgentFinish({"output": output}, text)
|
|
76
81
|
|
|
@@ -56,9 +56,8 @@ class ReActSingleInputOutputParser(AgentOutputParser):
|
|
|
56
56
|
action_match = re.search(regex, text, re.DOTALL)
|
|
57
57
|
if action_match:
|
|
58
58
|
if includes_answer:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
59
|
+
msg = f"{FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: {text}"
|
|
60
|
+
raise OutputParserException(msg)
|
|
62
61
|
action = action_match.group(1).strip()
|
|
63
62
|
action_input = action_match.group(2)
|
|
64
63
|
tool_input = action_input.strip(" ")
|
|
@@ -66,29 +65,34 @@ class ReActSingleInputOutputParser(AgentOutputParser):
|
|
|
66
65
|
|
|
67
66
|
return AgentAction(action, tool_input, text)
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
if includes_answer:
|
|
70
69
|
return AgentFinish(
|
|
71
|
-
{"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()},
|
|
70
|
+
{"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()},
|
|
71
|
+
text,
|
|
72
72
|
)
|
|
73
73
|
|
|
74
74
|
if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL):
|
|
75
|
+
msg = f"Could not parse LLM output: `{text}`"
|
|
75
76
|
raise OutputParserException(
|
|
76
|
-
|
|
77
|
+
msg,
|
|
77
78
|
observation=MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE,
|
|
78
79
|
llm_output=text,
|
|
79
80
|
send_to_llm=True,
|
|
80
81
|
)
|
|
81
|
-
|
|
82
|
-
r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)",
|
|
82
|
+
if not re.search(
|
|
83
|
+
r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)",
|
|
84
|
+
text,
|
|
85
|
+
re.DOTALL,
|
|
83
86
|
):
|
|
87
|
+
msg = f"Could not parse LLM output: `{text}`"
|
|
84
88
|
raise OutputParserException(
|
|
85
|
-
|
|
89
|
+
msg,
|
|
86
90
|
observation=MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE,
|
|
87
91
|
llm_output=text,
|
|
88
92
|
send_to_llm=True,
|
|
89
93
|
)
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
msg = f"Could not parse LLM output: `{text}`"
|
|
95
|
+
raise OutputParserException(msg)
|
|
92
96
|
|
|
93
97
|
@property
|
|
94
98
|
def _type(self) -> str:
|
|
@@ -37,9 +37,10 @@ class SelfAskOutputParser(AgentOutputParser):
|
|
|
37
37
|
|
|
38
38
|
def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
|
|
39
39
|
last_line = text.split("\n")[-1]
|
|
40
|
-
if not any(
|
|
40
|
+
if not any(follow in last_line for follow in self.followups):
|
|
41
41
|
if self.finish_string not in last_line:
|
|
42
|
-
|
|
42
|
+
msg = f"Could not parse output: {text}"
|
|
43
|
+
raise OutputParserException(msg)
|
|
43
44
|
return AgentFinish({"output": last_line[len(self.finish_string) :]}, text)
|
|
44
45
|
|
|
45
46
|
after_colon = text.split(":")[-1].strip()
|
|
@@ -24,7 +24,8 @@ def parse_ai_message_to_tool_action(
|
|
|
24
24
|
) -> Union[list[AgentAction], AgentFinish]:
|
|
25
25
|
"""Parse an AI message potentially containing tool_calls."""
|
|
26
26
|
if not isinstance(message, AIMessage):
|
|
27
|
-
|
|
27
|
+
msg = f"Expected an AI message got {type(message)}"
|
|
28
|
+
raise TypeError(msg)
|
|
28
29
|
|
|
29
30
|
actions: list = []
|
|
30
31
|
if message.tool_calls:
|
|
@@ -32,7 +33,8 @@ def parse_ai_message_to_tool_action(
|
|
|
32
33
|
else:
|
|
33
34
|
if not message.additional_kwargs.get("tool_calls"):
|
|
34
35
|
return AgentFinish(
|
|
35
|
-
return_values={"output": message.content},
|
|
36
|
+
return_values={"output": message.content},
|
|
37
|
+
log=str(message.content),
|
|
36
38
|
)
|
|
37
39
|
# Best-effort parsing
|
|
38
40
|
tool_calls = []
|
|
@@ -42,13 +44,14 @@ def parse_ai_message_to_tool_action(
|
|
|
42
44
|
try:
|
|
43
45
|
args = json.loads(function["arguments"] or "{}")
|
|
44
46
|
tool_calls.append(
|
|
45
|
-
ToolCall(name=function_name, args=args, id=tool_call["id"])
|
|
47
|
+
ToolCall(name=function_name, args=args, id=tool_call["id"]),
|
|
46
48
|
)
|
|
47
|
-
except JSONDecodeError:
|
|
48
|
-
|
|
49
|
+
except JSONDecodeError as e:
|
|
50
|
+
msg = (
|
|
49
51
|
f"Could not parse tool input: {function} because "
|
|
50
52
|
f"the `arguments` is not valid JSON."
|
|
51
53
|
)
|
|
54
|
+
raise OutputParserException(msg) from e
|
|
52
55
|
for tool_call in tool_calls:
|
|
53
56
|
# HACK HACK HACK:
|
|
54
57
|
# The code that encodes tool input into Open AI uses a special variable
|
|
@@ -58,10 +61,7 @@ def parse_ai_message_to_tool_action(
|
|
|
58
61
|
# Open AI does not support passing in a JSON array as an argument.
|
|
59
62
|
function_name = tool_call["name"]
|
|
60
63
|
_tool_input = tool_call["args"]
|
|
61
|
-
|
|
62
|
-
tool_input = _tool_input["__arg1"]
|
|
63
|
-
else:
|
|
64
|
-
tool_input = _tool_input
|
|
64
|
+
tool_input = _tool_input.get("__arg1", _tool_input)
|
|
65
65
|
|
|
66
66
|
content_msg = f"responded: {message.content}\n" if message.content else "\n"
|
|
67
67
|
log = f"\nInvoking: `{function_name}` with `{tool_input}`\n{content_msg}\n"
|
|
@@ -72,7 +72,7 @@ def parse_ai_message_to_tool_action(
|
|
|
72
72
|
log=log,
|
|
73
73
|
message_log=[message],
|
|
74
74
|
tool_call_id=tool_call["id"],
|
|
75
|
-
)
|
|
75
|
+
),
|
|
76
76
|
)
|
|
77
77
|
return actions
|
|
78
78
|
|
|
@@ -91,12 +91,17 @@ class ToolsAgentOutputParser(MultiActionAgentOutputParser):
|
|
|
91
91
|
return "tools-agent-output-parser"
|
|
92
92
|
|
|
93
93
|
def parse_result(
|
|
94
|
-
self,
|
|
94
|
+
self,
|
|
95
|
+
result: list[Generation],
|
|
96
|
+
*,
|
|
97
|
+
partial: bool = False,
|
|
95
98
|
) -> Union[list[AgentAction], AgentFinish]:
|
|
96
99
|
if not isinstance(result[0], ChatGeneration):
|
|
97
|
-
|
|
100
|
+
msg = "This output parser only works on ChatGeneration output"
|
|
101
|
+
raise ValueError(msg) # noqa: TRY004
|
|
98
102
|
message = result[0].message
|
|
99
103
|
return parse_ai_message_to_tool_action(message)
|
|
100
104
|
|
|
101
105
|
def parse(self, text: str) -> Union[list[AgentAction], AgentFinish]:
|
|
102
|
-
|
|
106
|
+
msg = "Can only parse messages"
|
|
107
|
+
raise ValueError(msg)
|
|
@@ -1,48 +1,119 @@
|
|
|
1
|
-
|
|
1
|
+
import re
|
|
2
|
+
from typing import Literal, Optional, Union
|
|
2
3
|
|
|
3
4
|
from langchain_core.agents import AgentAction, AgentFinish
|
|
5
|
+
from pydantic import Field
|
|
4
6
|
|
|
5
7
|
from langchain.agents import AgentOutputParser
|
|
6
8
|
|
|
7
9
|
|
|
10
|
+
def _unescape(text: str) -> str:
|
|
11
|
+
"""Convert custom tag delimiters back into XML tags."""
|
|
12
|
+
replacements = {
|
|
13
|
+
"[[tool]]": "<tool>",
|
|
14
|
+
"[[/tool]]": "</tool>",
|
|
15
|
+
"[[tool_input]]": "<tool_input>",
|
|
16
|
+
"[[/tool_input]]": "</tool_input>",
|
|
17
|
+
"[[observation]]": "<observation>",
|
|
18
|
+
"[[/observation]]": "</observation>",
|
|
19
|
+
}
|
|
20
|
+
for repl, orig in replacements.items():
|
|
21
|
+
text = text.replace(repl, orig)
|
|
22
|
+
return text
|
|
23
|
+
|
|
24
|
+
|
|
8
25
|
class XMLAgentOutputParser(AgentOutputParser):
|
|
9
|
-
"""Parses tool invocations and final answers
|
|
26
|
+
"""Parses tool invocations and final answers from XML-formatted agent output.
|
|
27
|
+
|
|
28
|
+
This parser extracts structured information from XML tags to determine whether
|
|
29
|
+
an agent should perform a tool action or provide a final answer. It includes
|
|
30
|
+
built-in escaping support to safely handle tool names and inputs
|
|
31
|
+
containing XML special characters.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
escape_format: The escaping format to use when parsing XML content.
|
|
35
|
+
Supports 'minimal' which uses custom delimiters like [[tool]] to replace
|
|
36
|
+
XML tags within content, preventing parsing conflicts.
|
|
37
|
+
Use 'minimal' if using a corresponding encoding format that uses
|
|
38
|
+
the _escape function when formatting the output (e.g., with format_xml).
|
|
39
|
+
|
|
40
|
+
Expected formats:
|
|
41
|
+
Tool invocation (returns AgentAction):
|
|
42
|
+
<tool>search</tool>
|
|
43
|
+
<tool_input>what is 2 + 2</tool_input>
|
|
10
44
|
|
|
11
|
-
|
|
45
|
+
Final answer (returns AgentFinish):
|
|
46
|
+
<final_answer>The answer is 4</final_answer>
|
|
12
47
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
48
|
+
Note:
|
|
49
|
+
Minimal escaping allows tool names containing XML tags to be safely
|
|
50
|
+
represented. For example, a tool named "search<tool>nested</tool>" would be
|
|
51
|
+
escaped as "search[[tool]]nested[[/tool]]" in the XML and automatically
|
|
52
|
+
unescaped during parsing.
|
|
16
53
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
54
|
+
Raises:
|
|
55
|
+
ValueError: If the input doesn't match either expected XML format or
|
|
56
|
+
contains malformed XML structure.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
escape_format: Optional[Literal["minimal"]] = Field(default="minimal")
|
|
60
|
+
"""The format to use for escaping XML characters.
|
|
21
61
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
being returned.
|
|
62
|
+
minimal - uses custom delimiters to replace XML tags within content,
|
|
63
|
+
preventing parsing conflicts. This is the only supported format currently.
|
|
25
64
|
|
|
26
|
-
|
|
27
|
-
<final_answer>Foo</final_answer>
|
|
28
|
-
```
|
|
65
|
+
None - no escaping is applied, which may lead to parsing conflicts.
|
|
29
66
|
"""
|
|
30
67
|
|
|
31
68
|
def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
69
|
+
# Check for tool invocation first
|
|
70
|
+
tool_matches = re.findall(r"<tool>(.*?)</tool>", text, re.DOTALL)
|
|
71
|
+
if tool_matches:
|
|
72
|
+
if len(tool_matches) != 1:
|
|
73
|
+
msg = (
|
|
74
|
+
f"Malformed tool invocation: expected exactly one <tool> block, "
|
|
75
|
+
f"but found {len(tool_matches)}."
|
|
76
|
+
)
|
|
77
|
+
raise ValueError(msg)
|
|
78
|
+
_tool = tool_matches[0]
|
|
79
|
+
|
|
80
|
+
# Match optional tool input
|
|
81
|
+
input_matches = re.findall(
|
|
82
|
+
r"<tool_input>(.*?)</tool_input>", text, re.DOTALL
|
|
83
|
+
)
|
|
84
|
+
if len(input_matches) > 1:
|
|
85
|
+
msg = (
|
|
86
|
+
f"Malformed tool invocation: expected at most one <tool_input> "
|
|
87
|
+
f"block, but found {len(input_matches)}."
|
|
88
|
+
)
|
|
89
|
+
raise ValueError(msg)
|
|
90
|
+
_tool_input = input_matches[0] if input_matches else ""
|
|
91
|
+
|
|
92
|
+
# Unescape if minimal escape format is used
|
|
93
|
+
if self.escape_format == "minimal":
|
|
94
|
+
_tool = _unescape(_tool)
|
|
95
|
+
_tool_input = _unescape(_tool_input)
|
|
96
|
+
|
|
38
97
|
return AgentAction(tool=_tool, tool_input=_tool_input, log=text)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
98
|
+
# Check for final answer
|
|
99
|
+
if "<final_answer>" in text and "</final_answer>" in text:
|
|
100
|
+
matches = re.findall(r"<final_answer>(.*?)</final_answer>", text, re.DOTALL)
|
|
101
|
+
if len(matches) != 1:
|
|
102
|
+
msg = (
|
|
103
|
+
"Malformed output: expected exactly one "
|
|
104
|
+
"<final_answer>...</final_answer> block."
|
|
105
|
+
)
|
|
106
|
+
raise ValueError(msg)
|
|
107
|
+
answer = matches[0]
|
|
108
|
+
# Unescape custom delimiters in final answer
|
|
109
|
+
if self.escape_format == "minimal":
|
|
110
|
+
answer = _unescape(answer)
|
|
43
111
|
return AgentFinish(return_values={"output": answer}, log=text)
|
|
44
|
-
|
|
45
|
-
|
|
112
|
+
msg = (
|
|
113
|
+
"Malformed output: expected either a tool invocation "
|
|
114
|
+
"or a final answer in XML format."
|
|
115
|
+
)
|
|
116
|
+
raise ValueError(msg)
|
|
46
117
|
|
|
47
118
|
def get_format_instructions(self) -> str:
|
|
48
119
|
raise NotImplementedError
|