langchain 0.3.26__py3-none-any.whl → 0.4.0.dev0__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.
- 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 +174 -151
- langchain/agents/agent_iterator.py +50 -26
- 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 +4 -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 +8 -12
- langchain/agents/chat/output_parser.py +9 -6
- langchain/agents/chat/prompt.py +3 -4
- langchain/agents/conversational/base.py +11 -5
- langchain/agents/conversational/output_parser.py +4 -2
- langchain/agents/conversational/prompt.py +2 -3
- langchain/agents/conversational_chat/base.py +9 -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 +17 -9
- langchain/agents/json_chat/base.py +19 -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 +11 -4
- langchain/agents/mrkl/output_parser.py +17 -13
- langchain/agents/mrkl/prompt.py +1 -2
- langchain/agents/openai_assistant/base.py +81 -71
- langchain/agents/openai_functions_agent/agent_token_buffer_memory.py +2 -0
- langchain/agents/openai_functions_agent/base.py +47 -37
- langchain/agents/openai_functions_multi_agent/base.py +40 -27
- langchain/agents/openai_tools/base.py +9 -8
- langchain/agents/output_parsers/__init__.py +3 -3
- langchain/agents/output_parsers/json.py +8 -6
- langchain/agents/output_parsers/openai_functions.py +24 -9
- langchain/agents/output_parsers/openai_tools.py +16 -4
- langchain/agents/output_parsers/react_json_single_input.py +13 -5
- langchain/agents/output_parsers/react_single_input.py +18 -11
- langchain/agents/output_parsers/self_ask.py +5 -2
- langchain/agents/output_parsers/tools.py +32 -13
- langchain/agents/output_parsers/xml.py +102 -28
- langchain/agents/react/agent.py +5 -4
- langchain/agents/react/base.py +26 -17
- langchain/agents/react/output_parser.py +7 -6
- langchain/agents/react/textworld_prompt.py +0 -1
- langchain/agents/react/wiki_prompt.py +14 -15
- langchain/agents/schema.py +5 -2
- langchain/agents/self_ask_with_search/base.py +23 -15
- langchain/agents/self_ask_with_search/prompt.py +0 -1
- langchain/agents/structured_chat/base.py +19 -11
- langchain/agents/structured_chat/output_parser.py +29 -18
- langchain/agents/structured_chat/prompt.py +3 -4
- langchain/agents/tool_calling_agent/base.py +8 -6
- langchain/agents/tools.py +5 -2
- langchain/agents/utils.py +2 -3
- langchain/agents/xml/base.py +12 -6
- 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 +17 -3
- langchain/callbacks/streaming_aiter_final_only.py +16 -5
- langchain/callbacks/streaming_stdout_final_only.py +10 -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 +12 -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 +41 -23
- 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 +96 -56
- langchain/chains/chat_vector_db/prompts.py +2 -3
- langchain/chains/combine_documents/__init__.py +1 -1
- langchain/chains/combine_documents/base.py +30 -11
- langchain/chains/combine_documents/map_reduce.py +41 -30
- langchain/chains/combine_documents/map_rerank.py +39 -24
- langchain/chains/combine_documents/reduce.py +48 -26
- langchain/chains/combine_documents/refine.py +27 -17
- langchain/chains/combine_documents/stuff.py +24 -13
- langchain/chains/constitutional_ai/base.py +11 -4
- langchain/chains/constitutional_ai/principles.py +22 -25
- langchain/chains/constitutional_ai/prompts.py +25 -28
- langchain/chains/conversation/base.py +9 -4
- langchain/chains/conversation/memory.py +5 -5
- langchain/chains/conversation/prompt.py +5 -5
- langchain/chains/conversational_retrieval/base.py +108 -79
- langchain/chains/conversational_retrieval/prompts.py +2 -3
- langchain/chains/elasticsearch_database/base.py +10 -10
- 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 +28 -12
- langchain/chains/flare/prompts.py +2 -0
- 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 +82 -61
- langchain/chains/llm_bash/__init__.py +3 -2
- langchain/chains/llm_checker/base.py +19 -6
- langchain/chains/llm_checker/prompt.py +3 -4
- langchain/chains/llm_math/base.py +25 -10
- langchain/chains/llm_math/prompt.py +1 -2
- langchain/chains/llm_summarization_checker/base.py +22 -7
- langchain/chains/llm_symbolic_math/__init__.py +3 -2
- langchain/chains/loading.py +155 -97
- langchain/chains/mapreduce.py +4 -3
- langchain/chains/moderation.py +11 -9
- langchain/chains/natbot/base.py +11 -9
- langchain/chains/natbot/crawler.py +102 -76
- langchain/chains/natbot/prompt.py +2 -3
- langchain/chains/openai_functions/__init__.py +7 -7
- langchain/chains/openai_functions/base.py +15 -10
- langchain/chains/openai_functions/citation_fuzzy_match.py +21 -11
- langchain/chains/openai_functions/extraction.py +19 -19
- langchain/chains/openai_functions/openapi.py +39 -35
- langchain/chains/openai_functions/qa_with_structure.py +22 -15
- langchain/chains/openai_functions/tagging.py +4 -4
- langchain/chains/openai_tools/extraction.py +7 -8
- langchain/chains/qa_generation/base.py +8 -3
- langchain/chains/qa_generation/prompt.py +5 -5
- langchain/chains/qa_with_sources/base.py +17 -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 +15 -6
- langchain/chains/qa_with_sources/stuff_prompt.py +6 -7
- langchain/chains/qa_with_sources/vector_db.py +21 -8
- langchain/chains/query_constructor/base.py +37 -34
- langchain/chains/query_constructor/ir.py +4 -4
- langchain/chains/query_constructor/parser.py +101 -34
- 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 +38 -27
- langchain/chains/retrieval_qa/prompt.py +1 -2
- langchain/chains/router/__init__.py +3 -3
- langchain/chains/router/base.py +38 -22
- langchain/chains/router/embedding_router.py +15 -8
- langchain/chains/router/llm_router.py +23 -20
- langchain/chains/router/multi_prompt.py +5 -2
- langchain/chains/router/multi_retrieval_qa.py +28 -5
- langchain/chains/sequential.py +30 -18
- langchain/chains/sql_database/prompt.py +14 -16
- langchain/chains/sql_database/query.py +7 -5
- langchain/chains/structured_output/__init__.py +1 -1
- langchain/chains/structured_output/base.py +77 -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 +9 -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 +213 -139
- 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/blob_loaders/schema.py +1 -4
- 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 +35 -24
- langchain/embeddings/cache.py +37 -32
- 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 +26 -25
- langchain/evaluation/agents/trajectory_eval_prompt.py +6 -9
- langchain/evaluation/comparison/__init__.py +1 -1
- langchain/evaluation/comparison/eval_chain.py +21 -13
- langchain/evaluation/comparison/prompt.py +1 -2
- langchain/evaluation/criteria/__init__.py +1 -1
- langchain/evaluation/criteria/eval_chain.py +23 -11
- langchain/evaluation/criteria/prompt.py +2 -3
- langchain/evaluation/embedding_distance/base.py +34 -20
- langchain/evaluation/exact_match/base.py +14 -1
- langchain/evaluation/loading.py +16 -11
- langchain/evaluation/parsing/base.py +20 -4
- langchain/evaluation/parsing/json_distance.py +24 -10
- langchain/evaluation/parsing/json_schema.py +13 -12
- langchain/evaluation/qa/__init__.py +1 -1
- langchain/evaluation/qa/eval_chain.py +20 -5
- langchain/evaluation/qa/eval_prompt.py +7 -8
- langchain/evaluation/qa/generate_chain.py +4 -1
- langchain/evaluation/qa/generate_prompt.py +2 -4
- langchain/evaluation/regex_match/base.py +9 -1
- langchain/evaluation/schema.py +38 -30
- langchain/evaluation/scoring/__init__.py +1 -1
- langchain/evaluation/scoring/eval_chain.py +23 -15
- langchain/evaluation/scoring/prompt.py +0 -1
- langchain/evaluation/string_distance/base.py +20 -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 +14 -7
- langchain/memory/buffer_window.py +2 -0
- 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 +14 -13
- langchain/memory/entity.py +131 -61
- langchain/memory/prompt.py +10 -11
- langchain/memory/readonly.py +0 -2
- langchain/memory/simple.py +4 -3
- langchain/memory/summary.py +43 -11
- langchain/memory/summary_buffer.py +20 -8
- langchain/memory/token_buffer.py +2 -0
- 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 +14 -7
- langchain/output_parsers/datetime.py +32 -31
- langchain/output_parsers/enum.py +10 -4
- langchain/output_parsers/fix.py +60 -53
- 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 +59 -48
- langchain/output_parsers/prompts.py +1 -2
- langchain/output_parsers/rail_parser.py +1 -1
- langchain/output_parsers/regex.py +9 -8
- langchain/output_parsers/regex_dict.py +7 -10
- langchain/output_parsers/retry.py +99 -80
- langchain/output_parsers/structured.py +21 -6
- langchain/output_parsers/yaml.py +19 -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/pydantic_v1/__init__.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 +5 -3
- 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 +17 -15
- langchain/retrievers/document_compressors/cross_encoder_rerank.py +2 -0
- langchain/retrievers/document_compressors/embeddings_filter.py +24 -17
- langchain/retrievers/document_compressors/flashrank_rerank.py +1 -1
- langchain/retrievers/document_compressors/listwise_rerank.py +8 -5
- langchain/retrievers/ensemble.py +30 -27
- 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 +35 -27
- langchain/retrievers/multi_vector.py +24 -9
- langchain/retrievers/parent_document_retriever.py +33 -9
- langchain/retrievers/re_phraser.py +6 -5
- langchain/retrievers/self_query/base.py +157 -127
- langchain/retrievers/time_weighted_retriever.py +21 -7
- langchain/retrievers/zilliz.py +1 -1
- langchain/runnables/hub.py +12 -0
- langchain/runnables/openai_functions.py +12 -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 +2 -1
- langchain/smith/evaluation/__init__.py +2 -2
- langchain/smith/evaluation/config.py +9 -23
- langchain/smith/evaluation/name_generation.py +3 -3
- langchain/smith/evaluation/progress.py +22 -4
- langchain/smith/evaluation/runner_utils.py +416 -247
- langchain/smith/evaluation/string_run_evaluator.py +102 -68
- langchain/storage/__init__.py +2 -2
- langchain/storage/_lc_store.py +4 -2
- langchain/storage/encoder_backed.py +7 -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 +3 -2
- 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.4.0.dev0.dist-info}/METADATA +4 -14
- {langchain-0.3.26.dist-info → langchain-0.4.0.dev0.dist-info}/RECORD +590 -591
- {langchain-0.3.26.dist-info → langchain-0.4.0.dev0.dist-info}/WHEEL +1 -1
- langchain/smith/evaluation/utils.py +0 -0
- {langchain-0.3.26.dist-info → langchain-0.4.0.dev0.dist-info}/entry_points.txt +0 -0
- {langchain-0.3.26.dist-info → langchain-0.4.0.dev0.dist-info}/licenses/LICENSE +0 -0
langchain/memory/entity.py
CHANGED
|
@@ -4,13 +4,14 @@ 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
|
|
11
11
|
from langchain_core.messages import BaseMessage, get_buffer_string
|
|
12
12
|
from langchain_core.prompts import BasePromptTemplate
|
|
13
13
|
from pydantic import BaseModel, ConfigDict, Field
|
|
14
|
+
from typing_extensions import override
|
|
14
15
|
|
|
15
16
|
from langchain.chains.llm import LLMChain
|
|
16
17
|
from langchain.memory.chat_memory import BaseChatMemory
|
|
@@ -20,6 +21,9 @@ from langchain.memory.prompt import (
|
|
|
20
21
|
)
|
|
21
22
|
from langchain.memory.utils import get_prompt_input_key
|
|
22
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
import sqlite3
|
|
26
|
+
|
|
23
27
|
logger = logging.getLogger(__name__)
|
|
24
28
|
|
|
25
29
|
|
|
@@ -37,27 +41,22 @@ class BaseEntityStore(BaseModel, ABC):
|
|
|
37
41
|
@abstractmethod
|
|
38
42
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
39
43
|
"""Get entity value from store."""
|
|
40
|
-
pass
|
|
41
44
|
|
|
42
45
|
@abstractmethod
|
|
43
46
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
44
47
|
"""Set entity value in store."""
|
|
45
|
-
pass
|
|
46
48
|
|
|
47
49
|
@abstractmethod
|
|
48
50
|
def delete(self, key: str) -> None:
|
|
49
51
|
"""Delete entity value from store."""
|
|
50
|
-
pass
|
|
51
52
|
|
|
52
53
|
@abstractmethod
|
|
53
54
|
def exists(self, key: str) -> bool:
|
|
54
55
|
"""Check if entity exists in store."""
|
|
55
|
-
pass
|
|
56
56
|
|
|
57
57
|
@abstractmethod
|
|
58
58
|
def clear(self) -> None:
|
|
59
59
|
"""Delete all entities from store."""
|
|
60
|
-
pass
|
|
61
60
|
|
|
62
61
|
|
|
63
62
|
@deprecated(
|
|
@@ -73,18 +72,23 @@ class InMemoryEntityStore(BaseEntityStore):
|
|
|
73
72
|
|
|
74
73
|
store: dict[str, Optional[str]] = {}
|
|
75
74
|
|
|
75
|
+
@override
|
|
76
76
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
77
77
|
return self.store.get(key, default)
|
|
78
78
|
|
|
79
|
+
@override
|
|
79
80
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
80
81
|
self.store[key] = value
|
|
81
82
|
|
|
83
|
+
@override
|
|
82
84
|
def delete(self, key: str) -> None:
|
|
83
85
|
del self.store[key]
|
|
84
86
|
|
|
87
|
+
@override
|
|
85
88
|
def exists(self, key: str) -> bool:
|
|
86
89
|
return key in self.store
|
|
87
90
|
|
|
91
|
+
@override
|
|
88
92
|
def clear(self) -> None:
|
|
89
93
|
return self.store.clear()
|
|
90
94
|
|
|
@@ -115,20 +119,33 @@ class UpstashRedisEntityStore(BaseEntityStore):
|
|
|
115
119
|
*args: Any,
|
|
116
120
|
**kwargs: Any,
|
|
117
121
|
):
|
|
122
|
+
"""Initializes the RedisEntityStore.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
session_id: Unique identifier for the session.
|
|
126
|
+
url: URL of the Redis server.
|
|
127
|
+
token: Authentication token for the Redis server.
|
|
128
|
+
key_prefix: Prefix for keys in the Redis store.
|
|
129
|
+
ttl: Time-to-live for keys in seconds (default 1 day).
|
|
130
|
+
recall_ttl: Time-to-live extension for keys when recalled (default 3 days).
|
|
131
|
+
"""
|
|
118
132
|
try:
|
|
119
133
|
from upstash_redis import Redis
|
|
120
|
-
except ImportError:
|
|
121
|
-
|
|
134
|
+
except ImportError as e:
|
|
135
|
+
msg = (
|
|
122
136
|
"Could not import upstash_redis python package. "
|
|
123
137
|
"Please install it with `pip install upstash_redis`."
|
|
124
138
|
)
|
|
139
|
+
raise ImportError(msg) from e
|
|
125
140
|
|
|
126
141
|
super().__init__(*args, **kwargs)
|
|
127
142
|
|
|
128
143
|
try:
|
|
129
144
|
self.redis_client = Redis(url=url, token=token)
|
|
130
|
-
except Exception:
|
|
131
|
-
|
|
145
|
+
except Exception as exc:
|
|
146
|
+
error_msg = "Upstash Redis instance could not be initiated"
|
|
147
|
+
logger.exception(error_msg)
|
|
148
|
+
raise RuntimeError(error_msg) from exc
|
|
132
149
|
|
|
133
150
|
self.session_id = session_id
|
|
134
151
|
self.key_prefix = key_prefix
|
|
@@ -137,35 +154,49 @@ class UpstashRedisEntityStore(BaseEntityStore):
|
|
|
137
154
|
|
|
138
155
|
@property
|
|
139
156
|
def full_key_prefix(self) -> str:
|
|
157
|
+
"""Returns the full key prefix with session ID."""
|
|
140
158
|
return f"{self.key_prefix}:{self.session_id}"
|
|
141
159
|
|
|
160
|
+
@override
|
|
142
161
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
143
162
|
res = (
|
|
144
163
|
self.redis_client.getex(f"{self.full_key_prefix}:{key}", ex=self.recall_ttl)
|
|
145
164
|
or default
|
|
146
165
|
or ""
|
|
147
166
|
)
|
|
148
|
-
logger.debug(
|
|
167
|
+
logger.debug(
|
|
168
|
+
"Upstash Redis MEM get '%s:%s': '%s'", self.full_key_prefix, key, res
|
|
169
|
+
)
|
|
149
170
|
return res
|
|
150
171
|
|
|
172
|
+
@override
|
|
151
173
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
152
174
|
if not value:
|
|
153
175
|
return self.delete(key)
|
|
154
176
|
self.redis_client.set(f"{self.full_key_prefix}:{key}", value, ex=self.ttl)
|
|
155
177
|
logger.debug(
|
|
156
|
-
|
|
178
|
+
"Redis MEM set '%s:%s': '%s' EX %s",
|
|
179
|
+
self.full_key_prefix,
|
|
180
|
+
key,
|
|
181
|
+
value,
|
|
182
|
+
self.ttl,
|
|
157
183
|
)
|
|
184
|
+
return None
|
|
158
185
|
|
|
186
|
+
@override
|
|
159
187
|
def delete(self, key: str) -> None:
|
|
160
188
|
self.redis_client.delete(f"{self.full_key_prefix}:{key}")
|
|
161
189
|
|
|
190
|
+
@override
|
|
162
191
|
def exists(self, key: str) -> bool:
|
|
163
192
|
return self.redis_client.exists(f"{self.full_key_prefix}:{key}") == 1
|
|
164
193
|
|
|
194
|
+
@override
|
|
165
195
|
def clear(self) -> None:
|
|
166
196
|
def scan_and_delete(cursor: int) -> int:
|
|
167
197
|
cursor, keys_to_delete = self.redis_client.scan(
|
|
168
|
-
cursor,
|
|
198
|
+
cursor,
|
|
199
|
+
f"{self.full_key_prefix}:*",
|
|
169
200
|
)
|
|
170
201
|
self.redis_client.delete(*keys_to_delete)
|
|
171
202
|
return cursor
|
|
@@ -206,28 +237,40 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
206
237
|
*args: Any,
|
|
207
238
|
**kwargs: Any,
|
|
208
239
|
):
|
|
240
|
+
"""Initializes the RedisEntityStore.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
session_id: Unique identifier for the session.
|
|
244
|
+
url: URL of the Redis server.
|
|
245
|
+
key_prefix: Prefix for keys in the Redis store.
|
|
246
|
+
ttl: Time-to-live for keys in seconds (default 1 day).
|
|
247
|
+
recall_ttl: Time-to-live extension for keys when recalled (default 3 days).
|
|
248
|
+
"""
|
|
249
|
+
|
|
209
250
|
try:
|
|
210
251
|
import redis
|
|
211
|
-
except ImportError:
|
|
212
|
-
|
|
252
|
+
except ImportError as e:
|
|
253
|
+
msg = (
|
|
213
254
|
"Could not import redis python package. "
|
|
214
255
|
"Please install it with `pip install redis`."
|
|
215
256
|
)
|
|
257
|
+
raise ImportError(msg) from e
|
|
216
258
|
|
|
217
259
|
super().__init__(*args, **kwargs)
|
|
218
260
|
|
|
219
261
|
try:
|
|
220
262
|
from langchain_community.utilities.redis import get_client
|
|
221
|
-
except ImportError:
|
|
222
|
-
|
|
263
|
+
except ImportError as e:
|
|
264
|
+
msg = (
|
|
223
265
|
"Could not import langchain_community.utilities.redis.get_client. "
|
|
224
266
|
"Please install it with `pip install langchain-community`."
|
|
225
267
|
)
|
|
268
|
+
raise ImportError(msg) from e
|
|
226
269
|
|
|
227
270
|
try:
|
|
228
271
|
self.redis_client = get_client(redis_url=url, decode_responses=True)
|
|
229
|
-
except redis.exceptions.ConnectionError
|
|
230
|
-
logger.
|
|
272
|
+
except redis.exceptions.ConnectionError:
|
|
273
|
+
logger.exception("Redis client could not connect")
|
|
231
274
|
|
|
232
275
|
self.session_id = session_id
|
|
233
276
|
self.key_prefix = key_prefix
|
|
@@ -236,31 +279,42 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
236
279
|
|
|
237
280
|
@property
|
|
238
281
|
def full_key_prefix(self) -> str:
|
|
282
|
+
"""Returns the full key prefix with session ID."""
|
|
239
283
|
return f"{self.key_prefix}:{self.session_id}"
|
|
240
284
|
|
|
285
|
+
@override
|
|
241
286
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
242
287
|
res = (
|
|
243
288
|
self.redis_client.getex(f"{self.full_key_prefix}:{key}", ex=self.recall_ttl)
|
|
244
289
|
or default
|
|
245
290
|
or ""
|
|
246
291
|
)
|
|
247
|
-
logger.debug(
|
|
292
|
+
logger.debug("REDIS MEM get '%s:%s': '%s'", self.full_key_prefix, key, res)
|
|
248
293
|
return res
|
|
249
294
|
|
|
295
|
+
@override
|
|
250
296
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
251
297
|
if not value:
|
|
252
298
|
return self.delete(key)
|
|
253
299
|
self.redis_client.set(f"{self.full_key_prefix}:{key}", value, ex=self.ttl)
|
|
254
300
|
logger.debug(
|
|
255
|
-
|
|
301
|
+
"REDIS MEM set '%s:%s': '%s' EX %s",
|
|
302
|
+
self.full_key_prefix,
|
|
303
|
+
key,
|
|
304
|
+
value,
|
|
305
|
+
self.ttl,
|
|
256
306
|
)
|
|
307
|
+
return None
|
|
257
308
|
|
|
309
|
+
@override
|
|
258
310
|
def delete(self, key: str) -> None:
|
|
259
311
|
self.redis_client.delete(f"{self.full_key_prefix}:{key}")
|
|
260
312
|
|
|
313
|
+
@override
|
|
261
314
|
def exists(self, key: str) -> bool:
|
|
262
315
|
return self.redis_client.exists(f"{self.full_key_prefix}:{key}") == 1
|
|
263
316
|
|
|
317
|
+
@override
|
|
264
318
|
def clear(self) -> None:
|
|
265
319
|
# iterate a list in batches of size batch_size
|
|
266
320
|
def batched(iterable: Iterable[Any], batch_size: int) -> Iterable[Any]:
|
|
@@ -269,7 +323,8 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
269
323
|
yield batch
|
|
270
324
|
|
|
271
325
|
for keybatch in batched(
|
|
272
|
-
self.redis_client.scan_iter(f"{self.full_key_prefix}:*"),
|
|
326
|
+
self.redis_client.scan_iter(f"{self.full_key_prefix}:*"),
|
|
327
|
+
500,
|
|
273
328
|
):
|
|
274
329
|
self.redis_client.delete(*keybatch)
|
|
275
330
|
|
|
@@ -283,7 +338,7 @@ class RedisEntityStore(BaseEntityStore):
|
|
|
283
338
|
),
|
|
284
339
|
)
|
|
285
340
|
class SQLiteEntityStore(BaseEntityStore):
|
|
286
|
-
"""SQLite-backed Entity store"""
|
|
341
|
+
"""SQLite-backed Entity store with safe query construction."""
|
|
287
342
|
|
|
288
343
|
session_id: str = "default"
|
|
289
344
|
table_name: str = "memory_store"
|
|
@@ -301,14 +356,28 @@ class SQLiteEntityStore(BaseEntityStore):
|
|
|
301
356
|
*args: Any,
|
|
302
357
|
**kwargs: Any,
|
|
303
358
|
):
|
|
359
|
+
"""Initializes the SQLiteEntityStore.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
session_id: Unique identifier for the session.
|
|
363
|
+
db_file: Path to the SQLite database file.
|
|
364
|
+
table_name: Name of the table to store entities.
|
|
365
|
+
"""
|
|
366
|
+
super().__init__(*args, **kwargs)
|
|
304
367
|
try:
|
|
305
368
|
import sqlite3
|
|
306
|
-
except ImportError:
|
|
307
|
-
|
|
369
|
+
except ImportError as e:
|
|
370
|
+
msg = (
|
|
308
371
|
"Could not import sqlite3 python package. "
|
|
309
372
|
"Please install it with `pip install sqlite3`."
|
|
310
373
|
)
|
|
311
|
-
|
|
374
|
+
raise ImportError(msg) from e
|
|
375
|
+
|
|
376
|
+
# Basic validation to prevent obviously malicious table/session names
|
|
377
|
+
if not table_name.isidentifier() or not session_id.isidentifier():
|
|
378
|
+
# Since we validate here, we can safely suppress the S608 bandit warning
|
|
379
|
+
msg = "Table name and session ID must be valid Python identifiers."
|
|
380
|
+
raise ValueError(msg)
|
|
312
381
|
|
|
313
382
|
self.conn = sqlite3.connect(db_file)
|
|
314
383
|
self.session_id = session_id
|
|
@@ -317,64 +386,65 @@ class SQLiteEntityStore(BaseEntityStore):
|
|
|
317
386
|
|
|
318
387
|
@property
|
|
319
388
|
def full_table_name(self) -> str:
|
|
389
|
+
"""Returns the full table name with session ID."""
|
|
320
390
|
return f"{self.table_name}_{self.session_id}"
|
|
321
391
|
|
|
392
|
+
def _execute_query(self, query: str, params: tuple = ()) -> "sqlite3.Cursor":
|
|
393
|
+
"""Executes a query with proper connection handling."""
|
|
394
|
+
with self.conn:
|
|
395
|
+
return self.conn.execute(query, params)
|
|
396
|
+
|
|
322
397
|
def _create_table_if_not_exists(self) -> None:
|
|
398
|
+
"""Creates the entity table if it doesn't exist, using safe quoting."""
|
|
399
|
+
# Use standard SQL double quotes for the table name identifier
|
|
323
400
|
create_table_query = f"""
|
|
324
|
-
CREATE TABLE IF NOT EXISTS {self.full_table_name} (
|
|
401
|
+
CREATE TABLE IF NOT EXISTS "{self.full_table_name}" (
|
|
325
402
|
key TEXT PRIMARY KEY,
|
|
326
403
|
value TEXT
|
|
327
404
|
)
|
|
328
405
|
"""
|
|
329
|
-
|
|
330
|
-
self.conn.execute(create_table_query)
|
|
406
|
+
self._execute_query(create_table_query)
|
|
331
407
|
|
|
332
408
|
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
cursor = self.conn.execute(query, (key,))
|
|
409
|
+
"""Retrieves a value, safely quoting the table name."""
|
|
410
|
+
# `?` placeholder is used for the value to prevent SQL injection
|
|
411
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
412
|
+
query = f'SELECT value FROM "{self.full_table_name}" WHERE key = ?' # noqa: S608
|
|
413
|
+
cursor = self._execute_query(query, (key,))
|
|
339
414
|
result = cursor.fetchone()
|
|
340
|
-
if result is not None
|
|
341
|
-
value = result[0]
|
|
342
|
-
return value
|
|
343
|
-
return default
|
|
415
|
+
return result[0] if result is not None else default
|
|
344
416
|
|
|
345
417
|
def set(self, key: str, value: Optional[str]) -> None:
|
|
418
|
+
"""Inserts or replaces a value, safely quoting the table name."""
|
|
346
419
|
if not value:
|
|
347
420
|
return self.delete(key)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
421
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
422
|
+
query = (
|
|
423
|
+
"INSERT OR REPLACE INTO " # noqa: S608
|
|
424
|
+
f'"{self.full_table_name}" (key, value) VALUES (?, ?)'
|
|
425
|
+
)
|
|
426
|
+
self._execute_query(query, (key, value))
|
|
427
|
+
return None
|
|
354
428
|
|
|
355
429
|
def delete(self, key: str) -> None:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
with self.conn:
|
|
361
|
-
self.conn.execute(query, (key,))
|
|
430
|
+
"""Deletes a key-value pair, safely quoting the table name."""
|
|
431
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
432
|
+
query = f'DELETE FROM "{self.full_table_name}" WHERE key = ?' # noqa: S608
|
|
433
|
+
self._execute_query(query, (key,))
|
|
362
434
|
|
|
363
435
|
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
|
|
436
|
+
"""Checks for the existence of a key, safely quoting the table name."""
|
|
437
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
438
|
+
query = f'SELECT 1 FROM "{self.full_table_name}" WHERE key = ? LIMIT 1' # noqa: S608
|
|
439
|
+
cursor = self._execute_query(query, (key,))
|
|
440
|
+
return cursor.fetchone() is not None
|
|
373
441
|
|
|
442
|
+
@override
|
|
374
443
|
def clear(self) -> None:
|
|
444
|
+
# Ignore S608 since we validate for malicious table/session names in `__init__`
|
|
375
445
|
query = f"""
|
|
376
446
|
DELETE FROM {self.full_table_name}
|
|
377
|
-
"""
|
|
447
|
+
""" # noqa: S608
|
|
378
448
|
with self.conn:
|
|
379
449
|
self.conn.execute(query)
|
|
380
450
|
|
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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
3
|
from langchain_core.memory import BaseMemory
|
|
4
|
+
from typing_extensions import override
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class SimpleMemory(BaseMemory):
|
|
@@ -8,19 +9,19 @@ class SimpleMemory(BaseMemory):
|
|
|
8
9
|
ever change between prompts.
|
|
9
10
|
"""
|
|
10
11
|
|
|
11
|
-
memories: dict[str, Any] =
|
|
12
|
+
memories: dict[str, Any] = {}
|
|
12
13
|
|
|
13
14
|
@property
|
|
15
|
+
@override
|
|
14
16
|
def memory_variables(self) -> list[str]:
|
|
15
17
|
return list(self.memories.keys())
|
|
16
18
|
|
|
19
|
+
@override
|
|
17
20
|
def load_memory_variables(self, inputs: dict[str, Any]) -> dict[str, str]:
|
|
18
21
|
return self.memories
|
|
19
22
|
|
|
20
23
|
def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
|
|
21
24
|
"""Nothing should be saved or changed, my memory is set in stone."""
|
|
22
|
-
pass
|
|
23
25
|
|
|
24
26
|
def clear(self) -> None:
|
|
25
27
|
"""Nothing to clear, got a memory like a vault."""
|
|
26
|
-
pass
|
langchain/memory/summary.py
CHANGED
|
@@ -3,14 +3,13 @@ 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
|
|
11
9
|
from langchain_core.prompts import BasePromptTemplate
|
|
12
10
|
from langchain_core.utils import pre_init
|
|
13
11
|
from pydantic import BaseModel
|
|
12
|
+
from typing_extensions import override
|
|
14
13
|
|
|
15
14
|
from langchain.chains.llm import LLMChain
|
|
16
15
|
from langchain.memory.chat_memory import BaseChatMemory
|
|
@@ -22,7 +21,7 @@ from langchain.memory.prompt import SUMMARY_PROMPT
|
|
|
22
21
|
removal="1.0",
|
|
23
22
|
message=(
|
|
24
23
|
"Refer here for how to incorporate summaries of conversation history: "
|
|
25
|
-
"https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/"
|
|
24
|
+
"https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/"
|
|
26
25
|
),
|
|
27
26
|
)
|
|
28
27
|
class SummarizerMixin(BaseModel):
|
|
@@ -35,8 +34,19 @@ class SummarizerMixin(BaseModel):
|
|
|
35
34
|
summary_message_cls: type[BaseMessage] = SystemMessage
|
|
36
35
|
|
|
37
36
|
def predict_new_summary(
|
|
38
|
-
self,
|
|
37
|
+
self,
|
|
38
|
+
messages: list[BaseMessage],
|
|
39
|
+
existing_summary: str,
|
|
39
40
|
) -> str:
|
|
41
|
+
"""Predict a new summary based on the messages and existing summary.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
messages: List of messages to summarize.
|
|
45
|
+
existing_summary: Existing summary to build upon.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
A new summary string.
|
|
49
|
+
"""
|
|
40
50
|
new_lines = get_buffer_string(
|
|
41
51
|
messages,
|
|
42
52
|
human_prefix=self.human_prefix,
|
|
@@ -47,8 +57,19 @@ class SummarizerMixin(BaseModel):
|
|
|
47
57
|
return chain.predict(summary=existing_summary, new_lines=new_lines)
|
|
48
58
|
|
|
49
59
|
async def apredict_new_summary(
|
|
50
|
-
self,
|
|
60
|
+
self,
|
|
61
|
+
messages: list[BaseMessage],
|
|
62
|
+
existing_summary: str,
|
|
51
63
|
) -> str:
|
|
64
|
+
"""Predict a new summary based on the messages and existing summary.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
messages: List of messages to summarize.
|
|
68
|
+
existing_summary: Existing summary to build upon.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
A new summary string.
|
|
72
|
+
"""
|
|
52
73
|
new_lines = get_buffer_string(
|
|
53
74
|
messages,
|
|
54
75
|
human_prefix=self.human_prefix,
|
|
@@ -87,10 +108,21 @@ class ConversationSummaryMemory(BaseChatMemory, SummarizerMixin):
|
|
|
87
108
|
summarize_step: int = 2,
|
|
88
109
|
**kwargs: Any,
|
|
89
110
|
) -> ConversationSummaryMemory:
|
|
111
|
+
"""Create a ConversationSummaryMemory from a list of messages.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
llm: The language model to use for summarization.
|
|
115
|
+
chat_memory: The chat history to summarize.
|
|
116
|
+
summarize_step: Number of messages to summarize at a time.
|
|
117
|
+
**kwargs: Additional keyword arguments to pass to the class.
|
|
118
|
+
Returns:
|
|
119
|
+
An instance of ConversationSummaryMemory with the summarized history.
|
|
120
|
+
"""
|
|
90
121
|
obj = cls(llm=llm, chat_memory=chat_memory, **kwargs)
|
|
91
122
|
for i in range(0, len(obj.chat_memory.messages), summarize_step):
|
|
92
123
|
obj.buffer = obj.predict_new_summary(
|
|
93
|
-
obj.chat_memory.messages[i : i + summarize_step],
|
|
124
|
+
obj.chat_memory.messages[i : i + summarize_step],
|
|
125
|
+
obj.buffer,
|
|
94
126
|
)
|
|
95
127
|
return obj
|
|
96
128
|
|
|
@@ -102,6 +134,7 @@ class ConversationSummaryMemory(BaseChatMemory, SummarizerMixin):
|
|
|
102
134
|
"""
|
|
103
135
|
return [self.memory_key]
|
|
104
136
|
|
|
137
|
+
@override
|
|
105
138
|
def load_memory_variables(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
|
106
139
|
"""Return history buffer."""
|
|
107
140
|
if self.return_messages:
|
|
@@ -116,23 +149,22 @@ class ConversationSummaryMemory(BaseChatMemory, SummarizerMixin):
|
|
|
116
149
|
prompt_variables = values["prompt"].input_variables
|
|
117
150
|
expected_keys = {"summary", "new_lines"}
|
|
118
151
|
if expected_keys != set(prompt_variables):
|
|
119
|
-
|
|
152
|
+
msg = (
|
|
120
153
|
"Got unexpected prompt input variables. The prompt expects "
|
|
121
154
|
f"{prompt_variables}, but it should have {expected_keys}."
|
|
122
155
|
)
|
|
156
|
+
raise ValueError(msg)
|
|
123
157
|
return values
|
|
124
158
|
|
|
125
159
|
def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
|
|
126
160
|
"""Save context from this conversation to buffer."""
|
|
127
161
|
super().save_context(inputs, outputs)
|
|
128
162
|
self.buffer = self.predict_new_summary(
|
|
129
|
-
self.chat_memory.messages[-2:],
|
|
163
|
+
self.chat_memory.messages[-2:],
|
|
164
|
+
self.buffer,
|
|
130
165
|
)
|
|
131
166
|
|
|
132
167
|
def clear(self) -> None:
|
|
133
168
|
"""Clear memory contents."""
|
|
134
169
|
super().clear()
|
|
135
170
|
self.buffer = ""
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
ConversationSummaryMemory.model_rebuild()
|