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