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.

Files changed (580) hide show
  1. langchain/__init__.py +110 -96
  2. langchain/_api/__init__.py +2 -2
  3. langchain/_api/deprecation.py +3 -3
  4. langchain/_api/module_import.py +51 -46
  5. langchain/_api/path.py +1 -1
  6. langchain/adapters/openai.py +8 -8
  7. langchain/agents/__init__.py +15 -12
  8. langchain/agents/agent.py +160 -133
  9. langchain/agents/agent_iterator.py +31 -14
  10. langchain/agents/agent_toolkits/__init__.py +7 -6
  11. langchain/agents/agent_toolkits/ainetwork/toolkit.py +1 -1
  12. langchain/agents/agent_toolkits/amadeus/toolkit.py +1 -1
  13. langchain/agents/agent_toolkits/azure_cognitive_services.py +1 -1
  14. langchain/agents/agent_toolkits/clickup/toolkit.py +1 -1
  15. langchain/agents/agent_toolkits/conversational_retrieval/openai_functions.py +6 -4
  16. langchain/agents/agent_toolkits/csv/__init__.py +4 -2
  17. langchain/agents/agent_toolkits/file_management/__init__.py +1 -1
  18. langchain/agents/agent_toolkits/file_management/toolkit.py +1 -1
  19. langchain/agents/agent_toolkits/github/toolkit.py +9 -9
  20. langchain/agents/agent_toolkits/gitlab/toolkit.py +1 -1
  21. langchain/agents/agent_toolkits/json/base.py +1 -1
  22. langchain/agents/agent_toolkits/multion/toolkit.py +1 -1
  23. langchain/agents/agent_toolkits/office365/toolkit.py +1 -1
  24. langchain/agents/agent_toolkits/openapi/base.py +1 -1
  25. langchain/agents/agent_toolkits/openapi/planner.py +2 -2
  26. langchain/agents/agent_toolkits/openapi/planner_prompt.py +10 -10
  27. langchain/agents/agent_toolkits/openapi/prompt.py +1 -1
  28. langchain/agents/agent_toolkits/openapi/toolkit.py +1 -1
  29. langchain/agents/agent_toolkits/pandas/__init__.py +4 -2
  30. langchain/agents/agent_toolkits/playwright/__init__.py +1 -1
  31. langchain/agents/agent_toolkits/playwright/toolkit.py +1 -1
  32. langchain/agents/agent_toolkits/powerbi/base.py +1 -1
  33. langchain/agents/agent_toolkits/powerbi/chat_base.py +1 -1
  34. langchain/agents/agent_toolkits/powerbi/prompt.py +2 -2
  35. langchain/agents/agent_toolkits/powerbi/toolkit.py +1 -1
  36. langchain/agents/agent_toolkits/python/__init__.py +4 -2
  37. langchain/agents/agent_toolkits/spark/__init__.py +4 -2
  38. langchain/agents/agent_toolkits/spark_sql/base.py +1 -1
  39. langchain/agents/agent_toolkits/spark_sql/toolkit.py +1 -1
  40. langchain/agents/agent_toolkits/sql/prompt.py +1 -1
  41. langchain/agents/agent_toolkits/sql/toolkit.py +1 -1
  42. langchain/agents/agent_toolkits/vectorstore/base.py +2 -2
  43. langchain/agents/agent_toolkits/vectorstore/prompt.py +2 -4
  44. langchain/agents/agent_toolkits/vectorstore/toolkit.py +12 -11
  45. langchain/agents/agent_toolkits/xorbits/__init__.py +4 -2
  46. langchain/agents/agent_toolkits/zapier/toolkit.py +1 -1
  47. langchain/agents/agent_types.py +6 -6
  48. langchain/agents/chat/base.py +6 -12
  49. langchain/agents/chat/output_parser.py +9 -6
  50. langchain/agents/chat/prompt.py +3 -4
  51. langchain/agents/conversational/base.py +9 -5
  52. langchain/agents/conversational/output_parser.py +4 -2
  53. langchain/agents/conversational/prompt.py +2 -3
  54. langchain/agents/conversational_chat/base.py +7 -5
  55. langchain/agents/conversational_chat/output_parser.py +9 -11
  56. langchain/agents/conversational_chat/prompt.py +5 -6
  57. langchain/agents/format_scratchpad/__init__.py +3 -3
  58. langchain/agents/format_scratchpad/log_to_messages.py +1 -1
  59. langchain/agents/format_scratchpad/openai_functions.py +8 -6
  60. langchain/agents/format_scratchpad/tools.py +5 -3
  61. langchain/agents/format_scratchpad/xml.py +33 -2
  62. langchain/agents/initialize.py +16 -8
  63. langchain/agents/json_chat/base.py +18 -18
  64. langchain/agents/json_chat/prompt.py +2 -3
  65. langchain/agents/load_tools.py +2 -1
  66. langchain/agents/loading.py +28 -18
  67. langchain/agents/mrkl/base.py +9 -4
  68. langchain/agents/mrkl/output_parser.py +17 -13
  69. langchain/agents/mrkl/prompt.py +1 -2
  70. langchain/agents/openai_assistant/base.py +80 -70
  71. langchain/agents/openai_functions_agent/base.py +46 -37
  72. langchain/agents/openai_functions_multi_agent/base.py +39 -26
  73. langchain/agents/openai_tools/base.py +8 -8
  74. langchain/agents/output_parsers/__init__.py +3 -3
  75. langchain/agents/output_parsers/json.py +6 -6
  76. langchain/agents/output_parsers/openai_functions.py +15 -7
  77. langchain/agents/output_parsers/openai_tools.py +9 -4
  78. langchain/agents/output_parsers/react_json_single_input.py +10 -5
  79. langchain/agents/output_parsers/react_single_input.py +15 -11
  80. langchain/agents/output_parsers/self_ask.py +3 -2
  81. langchain/agents/output_parsers/tools.py +18 -13
  82. langchain/agents/output_parsers/xml.py +99 -28
  83. langchain/agents/react/agent.py +4 -4
  84. langchain/agents/react/base.py +22 -17
  85. langchain/agents/react/output_parser.py +5 -6
  86. langchain/agents/react/textworld_prompt.py +0 -1
  87. langchain/agents/react/wiki_prompt.py +14 -15
  88. langchain/agents/schema.py +3 -2
  89. langchain/agents/self_ask_with_search/base.py +19 -15
  90. langchain/agents/self_ask_with_search/prompt.py +0 -1
  91. langchain/agents/structured_chat/base.py +14 -11
  92. langchain/agents/structured_chat/output_parser.py +16 -18
  93. langchain/agents/structured_chat/prompt.py +3 -4
  94. langchain/agents/tool_calling_agent/base.py +7 -6
  95. langchain/agents/tools.py +2 -2
  96. langchain/agents/utils.py +2 -3
  97. langchain/agents/xml/base.py +5 -5
  98. langchain/agents/xml/prompt.py +1 -2
  99. langchain/cache.py +12 -12
  100. langchain/callbacks/__init__.py +11 -11
  101. langchain/callbacks/aim_callback.py +2 -2
  102. langchain/callbacks/argilla_callback.py +1 -1
  103. langchain/callbacks/arize_callback.py +1 -1
  104. langchain/callbacks/arthur_callback.py +1 -1
  105. langchain/callbacks/base.py +7 -7
  106. langchain/callbacks/clearml_callback.py +1 -1
  107. langchain/callbacks/comet_ml_callback.py +1 -1
  108. langchain/callbacks/confident_callback.py +1 -1
  109. langchain/callbacks/context_callback.py +1 -1
  110. langchain/callbacks/flyte_callback.py +1 -1
  111. langchain/callbacks/human.py +2 -2
  112. langchain/callbacks/infino_callback.py +1 -1
  113. langchain/callbacks/labelstudio_callback.py +1 -1
  114. langchain/callbacks/llmonitor_callback.py +1 -1
  115. langchain/callbacks/manager.py +5 -5
  116. langchain/callbacks/mlflow_callback.py +2 -2
  117. langchain/callbacks/openai_info.py +1 -1
  118. langchain/callbacks/promptlayer_callback.py +1 -1
  119. langchain/callbacks/sagemaker_callback.py +1 -1
  120. langchain/callbacks/streaming_aiter.py +4 -1
  121. langchain/callbacks/streaming_aiter_final_only.py +5 -3
  122. langchain/callbacks/streaming_stdout_final_only.py +5 -3
  123. langchain/callbacks/streamlit/__init__.py +3 -2
  124. langchain/callbacks/streamlit/mutable_expander.py +1 -1
  125. langchain/callbacks/streamlit/streamlit_callback_handler.py +3 -3
  126. langchain/callbacks/tracers/__init__.py +1 -1
  127. langchain/callbacks/tracers/comet.py +1 -1
  128. langchain/callbacks/tracers/evaluation.py +1 -1
  129. langchain/callbacks/tracers/log_stream.py +1 -1
  130. langchain/callbacks/tracers/logging.py +1 -1
  131. langchain/callbacks/tracers/stdout.py +1 -1
  132. langchain/callbacks/trubrics_callback.py +1 -1
  133. langchain/callbacks/utils.py +4 -4
  134. langchain/callbacks/wandb_callback.py +1 -1
  135. langchain/callbacks/whylabs_callback.py +1 -1
  136. langchain/chains/api/base.py +36 -22
  137. langchain/chains/api/news_docs.py +1 -2
  138. langchain/chains/api/open_meteo_docs.py +1 -2
  139. langchain/chains/api/openapi/requests_chain.py +1 -1
  140. langchain/chains/api/openapi/response_chain.py +1 -1
  141. langchain/chains/api/podcast_docs.py +1 -2
  142. langchain/chains/api/prompt.py +1 -2
  143. langchain/chains/api/tmdb_docs.py +1 -2
  144. langchain/chains/base.py +88 -54
  145. langchain/chains/chat_vector_db/prompts.py +2 -3
  146. langchain/chains/combine_documents/__init__.py +1 -1
  147. langchain/chains/combine_documents/base.py +23 -10
  148. langchain/chains/combine_documents/map_reduce.py +38 -30
  149. langchain/chains/combine_documents/map_rerank.py +33 -20
  150. langchain/chains/combine_documents/reduce.py +47 -26
  151. langchain/chains/combine_documents/refine.py +26 -17
  152. langchain/chains/combine_documents/stuff.py +19 -12
  153. langchain/chains/constitutional_ai/base.py +4 -4
  154. langchain/chains/constitutional_ai/principles.py +22 -25
  155. langchain/chains/constitutional_ai/prompts.py +25 -28
  156. langchain/chains/conversation/base.py +5 -3
  157. langchain/chains/conversation/memory.py +5 -5
  158. langchain/chains/conversation/prompt.py +5 -5
  159. langchain/chains/conversational_retrieval/base.py +41 -20
  160. langchain/chains/conversational_retrieval/prompts.py +2 -3
  161. langchain/chains/elasticsearch_database/base.py +8 -9
  162. langchain/chains/elasticsearch_database/prompts.py +2 -3
  163. langchain/chains/ernie_functions/__init__.py +2 -2
  164. langchain/chains/example_generator.py +3 -1
  165. langchain/chains/flare/base.py +26 -12
  166. langchain/chains/graph_qa/cypher.py +2 -2
  167. langchain/chains/graph_qa/falkordb.py +1 -1
  168. langchain/chains/graph_qa/gremlin.py +1 -1
  169. langchain/chains/graph_qa/neptune_sparql.py +1 -1
  170. langchain/chains/graph_qa/prompts.py +2 -2
  171. langchain/chains/history_aware_retriever.py +2 -1
  172. langchain/chains/hyde/base.py +6 -5
  173. langchain/chains/hyde/prompts.py +5 -6
  174. langchain/chains/llm.py +77 -61
  175. langchain/chains/llm_bash/__init__.py +2 -1
  176. langchain/chains/llm_checker/base.py +7 -5
  177. langchain/chains/llm_checker/prompt.py +3 -4
  178. langchain/chains/llm_math/base.py +16 -9
  179. langchain/chains/llm_math/prompt.py +1 -2
  180. langchain/chains/llm_summarization_checker/base.py +9 -6
  181. langchain/chains/llm_symbolic_math/__init__.py +2 -1
  182. langchain/chains/loading.py +151 -95
  183. langchain/chains/mapreduce.py +4 -3
  184. langchain/chains/moderation.py +8 -9
  185. langchain/chains/natbot/base.py +8 -8
  186. langchain/chains/natbot/crawler.py +73 -76
  187. langchain/chains/natbot/prompt.py +2 -3
  188. langchain/chains/openai_functions/__init__.py +7 -7
  189. langchain/chains/openai_functions/base.py +13 -10
  190. langchain/chains/openai_functions/citation_fuzzy_match.py +12 -11
  191. langchain/chains/openai_functions/extraction.py +19 -19
  192. langchain/chains/openai_functions/openapi.py +35 -35
  193. langchain/chains/openai_functions/qa_with_structure.py +19 -12
  194. langchain/chains/openai_functions/tagging.py +2 -4
  195. langchain/chains/openai_tools/extraction.py +7 -8
  196. langchain/chains/qa_generation/base.py +4 -3
  197. langchain/chains/qa_generation/prompt.py +5 -5
  198. langchain/chains/qa_with_sources/base.py +14 -6
  199. langchain/chains/qa_with_sources/loading.py +16 -8
  200. langchain/chains/qa_with_sources/map_reduce_prompt.py +8 -9
  201. langchain/chains/qa_with_sources/refine_prompts.py +0 -1
  202. langchain/chains/qa_with_sources/retrieval.py +14 -5
  203. langchain/chains/qa_with_sources/stuff_prompt.py +6 -7
  204. langchain/chains/qa_with_sources/vector_db.py +17 -6
  205. langchain/chains/query_constructor/base.py +34 -33
  206. langchain/chains/query_constructor/ir.py +4 -4
  207. langchain/chains/query_constructor/parser.py +37 -32
  208. langchain/chains/query_constructor/prompt.py +5 -6
  209. langchain/chains/question_answering/chain.py +21 -10
  210. langchain/chains/question_answering/map_reduce_prompt.py +14 -14
  211. langchain/chains/question_answering/map_rerank_prompt.py +3 -3
  212. langchain/chains/question_answering/refine_prompts.py +2 -5
  213. langchain/chains/question_answering/stuff_prompt.py +5 -5
  214. langchain/chains/retrieval.py +1 -3
  215. langchain/chains/retrieval_qa/base.py +34 -27
  216. langchain/chains/retrieval_qa/prompt.py +1 -2
  217. langchain/chains/router/__init__.py +3 -3
  218. langchain/chains/router/base.py +24 -20
  219. langchain/chains/router/embedding_router.py +12 -8
  220. langchain/chains/router/llm_router.py +17 -16
  221. langchain/chains/router/multi_prompt.py +2 -2
  222. langchain/chains/router/multi_retrieval_qa.py +10 -5
  223. langchain/chains/sequential.py +30 -18
  224. langchain/chains/sql_database/prompt.py +14 -16
  225. langchain/chains/sql_database/query.py +6 -5
  226. langchain/chains/structured_output/__init__.py +1 -1
  227. langchain/chains/structured_output/base.py +75 -67
  228. langchain/chains/summarize/chain.py +11 -5
  229. langchain/chains/summarize/map_reduce_prompt.py +0 -1
  230. langchain/chains/summarize/stuff_prompt.py +0 -1
  231. langchain/chains/transform.py +5 -6
  232. langchain/chat_loaders/facebook_messenger.py +1 -1
  233. langchain/chat_loaders/langsmith.py +1 -1
  234. langchain/chat_loaders/utils.py +3 -3
  235. langchain/chat_models/__init__.py +20 -19
  236. langchain/chat_models/anthropic.py +1 -1
  237. langchain/chat_models/azureml_endpoint.py +1 -1
  238. langchain/chat_models/baidu_qianfan_endpoint.py +1 -1
  239. langchain/chat_models/base.py +160 -123
  240. langchain/chat_models/bedrock.py +1 -1
  241. langchain/chat_models/fake.py +1 -1
  242. langchain/chat_models/meta.py +1 -1
  243. langchain/chat_models/pai_eas_endpoint.py +1 -1
  244. langchain/chat_models/promptlayer_openai.py +1 -1
  245. langchain/chat_models/volcengine_maas.py +1 -1
  246. langchain/docstore/base.py +1 -1
  247. langchain/document_loaders/__init__.py +9 -9
  248. langchain/document_loaders/airbyte.py +3 -3
  249. langchain/document_loaders/assemblyai.py +1 -1
  250. langchain/document_loaders/azure_blob_storage_container.py +1 -1
  251. langchain/document_loaders/azure_blob_storage_file.py +1 -1
  252. langchain/document_loaders/baiducloud_bos_file.py +1 -1
  253. langchain/document_loaders/base.py +1 -1
  254. langchain/document_loaders/blob_loaders/__init__.py +1 -1
  255. langchain/document_loaders/blockchain.py +1 -1
  256. langchain/document_loaders/chatgpt.py +1 -1
  257. langchain/document_loaders/college_confidential.py +1 -1
  258. langchain/document_loaders/confluence.py +1 -1
  259. langchain/document_loaders/email.py +1 -1
  260. langchain/document_loaders/facebook_chat.py +1 -1
  261. langchain/document_loaders/markdown.py +1 -1
  262. langchain/document_loaders/notebook.py +1 -1
  263. langchain/document_loaders/org_mode.py +1 -1
  264. langchain/document_loaders/parsers/__init__.py +1 -1
  265. langchain/document_loaders/parsers/docai.py +1 -1
  266. langchain/document_loaders/parsers/generic.py +1 -1
  267. langchain/document_loaders/parsers/html/__init__.py +1 -1
  268. langchain/document_loaders/parsers/html/bs4.py +1 -1
  269. langchain/document_loaders/parsers/language/cobol.py +1 -1
  270. langchain/document_loaders/parsers/language/python.py +1 -1
  271. langchain/document_loaders/parsers/msword.py +1 -1
  272. langchain/document_loaders/parsers/pdf.py +5 -5
  273. langchain/document_loaders/parsers/registry.py +1 -1
  274. langchain/document_loaders/pdf.py +8 -8
  275. langchain/document_loaders/powerpoint.py +1 -1
  276. langchain/document_loaders/pyspark_dataframe.py +1 -1
  277. langchain/document_loaders/telegram.py +2 -2
  278. langchain/document_loaders/tencent_cos_directory.py +1 -1
  279. langchain/document_loaders/unstructured.py +5 -5
  280. langchain/document_loaders/url_playwright.py +1 -1
  281. langchain/document_loaders/whatsapp_chat.py +1 -1
  282. langchain/document_loaders/youtube.py +2 -2
  283. langchain/document_transformers/__init__.py +3 -3
  284. langchain/document_transformers/beautiful_soup_transformer.py +1 -1
  285. langchain/document_transformers/doctran_text_extract.py +1 -1
  286. langchain/document_transformers/doctran_text_qa.py +1 -1
  287. langchain/document_transformers/doctran_text_translate.py +1 -1
  288. langchain/document_transformers/embeddings_redundant_filter.py +3 -3
  289. langchain/document_transformers/google_translate.py +1 -1
  290. langchain/document_transformers/html2text.py +1 -1
  291. langchain/document_transformers/nuclia_text_transform.py +1 -1
  292. langchain/embeddings/__init__.py +5 -5
  293. langchain/embeddings/base.py +33 -24
  294. langchain/embeddings/cache.py +36 -31
  295. langchain/embeddings/fake.py +1 -1
  296. langchain/embeddings/huggingface.py +2 -2
  297. langchain/evaluation/__init__.py +22 -22
  298. langchain/evaluation/agents/trajectory_eval_chain.py +23 -23
  299. langchain/evaluation/agents/trajectory_eval_prompt.py +6 -9
  300. langchain/evaluation/comparison/__init__.py +1 -1
  301. langchain/evaluation/comparison/eval_chain.py +20 -13
  302. langchain/evaluation/comparison/prompt.py +1 -2
  303. langchain/evaluation/criteria/__init__.py +1 -1
  304. langchain/evaluation/criteria/eval_chain.py +20 -11
  305. langchain/evaluation/criteria/prompt.py +2 -3
  306. langchain/evaluation/embedding_distance/base.py +23 -20
  307. langchain/evaluation/loading.py +15 -11
  308. langchain/evaluation/parsing/base.py +4 -1
  309. langchain/evaluation/parsing/json_distance.py +5 -2
  310. langchain/evaluation/parsing/json_schema.py +12 -8
  311. langchain/evaluation/qa/__init__.py +1 -1
  312. langchain/evaluation/qa/eval_chain.py +12 -5
  313. langchain/evaluation/qa/eval_prompt.py +7 -8
  314. langchain/evaluation/qa/generate_chain.py +2 -1
  315. langchain/evaluation/qa/generate_prompt.py +2 -4
  316. langchain/evaluation/schema.py +38 -30
  317. langchain/evaluation/scoring/__init__.py +1 -1
  318. langchain/evaluation/scoring/eval_chain.py +22 -15
  319. langchain/evaluation/scoring/prompt.py +0 -1
  320. langchain/evaluation/string_distance/base.py +14 -9
  321. langchain/globals.py +12 -11
  322. langchain/graphs/__init__.py +6 -6
  323. langchain/graphs/graph_document.py +1 -1
  324. langchain/graphs/networkx_graph.py +2 -2
  325. langchain/hub.py +9 -11
  326. langchain/indexes/__init__.py +3 -3
  327. langchain/indexes/_sql_record_manager.py +63 -46
  328. langchain/indexes/prompts/entity_extraction.py +1 -2
  329. langchain/indexes/prompts/entity_summarization.py +1 -2
  330. langchain/indexes/prompts/knowledge_triplet_extraction.py +1 -3
  331. langchain/indexes/vectorstore.py +35 -19
  332. langchain/llms/__init__.py +13 -13
  333. langchain/llms/ai21.py +1 -1
  334. langchain/llms/azureml_endpoint.py +4 -4
  335. langchain/llms/base.py +15 -7
  336. langchain/llms/bedrock.py +1 -1
  337. langchain/llms/cloudflare_workersai.py +1 -1
  338. langchain/llms/gradient_ai.py +1 -1
  339. langchain/llms/loading.py +1 -1
  340. langchain/llms/openai.py +1 -1
  341. langchain/llms/sagemaker_endpoint.py +1 -1
  342. langchain/load/dump.py +1 -1
  343. langchain/load/load.py +1 -1
  344. langchain/load/serializable.py +3 -3
  345. langchain/memory/__init__.py +3 -3
  346. langchain/memory/buffer.py +9 -7
  347. langchain/memory/chat_memory.py +14 -8
  348. langchain/memory/chat_message_histories/__init__.py +1 -1
  349. langchain/memory/chat_message_histories/astradb.py +1 -1
  350. langchain/memory/chat_message_histories/cassandra.py +1 -1
  351. langchain/memory/chat_message_histories/cosmos_db.py +1 -1
  352. langchain/memory/chat_message_histories/dynamodb.py +1 -1
  353. langchain/memory/chat_message_histories/elasticsearch.py +1 -1
  354. langchain/memory/chat_message_histories/file.py +1 -1
  355. langchain/memory/chat_message_histories/firestore.py +1 -1
  356. langchain/memory/chat_message_histories/momento.py +1 -1
  357. langchain/memory/chat_message_histories/mongodb.py +1 -1
  358. langchain/memory/chat_message_histories/neo4j.py +1 -1
  359. langchain/memory/chat_message_histories/postgres.py +1 -1
  360. langchain/memory/chat_message_histories/redis.py +1 -1
  361. langchain/memory/chat_message_histories/rocksetdb.py +1 -1
  362. langchain/memory/chat_message_histories/singlestoredb.py +1 -1
  363. langchain/memory/chat_message_histories/streamlit.py +1 -1
  364. langchain/memory/chat_message_histories/upstash_redis.py +1 -1
  365. langchain/memory/chat_message_histories/xata.py +1 -1
  366. langchain/memory/chat_message_histories/zep.py +1 -1
  367. langchain/memory/combined.py +13 -12
  368. langchain/memory/entity.py +84 -61
  369. langchain/memory/prompt.py +10 -11
  370. langchain/memory/readonly.py +0 -2
  371. langchain/memory/simple.py +1 -3
  372. langchain/memory/summary.py +13 -11
  373. langchain/memory/summary_buffer.py +17 -8
  374. langchain/memory/utils.py +3 -2
  375. langchain/memory/vectorstore.py +12 -5
  376. langchain/memory/vectorstore_token_buffer_memory.py +5 -5
  377. langchain/model_laboratory.py +12 -11
  378. langchain/output_parsers/__init__.py +4 -4
  379. langchain/output_parsers/boolean.py +7 -4
  380. langchain/output_parsers/combining.py +10 -5
  381. langchain/output_parsers/datetime.py +32 -31
  382. langchain/output_parsers/enum.py +5 -3
  383. langchain/output_parsers/fix.py +52 -52
  384. langchain/output_parsers/format_instructions.py +6 -8
  385. langchain/output_parsers/json.py +2 -2
  386. langchain/output_parsers/list.py +2 -2
  387. langchain/output_parsers/loading.py +9 -9
  388. langchain/output_parsers/openai_functions.py +3 -3
  389. langchain/output_parsers/openai_tools.py +1 -1
  390. langchain/output_parsers/pandas_dataframe.py +43 -47
  391. langchain/output_parsers/prompts.py +1 -2
  392. langchain/output_parsers/rail_parser.py +1 -1
  393. langchain/output_parsers/regex.py +7 -8
  394. langchain/output_parsers/regex_dict.py +7 -10
  395. langchain/output_parsers/retry.py +77 -78
  396. langchain/output_parsers/structured.py +11 -6
  397. langchain/output_parsers/yaml.py +15 -11
  398. langchain/prompts/__init__.py +5 -3
  399. langchain/prompts/base.py +5 -5
  400. langchain/prompts/chat.py +8 -8
  401. langchain/prompts/example_selector/__init__.py +3 -1
  402. langchain/prompts/example_selector/semantic_similarity.py +2 -2
  403. langchain/prompts/few_shot.py +1 -1
  404. langchain/prompts/loading.py +3 -3
  405. langchain/prompts/prompt.py +1 -1
  406. langchain/retrievers/__init__.py +5 -5
  407. langchain/retrievers/bedrock.py +2 -2
  408. langchain/retrievers/bm25.py +1 -1
  409. langchain/retrievers/contextual_compression.py +14 -8
  410. langchain/retrievers/docarray.py +1 -1
  411. langchain/retrievers/document_compressors/__init__.py +5 -4
  412. langchain/retrievers/document_compressors/base.py +12 -6
  413. langchain/retrievers/document_compressors/chain_extract.py +2 -2
  414. langchain/retrievers/document_compressors/chain_extract_prompt.py +2 -3
  415. langchain/retrievers/document_compressors/chain_filter.py +9 -9
  416. langchain/retrievers/document_compressors/chain_filter_prompt.py +1 -2
  417. langchain/retrievers/document_compressors/cohere_rerank.py +15 -15
  418. langchain/retrievers/document_compressors/embeddings_filter.py +21 -17
  419. langchain/retrievers/document_compressors/flashrank_rerank.py +1 -1
  420. langchain/retrievers/document_compressors/listwise_rerank.py +7 -5
  421. langchain/retrievers/ensemble.py +28 -25
  422. langchain/retrievers/google_cloud_documentai_warehouse.py +1 -1
  423. langchain/retrievers/google_vertex_ai_search.py +2 -2
  424. langchain/retrievers/kendra.py +10 -10
  425. langchain/retrievers/llama_index.py +1 -1
  426. langchain/retrievers/merger_retriever.py +11 -11
  427. langchain/retrievers/milvus.py +1 -1
  428. langchain/retrievers/multi_query.py +32 -26
  429. langchain/retrievers/multi_vector.py +20 -8
  430. langchain/retrievers/parent_document_retriever.py +18 -9
  431. langchain/retrievers/re_phraser.py +6 -5
  432. langchain/retrievers/self_query/base.py +138 -127
  433. langchain/retrievers/time_weighted_retriever.py +18 -7
  434. langchain/retrievers/zilliz.py +1 -1
  435. langchain/runnables/openai_functions.py +6 -2
  436. langchain/schema/__init__.py +23 -23
  437. langchain/schema/cache.py +1 -1
  438. langchain/schema/callbacks/base.py +7 -7
  439. langchain/schema/callbacks/manager.py +19 -19
  440. langchain/schema/callbacks/tracers/base.py +1 -1
  441. langchain/schema/callbacks/tracers/evaluation.py +1 -1
  442. langchain/schema/callbacks/tracers/langchain.py +1 -1
  443. langchain/schema/callbacks/tracers/langchain_v1.py +1 -1
  444. langchain/schema/callbacks/tracers/log_stream.py +1 -1
  445. langchain/schema/callbacks/tracers/schemas.py +8 -8
  446. langchain/schema/callbacks/tracers/stdout.py +3 -3
  447. langchain/schema/document.py +1 -1
  448. langchain/schema/language_model.py +2 -2
  449. langchain/schema/messages.py +12 -12
  450. langchain/schema/output.py +3 -3
  451. langchain/schema/output_parser.py +3 -3
  452. langchain/schema/runnable/__init__.py +3 -3
  453. langchain/schema/runnable/base.py +9 -9
  454. langchain/schema/runnable/config.py +5 -5
  455. langchain/schema/runnable/configurable.py +1 -1
  456. langchain/schema/runnable/history.py +1 -1
  457. langchain/schema/runnable/passthrough.py +1 -1
  458. langchain/schema/runnable/utils.py +16 -16
  459. langchain/schema/vectorstore.py +1 -1
  460. langchain/smith/__init__.py +1 -1
  461. langchain/smith/evaluation/__init__.py +2 -2
  462. langchain/smith/evaluation/config.py +10 -7
  463. langchain/smith/evaluation/name_generation.py +3 -3
  464. langchain/smith/evaluation/progress.py +11 -2
  465. langchain/smith/evaluation/runner_utils.py +179 -127
  466. langchain/smith/evaluation/string_run_evaluator.py +75 -68
  467. langchain/storage/__init__.py +2 -2
  468. langchain/storage/_lc_store.py +4 -2
  469. langchain/storage/encoder_backed.py +6 -2
  470. langchain/storage/file_system.py +19 -16
  471. langchain/storage/in_memory.py +1 -1
  472. langchain/storage/upstash_redis.py +1 -1
  473. langchain/text_splitter.py +15 -15
  474. langchain/tools/__init__.py +28 -26
  475. langchain/tools/ainetwork/app.py +1 -1
  476. langchain/tools/ainetwork/base.py +1 -1
  477. langchain/tools/ainetwork/owner.py +1 -1
  478. langchain/tools/ainetwork/rule.py +1 -1
  479. langchain/tools/ainetwork/transfer.py +1 -1
  480. langchain/tools/ainetwork/value.py +1 -1
  481. langchain/tools/amadeus/closest_airport.py +1 -1
  482. langchain/tools/amadeus/flight_search.py +1 -1
  483. langchain/tools/azure_cognitive_services/__init__.py +1 -1
  484. langchain/tools/base.py +4 -4
  485. langchain/tools/bearly/tool.py +1 -1
  486. langchain/tools/bing_search/__init__.py +1 -1
  487. langchain/tools/bing_search/tool.py +1 -1
  488. langchain/tools/dataforseo_api_search/__init__.py +1 -1
  489. langchain/tools/dataforseo_api_search/tool.py +1 -1
  490. langchain/tools/ddg_search/tool.py +1 -1
  491. langchain/tools/e2b_data_analysis/tool.py +2 -2
  492. langchain/tools/edenai/__init__.py +1 -1
  493. langchain/tools/file_management/__init__.py +1 -1
  494. langchain/tools/file_management/copy.py +1 -1
  495. langchain/tools/file_management/delete.py +1 -1
  496. langchain/tools/gmail/__init__.py +2 -2
  497. langchain/tools/gmail/get_message.py +1 -1
  498. langchain/tools/gmail/search.py +1 -1
  499. langchain/tools/gmail/send_message.py +1 -1
  500. langchain/tools/google_finance/__init__.py +1 -1
  501. langchain/tools/google_finance/tool.py +1 -1
  502. langchain/tools/google_scholar/__init__.py +1 -1
  503. langchain/tools/google_scholar/tool.py +1 -1
  504. langchain/tools/google_search/__init__.py +1 -1
  505. langchain/tools/google_search/tool.py +1 -1
  506. langchain/tools/google_serper/__init__.py +1 -1
  507. langchain/tools/google_serper/tool.py +1 -1
  508. langchain/tools/google_trends/__init__.py +1 -1
  509. langchain/tools/google_trends/tool.py +1 -1
  510. langchain/tools/jira/tool.py +20 -1
  511. langchain/tools/json/tool.py +25 -3
  512. langchain/tools/memorize/tool.py +1 -1
  513. langchain/tools/multion/__init__.py +1 -1
  514. langchain/tools/multion/update_session.py +1 -1
  515. langchain/tools/office365/__init__.py +2 -2
  516. langchain/tools/office365/events_search.py +1 -1
  517. langchain/tools/office365/messages_search.py +1 -1
  518. langchain/tools/office365/send_event.py +1 -1
  519. langchain/tools/office365/send_message.py +1 -1
  520. langchain/tools/openapi/utils/api_models.py +6 -6
  521. langchain/tools/playwright/__init__.py +5 -5
  522. langchain/tools/playwright/click.py +1 -1
  523. langchain/tools/playwright/extract_hyperlinks.py +1 -1
  524. langchain/tools/playwright/get_elements.py +1 -1
  525. langchain/tools/playwright/navigate.py +1 -1
  526. langchain/tools/plugin.py +2 -2
  527. langchain/tools/powerbi/tool.py +1 -1
  528. langchain/tools/python/__init__.py +2 -1
  529. langchain/tools/reddit_search/tool.py +1 -1
  530. langchain/tools/render.py +2 -2
  531. langchain/tools/requests/tool.py +2 -2
  532. langchain/tools/searchapi/tool.py +1 -1
  533. langchain/tools/searx_search/tool.py +1 -1
  534. langchain/tools/slack/get_message.py +1 -1
  535. langchain/tools/spark_sql/tool.py +1 -1
  536. langchain/tools/sql_database/tool.py +1 -1
  537. langchain/tools/tavily_search/__init__.py +1 -1
  538. langchain/tools/tavily_search/tool.py +1 -1
  539. langchain/tools/zapier/__init__.py +1 -1
  540. langchain/tools/zapier/tool.py +24 -2
  541. langchain/utilities/__init__.py +4 -4
  542. langchain/utilities/arcee.py +4 -4
  543. langchain/utilities/clickup.py +4 -4
  544. langchain/utilities/dalle_image_generator.py +1 -1
  545. langchain/utilities/dataforseo_api_search.py +1 -1
  546. langchain/utilities/opaqueprompts.py +1 -1
  547. langchain/utilities/reddit_search.py +1 -1
  548. langchain/utilities/sql_database.py +1 -1
  549. langchain/utilities/tavily_search.py +1 -1
  550. langchain/utilities/vertexai.py +2 -2
  551. langchain/utils/__init__.py +1 -1
  552. langchain/utils/aiter.py +1 -1
  553. langchain/utils/html.py +3 -3
  554. langchain/utils/input.py +1 -1
  555. langchain/utils/iter.py +1 -1
  556. langchain/utils/json_schema.py +1 -3
  557. langchain/utils/strings.py +1 -1
  558. langchain/utils/utils.py +6 -6
  559. langchain/vectorstores/__init__.py +5 -5
  560. langchain/vectorstores/alibabacloud_opensearch.py +1 -1
  561. langchain/vectorstores/azure_cosmos_db.py +1 -1
  562. langchain/vectorstores/clickhouse.py +1 -1
  563. langchain/vectorstores/elastic_vector_search.py +1 -1
  564. langchain/vectorstores/elasticsearch.py +2 -2
  565. langchain/vectorstores/myscale.py +1 -1
  566. langchain/vectorstores/neo4j_vector.py +1 -1
  567. langchain/vectorstores/pgembedding.py +1 -1
  568. langchain/vectorstores/qdrant.py +1 -1
  569. langchain/vectorstores/redis/__init__.py +1 -1
  570. langchain/vectorstores/redis/base.py +1 -1
  571. langchain/vectorstores/redis/filters.py +4 -4
  572. langchain/vectorstores/redis/schema.py +6 -6
  573. langchain/vectorstores/sklearn.py +2 -2
  574. langchain/vectorstores/starrocks.py +1 -1
  575. langchain/vectorstores/utils.py +1 -1
  576. {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/METADATA +4 -4
  577. {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/RECORD +580 -580
  578. {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/WHEEL +1 -1
  579. {langchain-0.3.26.dist-info → langchain-0.3.27.dist-info}/entry_points.txt +0 -0
  580. {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)
@@ -16,16 +16,18 @@ class CombinedMemory(BaseMemory):
16
16
  @field_validator("memories")
17
17
  @classmethod
18
18
  def check_repeated_memory_variable(
19
- cls, value: list[BaseMemory]
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
- raise ValueError(
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
- if val.input_key is None:
40
- warnings.warn(
41
- "When using CombinedMemory, "
42
- "input keys should be so the input is known. "
43
- f" Was not set on {val}"
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
- raise ValueError(
69
- f"The variable {key} is repeated in the CombinedMemory."
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
@@ -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
- raise ImportError(
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
- logger.error("Upstash Redis instance could not be initiated.")
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(f"Upstash Redis MEM get '{self.full_key_prefix}:{key}': '{res}'")
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
- f"Redis MEM set '{self.full_key_prefix}:{key}': '{value}' EX {self.ttl}"
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, f"{self.full_key_prefix}:*"
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
- raise ImportError(
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
- raise ImportError(
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 as error:
230
- logger.error(error)
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(f"REDIS MEM get '{self.full_key_prefix}:{key}': '{res}'")
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
- f"REDIS MEM set '{self.full_key_prefix}:{key}': '{value}' EX {self.ttl}"
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}:*"), 500
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
- raise ImportError(
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
- super().__init__(*args, **kwargs)
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
- with self.conn:
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
- query = f"""
334
- SELECT value
335
- FROM {self.full_table_name}
336
- WHERE key = ?
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
- query = f"""
349
- INSERT OR REPLACE INTO {self.full_table_name} (key, value)
350
- VALUES (?, ?)
351
- """
352
- with self.conn:
353
- self.conn.execute(query, (key, value))
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
- query = f"""
357
- DELETE FROM {self.full_table_name}
358
- WHERE key = ?
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
- query = f"""
365
- SELECT 1
366
- FROM {self.full_table_name}
367
- WHERE key = ?
368
- LIMIT 1
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
 
@@ -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}"
@@ -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
@@ -8,7 +8,7 @@ class SimpleMemory(BaseMemory):
8
8
  ever change between prompts.
9
9
  """
10
10
 
11
- memories: dict[str, Any] = dict()
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
@@ -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/" # noqa: E501
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, messages: list[BaseMessage], existing_summary: str
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, messages: list[BaseMessage], existing_summary: str
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], obj.buffer
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
- raise ValueError(
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:], self.buffer
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, human_prefix=self.human_prefix, ai_prefix=self.ai_prefix
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, human_prefix=self.human_prefix, ai_prefix=self.ai_prefix
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
- raise ValueError(
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, inputs: dict[str, Any], outputs: dict[str, str]
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, self.moving_summary_buffer
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, self.moving_summary_buffer
136
+ pruned_memory,
137
+ self.moving_summary_buffer,
129
138
  )
130
139
 
131
140
  def clear(self) -> None: