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
|
@@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
|
|
11
11
|
# Used to consolidate logic for raising deprecation warnings and
|
|
12
12
|
# handling optional imports.
|
|
13
13
|
DEPRECATED_LOOKUP = {
|
|
14
|
-
"SingleStoreDBChatMessageHistory": "langchain_community.chat_message_histories"
|
|
14
|
+
"SingleStoreDBChatMessageHistory": "langchain_community.chat_message_histories",
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
_import_attribute = create_importer(__package__, deprecated_lookups=DEPRECATED_LOOKUP)
|
|
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
|
|
|
9
9
|
# Used to consolidate logic for raising deprecation warnings and
|
|
10
10
|
# handling optional imports.
|
|
11
11
|
DEPRECATED_LOOKUP = {
|
|
12
|
-
"StreamlitChatMessageHistory": "langchain_community.chat_message_histories"
|
|
12
|
+
"StreamlitChatMessageHistory": "langchain_community.chat_message_histories",
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
_import_attribute = create_importer(__package__, deprecated_lookups=DEPRECATED_LOOKUP)
|
|
@@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
|
|
11
11
|
# Used to consolidate logic for raising deprecation warnings and
|
|
12
12
|
# handling optional imports.
|
|
13
13
|
DEPRECATED_LOOKUP = {
|
|
14
|
-
"UpstashRedisChatMessageHistory": "langchain_community.chat_message_histories"
|
|
14
|
+
"UpstashRedisChatMessageHistory": "langchain_community.chat_message_histories",
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
_import_attribute = create_importer(__package__, deprecated_lookups=DEPRECATED_LOOKUP)
|
|
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
|
|
|
9
9
|
# Used to consolidate logic for raising deprecation warnings and
|
|
10
10
|
# handling optional imports.
|
|
11
11
|
DEPRECATED_LOOKUP = {
|
|
12
|
-
"XataChatMessageHistory": "langchain_community.chat_message_histories"
|
|
12
|
+
"XataChatMessageHistory": "langchain_community.chat_message_histories",
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
_import_attribute = create_importer(__package__, deprecated_lookups=DEPRECATED_LOOKUP)
|
|
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
|
|
|
9
9
|
# Used to consolidate logic for raising deprecation warnings and
|
|
10
10
|
# handling optional imports.
|
|
11
11
|
DEPRECATED_LOOKUP = {
|
|
12
|
-
"ZepChatMessageHistory": "langchain_community.chat_message_histories"
|
|
12
|
+
"ZepChatMessageHistory": "langchain_community.chat_message_histories",
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
_import_attribute = create_importer(__package__, deprecated_lookups=DEPRECATED_LOOKUP)
|
langchain/memory/combined.py
CHANGED
|
@@ -16,16 +16,18 @@ class CombinedMemory(BaseMemory):
|
|
|
16
16
|
@field_validator("memories")
|
|
17
17
|
@classmethod
|
|
18
18
|
def check_repeated_memory_variable(
|
|
19
|
-
cls,
|
|
19
|
+
cls,
|
|
20
|
+
value: list[BaseMemory],
|
|
20
21
|
) -> list[BaseMemory]:
|
|
21
22
|
all_variables: set[str] = set()
|
|
22
23
|
for val in value:
|
|
23
24
|
overlap = all_variables.intersection(val.memory_variables)
|
|
24
25
|
if overlap:
|
|
25
|
-
|
|
26
|
+
msg = (
|
|
26
27
|
f"The same variables {overlap} are found in multiple"
|
|
27
28
|
"memory object, which is not allowed by CombinedMemory."
|
|
28
29
|
)
|
|
30
|
+
raise ValueError(msg)
|
|
29
31
|
all_variables |= set(val.memory_variables)
|
|
30
32
|
|
|
31
33
|
return value
|
|
@@ -35,13 +37,13 @@ class CombinedMemory(BaseMemory):
|
|
|
35
37
|
def check_input_key(cls, value: list[BaseMemory]) -> list[BaseMemory]:
|
|
36
38
|
"""Check that if memories are of type BaseChatMemory that input keys exist."""
|
|
37
39
|
for val in value:
|
|
38
|
-
if isinstance(val, BaseChatMemory):
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
if isinstance(val, BaseChatMemory) and val.input_key is None:
|
|
41
|
+
warnings.warn(
|
|
42
|
+
"When using CombinedMemory, "
|
|
43
|
+
"input keys should be so the input is known. "
|
|
44
|
+
f" Was not set on {val}",
|
|
45
|
+
stacklevel=5,
|
|
46
|
+
)
|
|
45
47
|
return value
|
|
46
48
|
|
|
47
49
|
@property
|
|
@@ -65,9 +67,8 @@ class CombinedMemory(BaseMemory):
|
|
|
65
67
|
data = memory.load_memory_variables(inputs)
|
|
66
68
|
for key, value in data.items():
|
|
67
69
|
if key in memory_data:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
)
|
|
70
|
+
msg = f"The variable {key} is repeated in the CombinedMemory."
|
|
71
|
+
raise ValueError(msg)
|
|
71
72
|
memory_data[key] = value
|
|
72
73
|
|
|
73
74
|
return memory_data
|
langchain/memory/entity.py
CHANGED
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from collections.abc import Iterable
|
|
6
6
|
from itertools import islice
|
|
7
|
-
from typing import Any, Optional
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
8
8
|
|
|
9
9
|
from langchain_core._api import deprecated
|
|
10
10
|
from langchain_core.language_models import BaseLanguageModel
|
|
@@ -20,6 +20,9 @@ from langchain.memory.prompt import (
|
|
|
20
20
|
)
|
|
21
21
|
from langchain.memory.utils import get_prompt_input_key
|
|
22
22
|
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
import sqlite3
|
|
25
|
+
|
|
23
26
|
logger = logging.getLogger(__name__)
|
|
24
27
|
|
|
25
28
|
|
|
@@ -37,27 +40,22 @@ class BaseEntityStore(BaseModel, ABC):
|
|
|
37
40
|
@abstractmethod
|
|
38
41
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
39
42
|
"""Get entity value from store."""
|
|
40
|
-
pass
|
|
41
43
|
|
|
42
44
|
@abstractmethod
|
|
43
45
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
44
46
|
"""Set entity value in store."""
|
|
45
|
-
pass
|
|
46
47
|
|
|
47
48
|
@abstractmethod
|
|
48
49
|
def delete(self, key: str) -> None:
|
|
49
50
|
"""Delete entity value from store."""
|
|
50
|
-
pass
|
|
51
51
|
|
|
52
52
|
@abstractmethod
|
|
53
53
|
def exists(self, key: str) -> bool:
|
|
54
54
|
"""Check if entity exists in store."""
|
|
55
|
-
pass
|
|
56
55
|
|
|
57
56
|
@abstractmethod
|
|
58
57
|
def clear(self) -> None:
|
|
59
58
|
"""Delete all entities from store."""
|
|
60
|
-
pass
|
|
61
59
|
|
|
62
60
|
|
|
63
61
|
@deprecated(
|
|
@@ -117,18 +115,21 @@ class UpstashRedisEntityStore(BaseEntityStore):
|
|
|
117
115
|
):
|
|
118
116
|
try:
|
|
119
117
|
from upstash_redis import Redis
|
|
120
|
-
except ImportError:
|
|
121
|
-
|
|
118
|
+
except ImportError as e:
|
|
119
|
+
msg = (
|
|
122
120
|
"Could not import upstash_redis python package. "
|
|
123
121
|
"Please install it with `pip install upstash_redis`."
|
|
124
122
|
)
|
|
123
|
+
raise ImportError(msg) from e
|
|
125
124
|
|
|
126
125
|
super().__init__(*args, **kwargs)
|
|
127
126
|
|
|
128
127
|
try:
|
|
129
128
|
self.redis_client = Redis(url=url, token=token)
|
|
130
|
-
except Exception:
|
|
131
|
-
|
|
129
|
+
except Exception as exc:
|
|
130
|
+
error_msg = "Upstash Redis instance could not be initiated"
|
|
131
|
+
logger.exception(error_msg)
|
|
132
|
+
raise RuntimeError(error_msg) from exc
|
|
132
133
|
|
|
133
134
|
self.session_id = session_id
|
|
134
135
|
self.key_prefix = key_prefix
|
|
@@ -145,7 +146,9 @@ class UpstashRedisEntityStore(BaseEntityStore):
|
|
|
145
146
|
or default
|
|
146
147
|
or ""
|
|
147
148
|
)
|
|
148
|
-
logger.debug(
|
|
149
|
+
logger.debug(
|
|
150
|
+
"Upstash Redis MEM get '%s:%s': '%s'", self.full_key_prefix, key, res
|
|
151
|
+
)
|
|
149
152
|
return res
|
|
150
153
|
|
|
151
154
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
@@ -153,8 +156,13 @@ class UpstashRedisEntityStore(BaseEntityStore):
|
|
|
153
156
|
return self.delete(key)
|
|
154
157
|
self.redis_client.set(f"{self.full_key_prefix}:{key}", value, ex=self.ttl)
|
|
155
158
|
logger.debug(
|
|
156
|
-
|
|
159
|
+
"Redis MEM set '%s:%s': '%s' EX %s",
|
|
160
|
+
self.full_key_prefix,
|
|
161
|
+
key,
|
|
162
|
+
value,
|
|
163
|
+
self.ttl,
|
|
157
164
|
)
|
|
165
|
+
return None
|
|
158
166
|
|
|
159
167
|
def delete(self, key: str) -> None:
|
|
160
168
|
self.redis_client.delete(f"{self.full_key_prefix}:{key}")
|
|
@@ -165,7 +173,8 @@ class UpstashRedisEntityStore(BaseEntityStore):
|
|
|
165
173
|
def clear(self) -> None:
|
|
166
174
|
def scan_and_delete(cursor: int) -> int:
|
|
167
175
|
cursor, keys_to_delete = self.redis_client.scan(
|
|
168
|
-
cursor,
|
|
176
|
+
cursor,
|
|
177
|
+
f"{self.full_key_prefix}:*",
|
|
169
178
|
)
|
|
170
179
|
self.redis_client.delete(*keys_to_delete)
|
|
171
180
|
return cursor
|
|
@@ -208,26 +217,28 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
208
217
|
):
|
|
209
218
|
try:
|
|
210
219
|
import redis
|
|
211
|
-
except ImportError:
|
|
212
|
-
|
|
220
|
+
except ImportError as e:
|
|
221
|
+
msg = (
|
|
213
222
|
"Could not import redis python package. "
|
|
214
223
|
"Please install it with `pip install redis`."
|
|
215
224
|
)
|
|
225
|
+
raise ImportError(msg) from e
|
|
216
226
|
|
|
217
227
|
super().__init__(*args, **kwargs)
|
|
218
228
|
|
|
219
229
|
try:
|
|
220
230
|
from langchain_community.utilities.redis import get_client
|
|
221
|
-
except ImportError:
|
|
222
|
-
|
|
231
|
+
except ImportError as e:
|
|
232
|
+
msg = (
|
|
223
233
|
"Could not import langchain_community.utilities.redis.get_client. "
|
|
224
234
|
"Please install it with `pip install langchain-community`."
|
|
225
235
|
)
|
|
236
|
+
raise ImportError(msg) from e
|
|
226
237
|
|
|
227
238
|
try:
|
|
228
239
|
self.redis_client = get_client(redis_url=url, decode_responses=True)
|
|
229
|
-
except redis.exceptions.ConnectionError
|
|
230
|
-
logger.
|
|
240
|
+
except redis.exceptions.ConnectionError:
|
|
241
|
+
logger.exception("Redis client could not connect")
|
|
231
242
|
|
|
232
243
|
self.session_id = session_id
|
|
233
244
|
self.key_prefix = key_prefix
|
|
@@ -244,7 +255,7 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
244
255
|
or default
|
|
245
256
|
or ""
|
|
246
257
|
)
|
|
247
|
-
logger.debug(
|
|
258
|
+
logger.debug("REDIS MEM get '%s:%s': '%s'", self.full_key_prefix, key, res)
|
|
248
259
|
return res
|
|
249
260
|
|
|
250
261
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
@@ -252,8 +263,13 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
252
263
|
return self.delete(key)
|
|
253
264
|
self.redis_client.set(f"{self.full_key_prefix}:{key}", value, ex=self.ttl)
|
|
254
265
|
logger.debug(
|
|
255
|
-
|
|
266
|
+
"REDIS MEM set '%s:%s': '%s' EX %s",
|
|
267
|
+
self.full_key_prefix,
|
|
268
|
+
key,
|
|
269
|
+
value,
|
|
270
|
+
self.ttl,
|
|
256
271
|
)
|
|
272
|
+
return None
|
|
257
273
|
|
|
258
274
|
def delete(self, key: str) -> None:
|
|
259
275
|
self.redis_client.delete(f"{self.full_key_prefix}:{key}")
|
|
@@ -269,7 +285,8 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
269
285
|
yield batch
|
|
270
286
|
|
|
271
287
|
for keybatch in batched(
|
|
272
|
-
self.redis_client.scan_iter(f"{self.full_key_prefix}:*"),
|
|
288
|
+
self.redis_client.scan_iter(f"{self.full_key_prefix}:*"),
|
|
289
|
+
500,
|
|
273
290
|
):
|
|
274
291
|
self.redis_client.delete(*keybatch)
|
|
275
292
|
|
|
@@ -283,7 +300,7 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
283
300
|
),
|
|
284
301
|
)
|
|
285
302
|
class SQLiteEntityStore(BaseEntityStore):
|
|
286
|
-
"""SQLite-backed Entity store"""
|
|
303
|
+
"""SQLite-backed Entity store with safe query construction."""
|
|
287
304
|
|
|
288
305
|
session_id: str = "default"
|
|
289
306
|
table_name: str = "memory_store"
|
|
@@ -301,14 +318,21 @@ class SQLiteEntityStore(BaseEntityStore):
|
|
|
301
318
|
*args: Any,
|
|
302
319
|
**kwargs: Any,
|
|
303
320
|
):
|
|
321
|
+
super().__init__(*args, **kwargs)
|
|
304
322
|
try:
|
|
305
323
|
import sqlite3
|
|
306
|
-
except ImportError:
|
|
307
|
-
|
|
324
|
+
except ImportError as e:
|
|
325
|
+
msg = (
|
|
308
326
|
"Could not import sqlite3 python package. "
|
|
309
327
|
"Please install it with `pip install sqlite3`."
|
|
310
328
|
)
|
|
311
|
-
|
|
329
|
+
raise ImportError(msg) from e
|
|
330
|
+
|
|
331
|
+
# Basic validation to prevent obviously malicious table/session names
|
|
332
|
+
if not table_name.isidentifier() or not session_id.isidentifier():
|
|
333
|
+
# Since we validate here, we can safely suppress the S608 bandit warning
|
|
334
|
+
msg = "Table name and session ID must be valid Python identifiers."
|
|
335
|
+
raise ValueError(msg)
|
|
312
336
|
|
|
313
337
|
self.conn = sqlite3.connect(db_file)
|
|
314
338
|
self.session_id = session_id
|
|
@@ -319,62 +343,61 @@ class SQLiteEntityStore(BaseEntityStore):
|
|
|
319
343
|
def full_table_name(self) -> str:
|
|
320
344
|
return f"{self.table_name}_{self.session_id}"
|
|
321
345
|
|
|
346
|
+
def _execute_query(self, query: str, params: tuple = ()) -> "sqlite3.Cursor":
|
|
347
|
+
"""Executes a query with proper connection handling."""
|
|
348
|
+
with self.conn:
|
|
349
|
+
return self.conn.execute(query, params)
|
|
350
|
+
|
|
322
351
|
def _create_table_if_not_exists(self) -> None:
|
|
352
|
+
"""Creates the entity table if it doesn't exist, using safe quoting."""
|
|
353
|
+
# Use standard SQL double quotes for the table name identifier
|
|
323
354
|
create_table_query = f"""
|
|
324
|
-
CREATE TABLE IF NOT EXISTS {self.full_table_name} (
|
|
355
|
+
CREATE TABLE IF NOT EXISTS "{self.full_table_name}" (
|
|
325
356
|
key TEXT PRIMARY KEY,
|
|
326
357
|
value TEXT
|
|
327
358
|
)
|
|
328
359
|
"""
|
|
329
|
-
|
|
330
|
-
self.conn.execute(create_table_query)
|
|
360
|
+
self._execute_query(create_table_query)
|
|
331
361
|
|
|
332
362
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
cursor = self.conn.execute(query, (key,))
|
|
363
|
+
"""Retrieves a value, safely quoting the table name."""
|
|
364
|
+
# `?` placeholder is used for the value to prevent SQL injection
|
|
365
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
366
|
+
query = f'SELECT value FROM "{self.full_table_name}" WHERE key = ?' # noqa: S608
|
|
367
|
+
cursor = self._execute_query(query, (key,))
|
|
339
368
|
result = cursor.fetchone()
|
|
340
|
-
if result is not None
|
|
341
|
-
value = result[0]
|
|
342
|
-
return value
|
|
343
|
-
return default
|
|
369
|
+
return result[0] if result is not None else default
|
|
344
370
|
|
|
345
371
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
372
|
+
"""Inserts or replaces a value, safely quoting the table name."""
|
|
346
373
|
if not value:
|
|
347
374
|
return self.delete(key)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
375
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
376
|
+
query = (
|
|
377
|
+
"INSERT OR REPLACE INTO " # noqa: S608
|
|
378
|
+
f'"{self.full_table_name}" (key, value) VALUES (?, ?)'
|
|
379
|
+
)
|
|
380
|
+
self._execute_query(query, (key, value))
|
|
381
|
+
return None
|
|
354
382
|
|
|
355
383
|
def delete(self, key: str) -> None:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
with self.conn:
|
|
361
|
-
self.conn.execute(query, (key,))
|
|
384
|
+
"""Deletes a key-value pair, safely quoting the table name."""
|
|
385
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
386
|
+
query = f'DELETE FROM "{self.full_table_name}" WHERE key = ?' # noqa: S608
|
|
387
|
+
self._execute_query(query, (key,))
|
|
362
388
|
|
|
363
389
|
def exists(self, key: str) -> bool:
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
"""
|
|
370
|
-
cursor = self.conn.execute(query, (key,))
|
|
371
|
-
result = cursor.fetchone()
|
|
372
|
-
return result is not None
|
|
390
|
+
"""Checks for the existence of a key, safely quoting the table name."""
|
|
391
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
392
|
+
query = f'SELECT 1 FROM "{self.full_table_name}" WHERE key = ? LIMIT 1' # noqa: S608
|
|
393
|
+
cursor = self._execute_query(query, (key,))
|
|
394
|
+
return cursor.fetchone() is not None
|
|
373
395
|
|
|
374
396
|
def clear(self) -> None:
|
|
397
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
375
398
|
query = f"""
|
|
376
399
|
DELETE FROM {self.full_table_name}
|
|
377
|
-
"""
|
|
400
|
+
""" # noqa: S608
|
|
378
401
|
with self.conn:
|
|
379
402
|
self.conn.execute(query)
|
|
380
403
|
|
langchain/memory/prompt.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# flake8: noqa
|
|
2
1
|
from langchain_core.prompts.prompt import PromptTemplate
|
|
3
2
|
|
|
4
3
|
_DEFAULT_ENTITY_MEMORY_CONVERSATION_TEMPLATE = """You are an assistant to a human, powered by a large language model trained by OpenAI.
|
|
@@ -16,7 +15,7 @@ Current conversation:
|
|
|
16
15
|
{history}
|
|
17
16
|
Last line:
|
|
18
17
|
Human: {input}
|
|
19
|
-
You:"""
|
|
18
|
+
You:""" # noqa: E501
|
|
20
19
|
|
|
21
20
|
ENTITY_MEMORY_CONVERSATION_TEMPLATE = PromptTemplate(
|
|
22
21
|
input_variables=["entities", "history", "input"],
|
|
@@ -43,7 +42,7 @@ Current summary:
|
|
|
43
42
|
New lines of conversation:
|
|
44
43
|
{new_lines}
|
|
45
44
|
|
|
46
|
-
New summary:"""
|
|
45
|
+
New summary:""" # noqa: E501
|
|
47
46
|
SUMMARY_PROMPT = PromptTemplate(
|
|
48
47
|
input_variables=["summary", "new_lines"], template=_DEFAULT_SUMMARIZER_TEMPLATE
|
|
49
48
|
)
|
|
@@ -81,7 +80,7 @@ Conversation history (for reference only):
|
|
|
81
80
|
Last line of conversation (for extraction):
|
|
82
81
|
Human: {input}
|
|
83
82
|
|
|
84
|
-
Output:"""
|
|
83
|
+
Output:""" # noqa: E501
|
|
85
84
|
ENTITY_EXTRACTION_PROMPT = PromptTemplate(
|
|
86
85
|
input_variables=["history", "input"], template=_DEFAULT_ENTITY_EXTRACTION_TEMPLATE
|
|
87
86
|
)
|
|
@@ -102,7 +101,7 @@ Existing summary of {entity}:
|
|
|
102
101
|
|
|
103
102
|
Last line of conversation:
|
|
104
103
|
Human: {input}
|
|
105
|
-
Updated summary:"""
|
|
104
|
+
Updated summary:""" # noqa: E501
|
|
106
105
|
|
|
107
106
|
ENTITY_SUMMARIZATION_PROMPT = PromptTemplate(
|
|
108
107
|
input_variables=["entity", "summary", "history", "input"],
|
|
@@ -128,7 +127,7 @@ _DEFAULT_KNOWLEDGE_TRIPLE_EXTRACTION_TEMPLATE = (
|
|
|
128
127
|
"Person #1: It's a secret military base in Nevada.\n"
|
|
129
128
|
"AI: What do you know about Nevada?\n"
|
|
130
129
|
"Last line of conversation:\n"
|
|
131
|
-
"Person #1: It's a state in the US. It's also the number 1 producer of gold in the US.\n\n"
|
|
130
|
+
"Person #1: It's a state in the US. It's also the number 1 producer of gold in the US.\n\n" # noqa: E501
|
|
132
131
|
f"Output: (Nevada, is a, state){KG_TRIPLE_DELIMITER}(Nevada, is in, US)"
|
|
133
132
|
f"{KG_TRIPLE_DELIMITER}(Nevada, is the number 1 producer of, gold)\n"
|
|
134
133
|
"END OF EXAMPLE\n\n"
|
|
@@ -145,12 +144,12 @@ _DEFAULT_KNOWLEDGE_TRIPLE_EXTRACTION_TEMPLATE = (
|
|
|
145
144
|
"EXAMPLE\n"
|
|
146
145
|
"Conversation history:\n"
|
|
147
146
|
"Person #1: What do you know about Descartes?\n"
|
|
148
|
-
"AI: Descartes was a French philosopher, mathematician, and scientist who lived in the 17th century.\n"
|
|
149
|
-
"Person #1: The Descartes I'm referring to is a standup comedian and interior designer from Montreal.\n"
|
|
150
|
-
"AI: Oh yes, He is a comedian and an interior designer. He has been in the industry for 30 years. His favorite food is baked bean pie.\n"
|
|
147
|
+
"AI: Descartes was a French philosopher, mathematician, and scientist who lived in the 17th century.\n" # noqa: E501
|
|
148
|
+
"Person #1: The Descartes I'm referring to is a standup comedian and interior designer from Montreal.\n" # noqa: E501
|
|
149
|
+
"AI: Oh yes, He is a comedian and an interior designer. He has been in the industry for 30 years. His favorite food is baked bean pie.\n" # noqa: E501
|
|
151
150
|
"Last line of conversation:\n"
|
|
152
|
-
"Person #1: Oh huh. I know Descartes likes to drive antique scooters and play the mandolin.\n"
|
|
153
|
-
f"Output: (Descartes, likes to drive, antique scooters){KG_TRIPLE_DELIMITER}(Descartes, plays, mandolin)\n"
|
|
151
|
+
"Person #1: Oh huh. I know Descartes likes to drive antique scooters and play the mandolin.\n" # noqa: E501
|
|
152
|
+
f"Output: (Descartes, likes to drive, antique scooters){KG_TRIPLE_DELIMITER}(Descartes, plays, mandolin)\n" # noqa: E501
|
|
154
153
|
"END OF EXAMPLE\n\n"
|
|
155
154
|
"Conversation history (for reference only):\n"
|
|
156
155
|
"{history}"
|
langchain/memory/readonly.py
CHANGED
|
@@ -19,8 +19,6 @@ class ReadOnlySharedMemory(BaseMemory):
|
|
|
19
19
|
|
|
20
20
|
def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
|
|
21
21
|
"""Nothing should be saved or changed"""
|
|
22
|
-
pass
|
|
23
22
|
|
|
24
23
|
def clear(self) -> None:
|
|
25
24
|
"""Nothing to clear, got a memory like a vault."""
|
|
26
|
-
pass
|
langchain/memory/simple.py
CHANGED
|
@@ -8,7 +8,7 @@ class SimpleMemory(BaseMemory):
|
|
|
8
8
|
ever change between prompts.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
memories: dict[str, Any] =
|
|
11
|
+
memories: dict[str, Any] = {}
|
|
12
12
|
|
|
13
13
|
@property
|
|
14
14
|
def memory_variables(self) -> list[str]:
|
|
@@ -19,8 +19,6 @@ class SimpleMemory(BaseMemory):
|
|
|
19
19
|
|
|
20
20
|
def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
|
|
21
21
|
"""Nothing should be saved or changed, my memory is set in stone."""
|
|
22
|
-
pass
|
|
23
22
|
|
|
24
23
|
def clear(self) -> None:
|
|
25
24
|
"""Nothing to clear, got a memory like a vault."""
|
|
26
|
-
pass
|
langchain/memory/summary.py
CHANGED
|
@@ -3,8 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from langchain_core._api import deprecated
|
|
6
|
-
from langchain_core.caches import BaseCache as BaseCache # For model_rebuild
|
|
7
|
-
from langchain_core.callbacks import Callbacks as Callbacks # For model_rebuild
|
|
8
6
|
from langchain_core.chat_history import BaseChatMessageHistory
|
|
9
7
|
from langchain_core.language_models import BaseLanguageModel
|
|
10
8
|
from langchain_core.messages import BaseMessage, SystemMessage, get_buffer_string
|
|
@@ -22,7 +20,7 @@ from langchain.memory.prompt import SUMMARY_PROMPT
|
|
|
22
20
|
removal="1.0",
|
|
23
21
|
message=(
|
|
24
22
|
"Refer here for how to incorporate summaries of conversation history: "
|
|
25
|
-
"https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/"
|
|
23
|
+
"https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/"
|
|
26
24
|
),
|
|
27
25
|
)
|
|
28
26
|
class SummarizerMixin(BaseModel):
|
|
@@ -35,7 +33,9 @@ class SummarizerMixin(BaseModel):
|
|
|
35
33
|
summary_message_cls: type[BaseMessage] = SystemMessage
|
|
36
34
|
|
|
37
35
|
def predict_new_summary(
|
|
38
|
-
self,
|
|
36
|
+
self,
|
|
37
|
+
messages: list[BaseMessage],
|
|
38
|
+
existing_summary: str,
|
|
39
39
|
) -> str:
|
|
40
40
|
new_lines = get_buffer_string(
|
|
41
41
|
messages,
|
|
@@ -47,7 +47,9 @@ class SummarizerMixin(BaseModel):
|
|
|
47
47
|
return chain.predict(summary=existing_summary, new_lines=new_lines)
|
|
48
48
|
|
|
49
49
|
async def apredict_new_summary(
|
|
50
|
-
self,
|
|
50
|
+
self,
|
|
51
|
+
messages: list[BaseMessage],
|
|
52
|
+
existing_summary: str,
|
|
51
53
|
) -> str:
|
|
52
54
|
new_lines = get_buffer_string(
|
|
53
55
|
messages,
|
|
@@ -90,7 +92,8 @@ class ConversationSummaryMemory(BaseChatMemory, SummarizerMixin):
|
|
|
90
92
|
obj = cls(llm=llm, chat_memory=chat_memory, **kwargs)
|
|
91
93
|
for i in range(0, len(obj.chat_memory.messages), summarize_step):
|
|
92
94
|
obj.buffer = obj.predict_new_summary(
|
|
93
|
-
obj.chat_memory.messages[i : i + summarize_step],
|
|
95
|
+
obj.chat_memory.messages[i : i + summarize_step],
|
|
96
|
+
obj.buffer,
|
|
94
97
|
)
|
|
95
98
|
return obj
|
|
96
99
|
|
|
@@ -116,23 +119,22 @@ class ConversationSummaryMemory(BaseChatMemory, SummarizerMixin):
|
|
|
116
119
|
prompt_variables = values["prompt"].input_variables
|
|
117
120
|
expected_keys = {"summary", "new_lines"}
|
|
118
121
|
if expected_keys != set(prompt_variables):
|
|
119
|
-
|
|
122
|
+
msg = (
|
|
120
123
|
"Got unexpected prompt input variables. The prompt expects "
|
|
121
124
|
f"{prompt_variables}, but it should have {expected_keys}."
|
|
122
125
|
)
|
|
126
|
+
raise ValueError(msg)
|
|
123
127
|
return values
|
|
124
128
|
|
|
125
129
|
def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
|
|
126
130
|
"""Save context from this conversation to buffer."""
|
|
127
131
|
super().save_context(inputs, outputs)
|
|
128
132
|
self.buffer = self.predict_new_summary(
|
|
129
|
-
self.chat_memory.messages[-2:],
|
|
133
|
+
self.chat_memory.messages[-2:],
|
|
134
|
+
self.buffer,
|
|
130
135
|
)
|
|
131
136
|
|
|
132
137
|
def clear(self) -> None:
|
|
133
138
|
"""Clear memory contents."""
|
|
134
139
|
super().clear()
|
|
135
140
|
self.buffer = ""
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
ConversationSummaryMemory.model_rebuild()
|
|
@@ -51,14 +51,16 @@ class ConversationSummaryBufferMemory(BaseChatMemory, SummarizerMixin):
|
|
|
51
51
|
buffer = self.chat_memory.messages
|
|
52
52
|
if self.moving_summary_buffer != "":
|
|
53
53
|
first_messages: list[BaseMessage] = [
|
|
54
|
-
self.summary_message_cls(content=self.moving_summary_buffer)
|
|
54
|
+
self.summary_message_cls(content=self.moving_summary_buffer),
|
|
55
55
|
]
|
|
56
56
|
buffer = first_messages + buffer
|
|
57
57
|
if self.return_messages:
|
|
58
58
|
final_buffer: Any = buffer
|
|
59
59
|
else:
|
|
60
60
|
final_buffer = get_buffer_string(
|
|
61
|
-
buffer,
|
|
61
|
+
buffer,
|
|
62
|
+
human_prefix=self.human_prefix,
|
|
63
|
+
ai_prefix=self.ai_prefix,
|
|
62
64
|
)
|
|
63
65
|
return {self.memory_key: final_buffer}
|
|
64
66
|
|
|
@@ -67,14 +69,16 @@ class ConversationSummaryBufferMemory(BaseChatMemory, SummarizerMixin):
|
|
|
67
69
|
buffer = await self.chat_memory.aget_messages()
|
|
68
70
|
if self.moving_summary_buffer != "":
|
|
69
71
|
first_messages: list[BaseMessage] = [
|
|
70
|
-
self.summary_message_cls(content=self.moving_summary_buffer)
|
|
72
|
+
self.summary_message_cls(content=self.moving_summary_buffer),
|
|
71
73
|
]
|
|
72
74
|
buffer = first_messages + buffer
|
|
73
75
|
if self.return_messages:
|
|
74
76
|
final_buffer: Any = buffer
|
|
75
77
|
else:
|
|
76
78
|
final_buffer = get_buffer_string(
|
|
77
|
-
buffer,
|
|
79
|
+
buffer,
|
|
80
|
+
human_prefix=self.human_prefix,
|
|
81
|
+
ai_prefix=self.ai_prefix,
|
|
78
82
|
)
|
|
79
83
|
return {self.memory_key: final_buffer}
|
|
80
84
|
|
|
@@ -84,10 +88,11 @@ class ConversationSummaryBufferMemory(BaseChatMemory, SummarizerMixin):
|
|
|
84
88
|
prompt_variables = values["prompt"].input_variables
|
|
85
89
|
expected_keys = {"summary", "new_lines"}
|
|
86
90
|
if expected_keys != set(prompt_variables):
|
|
87
|
-
|
|
91
|
+
msg = (
|
|
88
92
|
"Got unexpected prompt input variables. The prompt expects "
|
|
89
93
|
f"{prompt_variables}, but it should have {expected_keys}."
|
|
90
94
|
)
|
|
95
|
+
raise ValueError(msg)
|
|
91
96
|
return values
|
|
92
97
|
|
|
93
98
|
def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
|
|
@@ -96,7 +101,9 @@ class ConversationSummaryBufferMemory(BaseChatMemory, SummarizerMixin):
|
|
|
96
101
|
self.prune()
|
|
97
102
|
|
|
98
103
|
async def asave_context(
|
|
99
|
-
self,
|
|
104
|
+
self,
|
|
105
|
+
inputs: dict[str, Any],
|
|
106
|
+
outputs: dict[str, str],
|
|
100
107
|
) -> None:
|
|
101
108
|
"""Asynchronously save context from this conversation to buffer."""
|
|
102
109
|
await super().asave_context(inputs, outputs)
|
|
@@ -112,7 +119,8 @@ class ConversationSummaryBufferMemory(BaseChatMemory, SummarizerMixin):
|
|
|
112
119
|
pruned_memory.append(buffer.pop(0))
|
|
113
120
|
curr_buffer_length = self.llm.get_num_tokens_from_messages(buffer)
|
|
114
121
|
self.moving_summary_buffer = self.predict_new_summary(
|
|
115
|
-
pruned_memory,
|
|
122
|
+
pruned_memory,
|
|
123
|
+
self.moving_summary_buffer,
|
|
116
124
|
)
|
|
117
125
|
|
|
118
126
|
async def aprune(self) -> None:
|
|
@@ -125,7 +133,8 @@ class ConversationSummaryBufferMemory(BaseChatMemory, SummarizerMixin):
|
|
|
125
133
|
pruned_memory.append(buffer.pop(0))
|
|
126
134
|
curr_buffer_length = self.llm.get_num_tokens_from_messages(buffer)
|
|
127
135
|
self.moving_summary_buffer = await self.apredict_new_summary(
|
|
128
|
-
pruned_memory,
|
|
136
|
+
pruned_memory,
|
|
137
|
+
self.moving_summary_buffer,
|
|
129
138
|
)
|
|
130
139
|
|
|
131
140
|
def clear(self) -> None:
|