ryanbalch commited on
Commit
3653851
·
1 Parent(s): f2ddd4c

first langgraph workflow complete; integrations with zep and tools

Browse files
api/event_handlers/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .print_handler import PrintEventHandler
api/event_handlers/print_handler.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from colorama import Fore, Style
2
+ from langchain_core.callbacks import AsyncCallbackHandler
3
+ from langchain_core.outputs.llm_result import LLMResult
4
+
5
+
6
+ class PrintEventHandler(AsyncCallbackHandler):
7
+ """
8
+ Example async event handler: prints streaming tokens and tool results.
9
+ Replace with websocket or other side effects as needed.
10
+ """
11
+
12
+ def __init__(self, *args, **kwargs):
13
+ print('[INIT]')
14
+ super().__init__(*args, **kwargs)
15
+
16
+ async def on_chat_model_start(self, *args, **kwargs):
17
+ print('[CHAT START]')
18
+
19
+ async def on_llm_new_token(self, token: str, **kwargs):
20
+ if token:
21
+ print(Fore.YELLOW + token + Style.RESET_ALL, end="", flush=True)
22
+
23
+ async def on_llm_end(self, result: LLMResult, *args, **kwargs):
24
+ if self.is_chat_stream_end(result):
25
+ print('\n[END]')
26
+
27
+ async def on_tool_end(self, output: any, **kwargs):
28
+ print(f"\n{Fore.CYAN}[TOOL RESULT] {output}{Style.RESET_ALL}")
29
+
30
+ async def on_tool_start(self, input: any, *args, **kwargs):
31
+ print(f"\n{Fore.CYAN}[TOOL START]{Style.RESET_ALL}")
32
+
33
+ @staticmethod
34
+ def is_chat_stream_end(result: LLMResult) -> bool:
35
+ try:
36
+ content = result.generations[0][0].message.content
37
+ return bool(content and content.strip())
38
+ except (IndexError, AttributeError):
39
+ return False
40
+
41
+ # def __getattribute__(self, name):
42
+ # attr = super().__getattribute__(name)
43
+ # if callable(attr) and name.startswith("on_"):
44
+ # async def wrapper(*args, **kwargs):
45
+ # print(f"[EVENT] {name} args={args} kwargs={kwargs}")
46
+ # return await attr(*args, **kwargs)
47
+ # return wrapper
48
+ # return attr
api/poetry.lock CHANGED
@@ -269,7 +269,6 @@ files = [
269
  {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
270
  {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
271
  ]
272
- markers = {main = "platform_system == \"Windows\" or sys_platform == \"win32\"", dev = "sys_platform == \"win32\""}
273
 
274
  [[package]]
275
  name = "debugpy"
@@ -340,6 +339,69 @@ typing-extensions = ">=4.8.0"
340
  all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
341
  standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  [[package]]
344
  name = "h11"
345
  version = "0.14.0"
@@ -595,6 +657,46 @@ files = [
595
  {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"},
596
  ]
597
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
598
  [[package]]
599
  name = "langchain-core"
600
  version = "0.3.59"
@@ -636,6 +738,89 @@ langchain-core = ">=0.3.58,<1.0.0"
636
  openai = ">=1.68.2,<2.0.0"
637
  tiktoken = ">=0.7,<1"
638
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
639
  [[package]]
640
  name = "langsmith"
641
  version = "0.3.42"
@@ -765,7 +950,6 @@ description = "Fast, correct Python JSON library supporting dataclasses, datetim
765
  optional = false
766
  python-versions = ">=3.9"
767
  groups = ["main"]
768
- markers = "platform_python_implementation != \"PyPy\""
769
  files = [
770
  {file = "orjson-3.10.18-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a45e5d68066b408e4bc383b6e4ef05e717c65219a9e1390abc6155a520cac402"},
771
  {file = "orjson-3.10.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be3b9b143e8b9db05368b13b04c84d37544ec85bb97237b3a923f076265ec89c"},
@@ -841,6 +1025,57 @@ files = [
841
  {file = "orjson-3.10.18.tar.gz", hash = "sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53"},
842
  ]
843
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
844
  [[package]]
845
  name = "packaging"
846
  version = "24.2"
@@ -1286,6 +1521,102 @@ files = [
1286
  {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
1287
  ]
1288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1289
  [[package]]
1290
  name = "starlette"
1291
  version = "0.46.1"
@@ -1689,6 +2020,139 @@ files = [
1689
  {file = "websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"},
1690
  ]
1691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1692
  [[package]]
1693
  name = "zep-cloud"
1694
  version = "2.12.1"
@@ -1822,4 +2286,4 @@ cffi = ["cffi (>=1.11)"]
1822
  [metadata]
1823
  lock-version = "2.1"
1824
  python-versions = "^3.12"
1825
- content-hash = "c212f5e8502ec8ee9a6528940c67b96ce7117dcbed72522f0476680f68f8e01f"
 
269
  {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
270
  {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
271
  ]
 
272
 
273
  [[package]]
274
  name = "debugpy"
 
339
  all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
340
  standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
341
 
342
+ [[package]]
343
+ name = "greenlet"
344
+ version = "3.2.2"
345
+ description = "Lightweight in-process concurrent programming"
346
+ optional = false
347
+ python-versions = ">=3.9"
348
+ groups = ["main"]
349
+ markers = "python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"
350
+ files = [
351
+ {file = "greenlet-3.2.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c49e9f7c6f625507ed83a7485366b46cbe325717c60837f7244fc99ba16ba9d6"},
352
+ {file = "greenlet-3.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3cc1a3ed00ecfea8932477f729a9f616ad7347a5e55d50929efa50a86cb7be7"},
353
+ {file = "greenlet-3.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c9896249fbef2c615853b890ee854f22c671560226c9221cfd27c995db97e5c"},
354
+ {file = "greenlet-3.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7791dcb496ec53d60c7f1c78eaa156c21f402dda38542a00afc3e20cae0f480f"},
355
+ {file = "greenlet-3.2.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d8009ae46259e31bc73dc183e402f548e980c96f33a6ef58cc2e7865db012e13"},
356
+ {file = "greenlet-3.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fd9fb7c941280e2c837b603850efc93c999ae58aae2b40765ed682a6907ebbc5"},
357
+ {file = "greenlet-3.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:00cd814b8959b95a546e47e8d589610534cfb71f19802ea8a2ad99d95d702057"},
358
+ {file = "greenlet-3.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:d0cb7d47199001de7658c213419358aa8937df767936506db0db7ce1a71f4a2f"},
359
+ {file = "greenlet-3.2.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:dcb9cebbf3f62cb1e5afacae90761ccce0effb3adaa32339a0670fe7805d8068"},
360
+ {file = "greenlet-3.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf3fc9145141250907730886b031681dfcc0de1c158f3cc51c092223c0f381ce"},
361
+ {file = "greenlet-3.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:efcdfb9df109e8a3b475c016f60438fcd4be68cd13a365d42b35914cdab4bb2b"},
362
+ {file = "greenlet-3.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71566302219b17ca354eb274dfd29b8da3c268e41b646f330e324e3967546a74"},
363
+ {file = "greenlet-3.2.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3091bc45e6b0c73f225374fefa1536cd91b1e987377b12ef5b19129b07d93ebe"},
364
+ {file = "greenlet-3.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:44671c29da26539a5f142257eaba5110f71887c24d40df3ac87f1117df589e0e"},
365
+ {file = "greenlet-3.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c23ea227847c9dbe0b3910f5c0dd95658b607137614eb821e6cbaecd60d81cc6"},
366
+ {file = "greenlet-3.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:0a16fb934fcabfdfacf21d79e6fed81809d8cd97bc1be9d9c89f0e4567143d7b"},
367
+ {file = "greenlet-3.2.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:df4d1509efd4977e6a844ac96d8be0b9e5aa5d5c77aa27ca9f4d3f92d3fcf330"},
368
+ {file = "greenlet-3.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da956d534a6d1b9841f95ad0f18ace637668f680b1339ca4dcfb2c1837880a0b"},
369
+ {file = "greenlet-3.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c7b15fb9b88d9ee07e076f5a683027bc3befd5bb5d25954bb633c385d8b737e"},
370
+ {file = "greenlet-3.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ae572c996ae4b5e122331e12bbb971ea49c08cc7c232d1bd43150800a2d6c65"},
371
+ {file = "greenlet-3.2.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02f5972ff02c9cf615357c17ab713737cccfd0eaf69b951084a9fd43f39833d3"},
372
+ {file = "greenlet-3.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4fefc7aa68b34b9224490dfda2e70ccf2131368493add64b4ef2d372955c207e"},
373
+ {file = "greenlet-3.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a31ead8411a027c2c4759113cf2bd473690517494f3d6e4bf67064589afcd3c5"},
374
+ {file = "greenlet-3.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:b24c7844c0a0afc3ccbeb0b807adeefb7eff2b5599229ecedddcfeb0ef333bec"},
375
+ {file = "greenlet-3.2.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:3ab7194ee290302ca15449f601036007873028712e92ca15fc76597a0aeb4c59"},
376
+ {file = "greenlet-3.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc5c43bb65ec3669452af0ab10729e8fdc17f87a1f2ad7ec65d4aaaefabf6bf"},
377
+ {file = "greenlet-3.2.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:decb0658ec19e5c1f519faa9a160c0fc85a41a7e6654b3ce1b44b939f8bf1325"},
378
+ {file = "greenlet-3.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1919cbdc1c53ef739c94cf2985056bcc0838c1f217b57647cbf4578576c63825"},
379
+ {file = "greenlet-3.2.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3885f85b61798f4192d544aac7b25a04ece5fe2704670b4ab73c2d2c14ab740d"},
380
+ {file = "greenlet-3.2.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:85f3e248507125bf4af607a26fd6cb8578776197bd4b66e35229cdf5acf1dfbf"},
381
+ {file = "greenlet-3.2.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1e76106b6fc55fa3d6fe1c527f95ee65e324a13b62e243f77b48317346559708"},
382
+ {file = "greenlet-3.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:fe46d4f8e94e637634d54477b0cfabcf93c53f29eedcbdeecaf2af32029b4421"},
383
+ {file = "greenlet-3.2.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba30e88607fb6990544d84caf3c706c4b48f629e18853fc6a646f82db9629418"},
384
+ {file = "greenlet-3.2.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:055916fafad3e3388d27dd68517478933a97edc2fc54ae79d3bec827de2c64c4"},
385
+ {file = "greenlet-3.2.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89c69e9a10670eb7a66b8cef6354c24671ba241f46152dd3eed447f79c29fb5b"},
386
+ {file = "greenlet-3.2.2-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02a98600899ca1ca5d3a2590974c9e3ec259503b2d6ba6527605fcd74e08e207"},
387
+ {file = "greenlet-3.2.2-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:b50a8c5c162469c3209e5ec92ee4f95c8231b11db6a04db09bbe338176723bb8"},
388
+ {file = "greenlet-3.2.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:45f9f4853fb4cc46783085261c9ec4706628f3b57de3e68bae03e8f8b3c0de51"},
389
+ {file = "greenlet-3.2.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:9ea5231428af34226c05f927e16fc7f6fa5e39e3ad3cd24ffa48ba53a47f4240"},
390
+ {file = "greenlet-3.2.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:1e4747712c4365ef6765708f948acc9c10350719ca0545e362c24ab973017370"},
391
+ {file = "greenlet-3.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:782743700ab75716650b5238a4759f840bb2dcf7bff56917e9ffdf9f1f23ec59"},
392
+ {file = "greenlet-3.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:354f67445f5bed6604e493a06a9a49ad65675d3d03477d38a4db4a427e9aad0e"},
393
+ {file = "greenlet-3.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cb8553ee954536500d88a1a2f58fcb867e45125e600e80f586ade399b3f8819"},
394
+ {file = "greenlet-3.2.2-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1592a615b598643dbfd566bac8467f06c8c8ab6e56f069e573832ed1d5d528cc"},
395
+ {file = "greenlet-3.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1f72667cc341c95184f1c68f957cb2d4fc31eef81646e8e59358a10ce6689457"},
396
+ {file = "greenlet-3.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a8fa80665b1a29faf76800173ff5325095f3e66a78e62999929809907aca5659"},
397
+ {file = "greenlet-3.2.2-cp39-cp39-win32.whl", hash = "sha256:6629311595e3fe7304039c67f00d145cd1d38cf723bb5b99cc987b23c1433d61"},
398
+ {file = "greenlet-3.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:eeb27bece45c0c2a5842ac4c5a1b5c2ceaefe5711078eed4e8043159fa05c834"},
399
+ ]
400
+
401
+ [package.extras]
402
+ docs = ["Sphinx", "furo"]
403
+ test = ["objgraph", "psutil"]
404
+
405
  [[package]]
406
  name = "h11"
407
  version = "0.14.0"
 
657
  {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"},
658
  ]
659
 
660
+ [[package]]
661
+ name = "langchain"
662
+ version = "0.3.25"
663
+ description = "Building applications with LLMs through composability"
664
+ optional = false
665
+ python-versions = ">=3.9"
666
+ groups = ["main"]
667
+ files = [
668
+ {file = "langchain-0.3.25-py3-none-any.whl", hash = "sha256:931f7d2d1eaf182f9f41c5e3272859cfe7f94fc1f7cef6b3e5a46024b4884c21"},
669
+ {file = "langchain-0.3.25.tar.gz", hash = "sha256:a1d72aa39546a23db08492d7228464af35c9ee83379945535ceef877340d2a3a"},
670
+ ]
671
+
672
+ [package.dependencies]
673
+ langchain-core = ">=0.3.58,<1.0.0"
674
+ langchain-text-splitters = ">=0.3.8,<1.0.0"
675
+ langsmith = ">=0.1.17,<0.4"
676
+ pydantic = ">=2.7.4,<3.0.0"
677
+ PyYAML = ">=5.3"
678
+ requests = ">=2,<3"
679
+ SQLAlchemy = ">=1.4,<3"
680
+
681
+ [package.extras]
682
+ anthropic = ["langchain-anthropic"]
683
+ aws = ["langchain-aws"]
684
+ azure-ai = ["langchain-azure-ai"]
685
+ cohere = ["langchain-cohere"]
686
+ community = ["langchain-community"]
687
+ deepseek = ["langchain-deepseek"]
688
+ fireworks = ["langchain-fireworks"]
689
+ google-genai = ["langchain-google-genai"]
690
+ google-vertexai = ["langchain-google-vertexai"]
691
+ groq = ["langchain-groq"]
692
+ huggingface = ["langchain-huggingface"]
693
+ mistralai = ["langchain-mistralai"]
694
+ ollama = ["langchain-ollama"]
695
+ openai = ["langchain-openai"]
696
+ perplexity = ["langchain-perplexity"]
697
+ together = ["langchain-together"]
698
+ xai = ["langchain-xai"]
699
+
700
  [[package]]
701
  name = "langchain-core"
702
  version = "0.3.59"
 
738
  openai = ">=1.68.2,<2.0.0"
739
  tiktoken = ">=0.7,<1"
740
 
741
+ [[package]]
742
+ name = "langchain-text-splitters"
743
+ version = "0.3.8"
744
+ description = "LangChain text splitting utilities"
745
+ optional = false
746
+ python-versions = "<4.0,>=3.9"
747
+ groups = ["main"]
748
+ files = [
749
+ {file = "langchain_text_splitters-0.3.8-py3-none-any.whl", hash = "sha256:e75cc0f4ae58dcf07d9f18776400cf8ade27fadd4ff6d264df6278bb302f6f02"},
750
+ {file = "langchain_text_splitters-0.3.8.tar.gz", hash = "sha256:116d4b9f2a22dda357d0b79e30acf005c5518177971c66a9f1ab0edfdb0f912e"},
751
+ ]
752
+
753
+ [package.dependencies]
754
+ langchain-core = ">=0.3.51,<1.0.0"
755
+
756
+ [[package]]
757
+ name = "langgraph"
758
+ version = "0.4.3"
759
+ description = "Building stateful, multi-actor applications with LLMs"
760
+ optional = false
761
+ python-versions = ">=3.9"
762
+ groups = ["main"]
763
+ files = [
764
+ {file = "langgraph-0.4.3-py3-none-any.whl", hash = "sha256:dec926e034f4d440b92a3c52139cb6e9763bc1791e79a6ea53a233309cec864f"},
765
+ {file = "langgraph-0.4.3.tar.gz", hash = "sha256:272d5d5903f2c2882dbeeba849846a0f2500bd83fb3734a3801ebe64c1a60bdd"},
766
+ ]
767
+
768
+ [package.dependencies]
769
+ langchain-core = {version = ">=0.1", markers = "python_version < \"4.0\""}
770
+ langgraph-checkpoint = ">=2.0.10,<3.0.0"
771
+ langgraph-prebuilt = {version = ">=0.1.8", markers = "python_version < \"4.0\""}
772
+ langgraph-sdk = {version = ">=0.1.42", markers = "python_version < \"4.0\""}
773
+ pydantic = ">=2.7.4"
774
+ xxhash = ">=3.5.0,<4.0.0"
775
+
776
+ [[package]]
777
+ name = "langgraph-checkpoint"
778
+ version = "2.0.25"
779
+ description = "Library with base interfaces for LangGraph checkpoint savers."
780
+ optional = false
781
+ python-versions = "<4.0.0,>=3.9.0"
782
+ groups = ["main"]
783
+ files = [
784
+ {file = "langgraph_checkpoint-2.0.25-py3-none-any.whl", hash = "sha256:23416a0f5bc9dd712ac10918fc13e8c9c4530c419d2985a441df71a38fc81602"},
785
+ {file = "langgraph_checkpoint-2.0.25.tar.gz", hash = "sha256:77a63cab7b5f84dec1d49db561326ec28bdd48bcefb7fe4ac372069d2609287b"},
786
+ ]
787
+
788
+ [package.dependencies]
789
+ langchain-core = ">=0.2.38,<0.4"
790
+ ormsgpack = ">=1.8.0,<2.0.0"
791
+
792
+ [[package]]
793
+ name = "langgraph-prebuilt"
794
+ version = "0.1.8"
795
+ description = "Library with high-level APIs for creating and executing LangGraph agents and tools."
796
+ optional = false
797
+ python-versions = "<4.0.0,>=3.9.0"
798
+ groups = ["main"]
799
+ files = [
800
+ {file = "langgraph_prebuilt-0.1.8-py3-none-any.whl", hash = "sha256:ae97b828ae00be2cefec503423aa782e1bff165e9b94592e224da132f2526968"},
801
+ {file = "langgraph_prebuilt-0.1.8.tar.gz", hash = "sha256:4de7659151829b2b955b6798df6800e580e617782c15c2c5b29b139697491831"},
802
+ ]
803
+
804
+ [package.dependencies]
805
+ langchain-core = ">=0.2.43,<0.3.0 || >0.3.0,<0.3.1 || >0.3.1,<0.3.2 || >0.3.2,<0.3.3 || >0.3.3,<0.3.4 || >0.3.4,<0.3.5 || >0.3.5,<0.3.6 || >0.3.6,<0.3.7 || >0.3.7,<0.3.8 || >0.3.8,<0.3.9 || >0.3.9,<0.3.10 || >0.3.10,<0.3.11 || >0.3.11,<0.3.12 || >0.3.12,<0.3.13 || >0.3.13,<0.3.14 || >0.3.14,<0.3.15 || >0.3.15,<0.3.16 || >0.3.16,<0.3.17 || >0.3.17,<0.3.18 || >0.3.18,<0.3.19 || >0.3.19,<0.3.20 || >0.3.20,<0.3.21 || >0.3.21,<0.3.22 || >0.3.22,<0.4.0"
806
+ langgraph-checkpoint = ">=2.0.10,<3.0.0"
807
+
808
+ [[package]]
809
+ name = "langgraph-sdk"
810
+ version = "0.1.66"
811
+ description = "SDK for interacting with LangGraph API"
812
+ optional = false
813
+ python-versions = ">=3.9"
814
+ groups = ["main"]
815
+ files = [
816
+ {file = "langgraph_sdk-0.1.66-py3-none-any.whl", hash = "sha256:f781c63f3e913d3d6bedb02cb84d775cda64e3cdf3282fd387bdd8faaf53c603"},
817
+ {file = "langgraph_sdk-0.1.66.tar.gz", hash = "sha256:81474ad4555a06004cc7a2f4ab477135d5eaf7db11fbcf2a69257fb2d717582e"},
818
+ ]
819
+
820
+ [package.dependencies]
821
+ httpx = ">=0.25.2"
822
+ orjson = ">=3.10.1"
823
+
824
  [[package]]
825
  name = "langsmith"
826
  version = "0.3.42"
 
950
  optional = false
951
  python-versions = ">=3.9"
952
  groups = ["main"]
 
953
  files = [
954
  {file = "orjson-3.10.18-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a45e5d68066b408e4bc383b6e4ef05e717c65219a9e1390abc6155a520cac402"},
955
  {file = "orjson-3.10.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be3b9b143e8b9db05368b13b04c84d37544ec85bb97237b3a923f076265ec89c"},
 
1025
  {file = "orjson-3.10.18.tar.gz", hash = "sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53"},
1026
  ]
1027
 
1028
+ [[package]]
1029
+ name = "ormsgpack"
1030
+ version = "1.9.1"
1031
+ description = "Fast, correct Python msgpack library supporting dataclasses, datetimes, and numpy"
1032
+ optional = false
1033
+ python-versions = ">=3.9"
1034
+ groups = ["main"]
1035
+ files = [
1036
+ {file = "ormsgpack-1.9.1-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f1f804fd9c0fd84213a6022c34172f82323b34afa7052a4af18797582cf56365"},
1037
+ {file = "ormsgpack-1.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eab5cec99c46276b37071d570aab98603f3d0309b3818da3247eb64bb95e5cfc"},
1038
+ {file = "ormsgpack-1.9.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c12c6bb30e6df6fc0213b77f0a5e143f371d618be2e8eb4d555340ce01c6900"},
1039
+ {file = "ormsgpack-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994d4bbb7ee333264a3e55e30ccee063df6635d785f21a08bf52f67821454a51"},
1040
+ {file = "ormsgpack-1.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a668a584cf4bb6e1a6ef5a35f3f0d0fdae80cfb7237344ad19a50cce8c79317b"},
1041
+ {file = "ormsgpack-1.9.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:aaf77699203822638014c604d100f132583844d4fd01eb639a2266970c02cfdf"},
1042
+ {file = "ormsgpack-1.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:003d7e1992b447898caf25a820b3037ec68a57864b3e2f34b64693b7d60a9984"},
1043
+ {file = "ormsgpack-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:67fefc77e4ba9469f79426769eb4c78acf21f22bef3ab1239a72dd728036ffc2"},
1044
+ {file = "ormsgpack-1.9.1-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:16eaf32c33ab4249e242181d59e2509b8e0330d6f65c1d8bf08c3dea38fd7c02"},
1045
+ {file = "ormsgpack-1.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c70f2e5b2f9975536e8f7936a9721601dc54febe363d2d82f74c9b31d4fe1c65"},
1046
+ {file = "ormsgpack-1.9.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:17c9e18b07d69e3db2e0f8af4731040175e11bdfde78ad8e28126e9e66ec5167"},
1047
+ {file = "ormsgpack-1.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73538d749096bb6470328601a2be8f7bdec28849ec6fd19595c232a5848d7124"},
1048
+ {file = "ormsgpack-1.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:827ff71de228cfd6d07b9d6b47911aa61b1e8dc995dec3caf8fdcdf4f874bcd0"},
1049
+ {file = "ormsgpack-1.9.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7307f808b3df282c8e8ed92c6ebceeb3eea3d8eeec808438f3f212226b25e217"},
1050
+ {file = "ormsgpack-1.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f30aad7fb083bed1c540a3c163c6a9f63a94e3c538860bf8f13386c29b560ad5"},
1051
+ {file = "ormsgpack-1.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:829a1b4c5bc3c38ece0c55cf91ebc09c3b987fceb24d3f680c2bcd03fd3789a4"},
1052
+ {file = "ormsgpack-1.9.1-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:1ede445fc3fdba219bb0e0d1f289df26a9c7602016b7daac6fafe8fe4e91548f"},
1053
+ {file = "ormsgpack-1.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db50b9f918e25b289114312ed775794d0978b469831b992bdc65bfe20b91fe30"},
1054
+ {file = "ormsgpack-1.9.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c7d8fc58e4333308f58ec720b1ee6b12b2b3fe2d2d8f0766ab751cb351e8757"},
1055
+ {file = "ormsgpack-1.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeee6d08c040db265cb8563444aba343ecb32cbdbe2414a489dcead9f70c6765"},
1056
+ {file = "ormsgpack-1.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2fbb8181c198bdc413a4e889e5200f010724eea4b6d5a9a7eee2df039ac04aca"},
1057
+ {file = "ormsgpack-1.9.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:16488f094ac0e2250cceea6caf72962614aa432ee11dd57ef45e1ad25ece3eff"},
1058
+ {file = "ormsgpack-1.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:422d960bfd6ad88be20794f50ec7953d8f7a0f2df60e19d0e8feb994e2ed64ee"},
1059
+ {file = "ormsgpack-1.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:e6e2f9eab527cf43fb4a4293e493370276b1c8716cf305689202d646c6a782ef"},
1060
+ {file = "ormsgpack-1.9.1-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ac61c18d9dd085e8519b949f7e655f7fb07909fd09c53b4338dd33309012e289"},
1061
+ {file = "ormsgpack-1.9.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134840b8c6615da2c24ce77bd12a46098015c808197a9995c7a2d991e1904eec"},
1062
+ {file = "ormsgpack-1.9.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:38fd42618f626394b2c7713c5d4bcbc917254e9753d5d4cde460658b51b11a74"},
1063
+ {file = "ormsgpack-1.9.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d36397333ad07b9eba4c2e271fa78951bd81afc059c85a6e9f6c0eb2de07cda"},
1064
+ {file = "ormsgpack-1.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:603063089597917d04e4c1b1d53988a34f7dc2ff1a03adcfd1cf4ae966d5fba6"},
1065
+ {file = "ormsgpack-1.9.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:94bbf2b185e0cb721ceaba20e64b7158e6caf0cecd140ca29b9f05a8d5e91e2f"},
1066
+ {file = "ormsgpack-1.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38f380b1e8c96a712eb302b9349347385161a8e29046868ae2bfdfcb23e2692"},
1067
+ {file = "ormsgpack-1.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:a4bc63fb30db94075611cedbbc3d261dd17cf2aa8ff75a0fd684cd45ca29cb1b"},
1068
+ {file = "ormsgpack-1.9.1-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e95909248bece8e88a310a913838f17ff5a39190aa4e61de909c3cd27f59744b"},
1069
+ {file = "ormsgpack-1.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3939188810c5c641d6b207f29994142ae2b1c70534f7839bbd972d857ac2072"},
1070
+ {file = "ormsgpack-1.9.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b6476344a585aea00a2acc9fd07355bf2daac04062cfdd480fa83ec3e2403b"},
1071
+ {file = "ormsgpack-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d8b9d53da82b31662ce5a3834b65479cf794a34befb9fc50baa51518383250"},
1072
+ {file = "ormsgpack-1.9.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3933d4b0c0d404ee234dbc372836d6f2d2f4b6330c2a2fb9709ba4eaebfae7ba"},
1073
+ {file = "ormsgpack-1.9.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:f824e94a7969f0aee9a6847ec232cf731a03b8734951c2a774dd4762308ea2d2"},
1074
+ {file = "ormsgpack-1.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c1f3f2295374020f9650e4aa7af6403ff016a0d92778b4a48bb3901fd801232d"},
1075
+ {file = "ormsgpack-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:92eb1b4f7b168da47f547329b4b58d16d8f19508a97ce5266567385d42d81968"},
1076
+ {file = "ormsgpack-1.9.1.tar.gz", hash = "sha256:3da6e63d82565e590b98178545e64f0f8506137b92bd31a2d04fd7c82baf5794"},
1077
+ ]
1078
+
1079
  [[package]]
1080
  name = "packaging"
1081
  version = "24.2"
 
1521
  {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
1522
  ]
1523
 
1524
+ [[package]]
1525
+ name = "sqlalchemy"
1526
+ version = "2.0.40"
1527
+ description = "Database Abstraction Library"
1528
+ optional = false
1529
+ python-versions = ">=3.7"
1530
+ groups = ["main"]
1531
+ files = [
1532
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ae9597cab738e7cc823f04a704fb754a9249f0b6695a6aeb63b74055cd417a96"},
1533
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a5c21ab099a83d669ebb251fddf8f5cee4d75ea40a5a1653d9c43d60e20867"},
1534
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bece9527f5a98466d67fb5d34dc560c4da964240d8b09024bb21c1246545e04e"},
1535
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:8bb131ffd2165fae48162c7bbd0d97c84ab961deea9b8bab16366543deeab625"},
1536
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9408fd453d5f8990405cc9def9af46bfbe3183e6110401b407c2d073c3388f47"},
1537
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-win32.whl", hash = "sha256:00a494ea6f42a44c326477b5bee4e0fc75f6a80c01570a32b57e89cf0fbef85a"},
1538
+ {file = "SQLAlchemy-2.0.40-cp37-cp37m-win_amd64.whl", hash = "sha256:c7b927155112ac858357ccf9d255dd8c044fd9ad2dc6ce4c4149527c901fa4c3"},
1539
+ {file = "sqlalchemy-2.0.40-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f1ea21bef99c703f44444ad29c2c1b6bd55d202750b6de8e06a955380f4725d7"},
1540
+ {file = "sqlalchemy-2.0.40-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:afe63b208153f3a7a2d1a5b9df452b0673082588933e54e7c8aac457cf35e758"},
1541
+ {file = "sqlalchemy-2.0.40-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8aae085ea549a1eddbc9298b113cffb75e514eadbb542133dd2b99b5fb3b6af"},
1542
+ {file = "sqlalchemy-2.0.40-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ea9181284754d37db15156eb7be09c86e16e50fbe77610e9e7bee09291771a1"},
1543
+ {file = "sqlalchemy-2.0.40-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5434223b795be5c5ef8244e5ac98056e290d3a99bdcc539b916e282b160dda00"},
1544
+ {file = "sqlalchemy-2.0.40-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:15d08d5ef1b779af6a0909b97be6c1fd4298057504eb6461be88bd1696cb438e"},
1545
+ {file = "sqlalchemy-2.0.40-cp310-cp310-win32.whl", hash = "sha256:cd2f75598ae70bcfca9117d9e51a3b06fe29edd972fdd7fd57cc97b4dbf3b08a"},
1546
+ {file = "sqlalchemy-2.0.40-cp310-cp310-win_amd64.whl", hash = "sha256:2cbafc8d39ff1abdfdda96435f38fab141892dc759a2165947d1a8fffa7ef596"},
1547
+ {file = "sqlalchemy-2.0.40-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f6bacab7514de6146a1976bc56e1545bee247242fab030b89e5f70336fc0003e"},
1548
+ {file = "sqlalchemy-2.0.40-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5654d1ac34e922b6c5711631f2da497d3a7bffd6f9f87ac23b35feea56098011"},
1549
+ {file = "sqlalchemy-2.0.40-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35904d63412db21088739510216e9349e335f142ce4a04b69e2528020ee19ed4"},
1550
+ {file = "sqlalchemy-2.0.40-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7a80ed86d6aaacb8160a1caef6680d4ddd03c944d985aecee940d168c411d1"},
1551
+ {file = "sqlalchemy-2.0.40-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:519624685a51525ddaa7d8ba8265a1540442a2ec71476f0e75241eb8263d6f51"},
1552
+ {file = "sqlalchemy-2.0.40-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2ee5f9999a5b0e9689bed96e60ee53c3384f1a05c2dd8068cc2e8361b0df5b7a"},
1553
+ {file = "sqlalchemy-2.0.40-cp311-cp311-win32.whl", hash = "sha256:c0cae71e20e3c02c52f6b9e9722bca70e4a90a466d59477822739dc31ac18b4b"},
1554
+ {file = "sqlalchemy-2.0.40-cp311-cp311-win_amd64.whl", hash = "sha256:574aea2c54d8f1dd1699449f332c7d9b71c339e04ae50163a3eb5ce4c4325ee4"},
1555
+ {file = "sqlalchemy-2.0.40-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9d3b31d0a1c44b74d3ae27a3de422dfccd2b8f0b75e51ecb2faa2bf65ab1ba0d"},
1556
+ {file = "sqlalchemy-2.0.40-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:37f7a0f506cf78c80450ed1e816978643d3969f99c4ac6b01104a6fe95c5490a"},
1557
+ {file = "sqlalchemy-2.0.40-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bb933a650323e476a2e4fbef8997a10d0003d4da996aad3fd7873e962fdde4d"},
1558
+ {file = "sqlalchemy-2.0.40-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6959738971b4745eea16f818a2cd086fb35081383b078272c35ece2b07012716"},
1559
+ {file = "sqlalchemy-2.0.40-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:110179728e442dae85dd39591beb74072ae4ad55a44eda2acc6ec98ead80d5f2"},
1560
+ {file = "sqlalchemy-2.0.40-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8040680eaacdce4d635f12c55c714f3d4c7f57da2bc47a01229d115bd319191"},
1561
+ {file = "sqlalchemy-2.0.40-cp312-cp312-win32.whl", hash = "sha256:650490653b110905c10adac69408380688cefc1f536a137d0d69aca1069dc1d1"},
1562
+ {file = "sqlalchemy-2.0.40-cp312-cp312-win_amd64.whl", hash = "sha256:2be94d75ee06548d2fc591a3513422b873490efb124048f50556369a834853b0"},
1563
+ {file = "sqlalchemy-2.0.40-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:915866fd50dd868fdcc18d61d8258db1bf9ed7fbd6dfec960ba43365952f3b01"},
1564
+ {file = "sqlalchemy-2.0.40-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a4c5a2905a9ccdc67a8963e24abd2f7afcd4348829412483695c59e0af9a705"},
1565
+ {file = "sqlalchemy-2.0.40-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55028d7a3ebdf7ace492fab9895cbc5270153f75442a0472d8516e03159ab364"},
1566
+ {file = "sqlalchemy-2.0.40-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6cfedff6878b0e0d1d0a50666a817ecd85051d12d56b43d9d425455e608b5ba0"},
1567
+ {file = "sqlalchemy-2.0.40-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bb19e30fdae77d357ce92192a3504579abe48a66877f476880238a962e5b96db"},
1568
+ {file = "sqlalchemy-2.0.40-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:16d325ea898f74b26ffcd1cf8c593b0beed8714f0317df2bed0d8d1de05a8f26"},
1569
+ {file = "sqlalchemy-2.0.40-cp313-cp313-win32.whl", hash = "sha256:a669cbe5be3c63f75bcbee0b266779706f1a54bcb1000f302685b87d1b8c1500"},
1570
+ {file = "sqlalchemy-2.0.40-cp313-cp313-win_amd64.whl", hash = "sha256:641ee2e0834812d657862f3a7de95e0048bdcb6c55496f39c6fa3d435f6ac6ad"},
1571
+ {file = "sqlalchemy-2.0.40-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:50f5885bbed261fc97e2e66c5156244f9704083a674b8d17f24c72217d29baf5"},
1572
+ {file = "sqlalchemy-2.0.40-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cf0e99cdb600eabcd1d65cdba0d3c91418fee21c4aa1d28db47d095b1064a7d8"},
1573
+ {file = "sqlalchemy-2.0.40-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe147fcd85aaed53ce90645c91ed5fca0cc88a797314c70dfd9d35925bd5d106"},
1574
+ {file = "sqlalchemy-2.0.40-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf7cee56bd552385c1ee39af360772fbfc2f43be005c78d1140204ad6148438"},
1575
+ {file = "sqlalchemy-2.0.40-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4aeb939bcac234b88e2d25d5381655e8353fe06b4e50b1c55ecffe56951d18c2"},
1576
+ {file = "sqlalchemy-2.0.40-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c268b5100cfeaa222c40f55e169d484efa1384b44bf9ca415eae6d556f02cb08"},
1577
+ {file = "sqlalchemy-2.0.40-cp38-cp38-win32.whl", hash = "sha256:46628ebcec4f23a1584fb52f2abe12ddb00f3bb3b7b337618b80fc1b51177aff"},
1578
+ {file = "sqlalchemy-2.0.40-cp38-cp38-win_amd64.whl", hash = "sha256:7e0505719939e52a7b0c65d20e84a6044eb3712bb6f239c6b1db77ba8e173a37"},
1579
+ {file = "sqlalchemy-2.0.40-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c884de19528e0fcd9dc34ee94c810581dd6e74aef75437ff17e696c2bfefae3e"},
1580
+ {file = "sqlalchemy-2.0.40-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1abb387710283fc5983d8a1209d9696a4eae9db8d7ac94b402981fe2fe2e39ad"},
1581
+ {file = "sqlalchemy-2.0.40-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cfa124eda500ba4b0d3afc3e91ea27ed4754e727c7f025f293a22f512bcd4c9"},
1582
+ {file = "sqlalchemy-2.0.40-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b6b28d303b9d57c17a5164eb1fd2d5119bb6ff4413d5894e74873280483eeb5"},
1583
+ {file = "sqlalchemy-2.0.40-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b5a5bbe29c10c5bfd63893747a1bf6f8049df607638c786252cb9243b86b6706"},
1584
+ {file = "sqlalchemy-2.0.40-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f0fda83e113bb0fb27dc003685f32a5dcb99c9c4f41f4fa0838ac35265c23b5c"},
1585
+ {file = "sqlalchemy-2.0.40-cp39-cp39-win32.whl", hash = "sha256:957f8d85d5e834397ef78a6109550aeb0d27a53b5032f7a57f2451e1adc37e98"},
1586
+ {file = "sqlalchemy-2.0.40-cp39-cp39-win_amd64.whl", hash = "sha256:1ffdf9c91428e59744f8e6f98190516f8e1d05eec90e936eb08b257332c5e870"},
1587
+ {file = "sqlalchemy-2.0.40-py3-none-any.whl", hash = "sha256:32587e2e1e359276957e6fe5dad089758bc042a971a8a09ae8ecf7a8fe23d07a"},
1588
+ {file = "sqlalchemy-2.0.40.tar.gz", hash = "sha256:d827099289c64589418ebbcaead0145cd19f4e3e8a93919a0100247af245fa00"},
1589
+ ]
1590
+
1591
+ [package.dependencies]
1592
+ greenlet = {version = ">=1", markers = "python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"}
1593
+ typing-extensions = ">=4.6.0"
1594
+
1595
+ [package.extras]
1596
+ aiomysql = ["aiomysql (>=0.2.0)", "greenlet (>=1)"]
1597
+ aioodbc = ["aioodbc", "greenlet (>=1)"]
1598
+ aiosqlite = ["aiosqlite", "greenlet (>=1)", "typing_extensions (!=3.10.0.1)"]
1599
+ asyncio = ["greenlet (>=1)"]
1600
+ asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (>=1)"]
1601
+ mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10)"]
1602
+ mssql = ["pyodbc"]
1603
+ mssql-pymssql = ["pymssql"]
1604
+ mssql-pyodbc = ["pyodbc"]
1605
+ mypy = ["mypy (>=0.910)"]
1606
+ mysql = ["mysqlclient (>=1.4.0)"]
1607
+ mysql-connector = ["mysql-connector-python"]
1608
+ oracle = ["cx_oracle (>=8)"]
1609
+ oracle-oracledb = ["oracledb (>=1.0.1)"]
1610
+ postgresql = ["psycopg2 (>=2.7)"]
1611
+ postgresql-asyncpg = ["asyncpg", "greenlet (>=1)"]
1612
+ postgresql-pg8000 = ["pg8000 (>=1.29.1)"]
1613
+ postgresql-psycopg = ["psycopg (>=3.0.7)"]
1614
+ postgresql-psycopg2binary = ["psycopg2-binary"]
1615
+ postgresql-psycopg2cffi = ["psycopg2cffi"]
1616
+ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
1617
+ pymysql = ["pymysql"]
1618
+ sqlcipher = ["sqlcipher3_binary"]
1619
+
1620
  [[package]]
1621
  name = "starlette"
1622
  version = "0.46.1"
 
2020
  {file = "websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"},
2021
  ]
2022
 
2023
+ [[package]]
2024
+ name = "xxhash"
2025
+ version = "3.5.0"
2026
+ description = "Python binding for xxHash"
2027
+ optional = false
2028
+ python-versions = ">=3.7"
2029
+ groups = ["main"]
2030
+ files = [
2031
+ {file = "xxhash-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ece616532c499ee9afbb83078b1b952beffef121d989841f7f4b3dc5ac0fd212"},
2032
+ {file = "xxhash-3.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3171f693dbc2cef6477054a665dc255d996646b4023fe56cb4db80e26f4cc520"},
2033
+ {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c5d3e570ef46adaf93fc81b44aca6002b5a4d8ca11bd0580c07eac537f36680"},
2034
+ {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cb29a034301e2982df8b1fe6328a84f4b676106a13e9135a0d7e0c3e9f806da"},
2035
+ {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0d307d27099bb0cbeea7260eb39ed4fdb99c5542e21e94bb6fd29e49c57a23"},
2036
+ {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0342aafd421795d740e514bc9858ebddfc705a75a8c5046ac56d85fe97bf196"},
2037
+ {file = "xxhash-3.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dbbd9892c5ebffeca1ed620cf0ade13eb55a0d8c84e0751a6653adc6ac40d0c"},
2038
+ {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4cc2d67fdb4d057730c75a64c5923abfa17775ae234a71b0200346bfb0a7f482"},
2039
+ {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ec28adb204b759306a3d64358a5e5c07d7b1dd0ccbce04aa76cb9377b7b70296"},
2040
+ {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1328f6d8cca2b86acb14104e381225a3d7b42c92c4b86ceae814e5c400dbb415"},
2041
+ {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8d47ebd9f5d9607fd039c1fbf4994e3b071ea23eff42f4ecef246ab2b7334198"},
2042
+ {file = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b96d559e0fcddd3343c510a0fe2b127fbff16bf346dd76280b82292567523442"},
2043
+ {file = "xxhash-3.5.0-cp310-cp310-win32.whl", hash = "sha256:61c722ed8d49ac9bc26c7071eeaa1f6ff24053d553146d5df031802deffd03da"},
2044
+ {file = "xxhash-3.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:9bed5144c6923cc902cd14bb8963f2d5e034def4486ab0bbe1f58f03f042f9a9"},
2045
+ {file = "xxhash-3.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:893074d651cf25c1cc14e3bea4fceefd67f2921b1bb8e40fcfeba56820de80c6"},
2046
+ {file = "xxhash-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1"},
2047
+ {file = "xxhash-3.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8"},
2048
+ {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166"},
2049
+ {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7"},
2050
+ {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623"},
2051
+ {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a"},
2052
+ {file = "xxhash-3.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88"},
2053
+ {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c"},
2054
+ {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2"},
2055
+ {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084"},
2056
+ {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d"},
2057
+ {file = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839"},
2058
+ {file = "xxhash-3.5.0-cp311-cp311-win32.whl", hash = "sha256:109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da"},
2059
+ {file = "xxhash-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58"},
2060
+ {file = "xxhash-3.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3"},
2061
+ {file = "xxhash-3.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:14470ace8bd3b5d51318782cd94e6f94431974f16cb3b8dc15d52f3b69df8e00"},
2062
+ {file = "xxhash-3.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59aa1203de1cb96dbeab595ded0ad0c0056bb2245ae11fac11c0ceea861382b9"},
2063
+ {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08424f6648526076e28fae6ea2806c0a7d504b9ef05ae61d196d571e5c879c84"},
2064
+ {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61a1ff00674879725b194695e17f23d3248998b843eb5e933007ca743310f793"},
2065
+ {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f2c61bee5844d41c3eb015ac652a0229e901074951ae48581d58bfb2ba01be"},
2066
+ {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d32a592cac88d18cc09a89172e1c32d7f2a6e516c3dfde1b9adb90ab5df54a6"},
2067
+ {file = "xxhash-3.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70dabf941dede727cca579e8c205e61121afc9b28516752fd65724be1355cc90"},
2068
+ {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e5d0ddaca65ecca9c10dcf01730165fd858533d0be84c75c327487c37a906a27"},
2069
+ {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e5b5e16c5a480fe5f59f56c30abdeba09ffd75da8d13f6b9b6fd224d0b4d0a2"},
2070
+ {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149b7914451eb154b3dfaa721315117ea1dac2cc55a01bfbd4df7c68c5dd683d"},
2071
+ {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:eade977f5c96c677035ff39c56ac74d851b1cca7d607ab3d8f23c6b859379cab"},
2072
+ {file = "xxhash-3.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fa9f547bd98f5553d03160967866a71056a60960be00356a15ecc44efb40ba8e"},
2073
+ {file = "xxhash-3.5.0-cp312-cp312-win32.whl", hash = "sha256:f7b58d1fd3551b8c80a971199543379be1cee3d0d409e1f6d8b01c1a2eebf1f8"},
2074
+ {file = "xxhash-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:fa0cafd3a2af231b4e113fba24a65d7922af91aeb23774a8b78228e6cd785e3e"},
2075
+ {file = "xxhash-3.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:586886c7e89cb9828bcd8a5686b12e161368e0064d040e225e72607b43858ba2"},
2076
+ {file = "xxhash-3.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:37889a0d13b0b7d739cfc128b1c902f04e32de17b33d74b637ad42f1c55101f6"},
2077
+ {file = "xxhash-3.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:97a662338797c660178e682f3bc180277b9569a59abfb5925e8620fba00b9fc5"},
2078
+ {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f85e0108d51092bdda90672476c7d909c04ada6923c14ff9d913c4f7dc8a3bc"},
2079
+ {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2fd827b0ba763ac919440042302315c564fdb797294d86e8cdd4578e3bc7f3"},
2080
+ {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82085c2abec437abebf457c1d12fccb30cc8b3774a0814872511f0f0562c768c"},
2081
+ {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07fda5de378626e502b42b311b049848c2ef38784d0d67b6f30bb5008642f8eb"},
2082
+ {file = "xxhash-3.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c279f0d2b34ef15f922b77966640ade58b4ccdfef1c4d94b20f2a364617a493f"},
2083
+ {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:89e66ceed67b213dec5a773e2f7a9e8c58f64daeb38c7859d8815d2c89f39ad7"},
2084
+ {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bcd51708a633410737111e998ceb3b45d3dbc98c0931f743d9bb0a209033a326"},
2085
+ {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ff2c0a34eae7df88c868be53a8dd56fbdf592109e21d4bfa092a27b0bf4a7bf"},
2086
+ {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e28503dccc7d32e0b9817aa0cbfc1f45f563b2c995b7a66c4c8a0d232e840c7"},
2087
+ {file = "xxhash-3.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a6c50017518329ed65a9e4829154626f008916d36295b6a3ba336e2458824c8c"},
2088
+ {file = "xxhash-3.5.0-cp313-cp313-win32.whl", hash = "sha256:53a068fe70301ec30d868ece566ac90d873e3bb059cf83c32e76012c889b8637"},
2089
+ {file = "xxhash-3.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:80babcc30e7a1a484eab952d76a4f4673ff601f54d5142c26826502740e70b43"},
2090
+ {file = "xxhash-3.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:4811336f1ce11cac89dcbd18f3a25c527c16311709a89313c3acaf771def2d4b"},
2091
+ {file = "xxhash-3.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6e5f70f6dca1d3b09bccb7daf4e087075ff776e3da9ac870f86ca316736bb4aa"},
2092
+ {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e76e83efc7b443052dd1e585a76201e40b3411fe3da7af4fe434ec51b2f163b"},
2093
+ {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33eac61d0796ca0591f94548dcfe37bb193671e0c9bcf065789b5792f2eda644"},
2094
+ {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ec70a89be933ea49222fafc3999987d7899fc676f688dd12252509434636622"},
2095
+ {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86b8e7f703ec6ff4f351cfdb9f428955859537125904aa8c963604f2e9d3e7"},
2096
+ {file = "xxhash-3.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0adfbd36003d9f86c8c97110039f7539b379f28656a04097e7434d3eaf9aa131"},
2097
+ {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:63107013578c8a730419adc05608756c3fa640bdc6abe806c3123a49fb829f43"},
2098
+ {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:683b94dbd1ca67557850b86423318a2e323511648f9f3f7b1840408a02b9a48c"},
2099
+ {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:5d2a01dcce81789cf4b12d478b5464632204f4c834dc2d064902ee27d2d1f0ee"},
2100
+ {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:a9d360a792cbcce2fe7b66b8d51274ec297c53cbc423401480e53b26161a290d"},
2101
+ {file = "xxhash-3.5.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:f0b48edbebea1b7421a9c687c304f7b44d0677c46498a046079d445454504737"},
2102
+ {file = "xxhash-3.5.0-cp37-cp37m-win32.whl", hash = "sha256:7ccb800c9418e438b44b060a32adeb8393764da7441eb52aa2aa195448935306"},
2103
+ {file = "xxhash-3.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c3bc7bf8cb8806f8d1c9bf149c18708cb1c406520097d6b0a73977460ea03602"},
2104
+ {file = "xxhash-3.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:74752ecaa544657d88b1d1c94ae68031e364a4d47005a90288f3bab3da3c970f"},
2105
+ {file = "xxhash-3.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dee1316133c9b463aa81aca676bc506d3f80d8f65aeb0bba2b78d0b30c51d7bd"},
2106
+ {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:602d339548d35a8579c6b013339fb34aee2df9b4e105f985443d2860e4d7ffaa"},
2107
+ {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:695735deeddfb35da1677dbc16a083445360e37ff46d8ac5c6fcd64917ff9ade"},
2108
+ {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1030a39ba01b0c519b1a82f80e8802630d16ab95dc3f2b2386a0b5c8ed5cbb10"},
2109
+ {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5bc08f33c4966f4eb6590d6ff3ceae76151ad744576b5fc6c4ba8edd459fdec"},
2110
+ {file = "xxhash-3.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:160e0c19ee500482ddfb5d5570a0415f565d8ae2b3fd69c5dcfce8a58107b1c3"},
2111
+ {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f1abffa122452481a61c3551ab3c89d72238e279e517705b8b03847b1d93d738"},
2112
+ {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d5e9db7ef3ecbfc0b4733579cea45713a76852b002cf605420b12ef3ef1ec148"},
2113
+ {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:23241ff6423378a731d84864bf923a41649dc67b144debd1077f02e6249a0d54"},
2114
+ {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:82b833d5563fefd6fceafb1aed2f3f3ebe19f84760fdd289f8b926731c2e6e91"},
2115
+ {file = "xxhash-3.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a80ad0ffd78bef9509eee27b4a29e56f5414b87fb01a888353e3d5bda7038bd"},
2116
+ {file = "xxhash-3.5.0-cp38-cp38-win32.whl", hash = "sha256:50ac2184ffb1b999e11e27c7e3e70cc1139047e7ebc1aa95ed12f4269abe98d4"},
2117
+ {file = "xxhash-3.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:392f52ebbb932db566973693de48f15ce787cabd15cf6334e855ed22ea0be5b3"},
2118
+ {file = "xxhash-3.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bfc8cdd7f33d57f0468b0614ae634cc38ab9202c6957a60e31d285a71ebe0301"},
2119
+ {file = "xxhash-3.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e0c48b6300cd0b0106bf49169c3e0536408dfbeb1ccb53180068a18b03c662ab"},
2120
+ {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe1a92cfbaa0a1253e339ccec42dbe6db262615e52df591b68726ab10338003f"},
2121
+ {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33513d6cc3ed3b559134fb307aae9bdd94d7e7c02907b37896a6c45ff9ce51bd"},
2122
+ {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eefc37f6138f522e771ac6db71a6d4838ec7933939676f3753eafd7d3f4c40bc"},
2123
+ {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a606c8070ada8aa2a88e181773fa1ef17ba65ce5dd168b9d08038e2a61b33754"},
2124
+ {file = "xxhash-3.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42eca420c8fa072cc1dd62597635d140e78e384a79bb4944f825fbef8bfeeef6"},
2125
+ {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:604253b2143e13218ff1ef0b59ce67f18b8bd1c4205d2ffda22b09b426386898"},
2126
+ {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6e93a5ad22f434d7876665444a97e713a8f60b5b1a3521e8df11b98309bff833"},
2127
+ {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7a46e1d6d2817ba8024de44c4fd79913a90e5f7265434cef97026215b7d30df6"},
2128
+ {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:30eb2efe6503c379b7ab99c81ba4a779748e3830241f032ab46bd182bf5873af"},
2129
+ {file = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c8aa771ff2c13dd9cda8166d685d7333d389fae30a4d2bb39d63ab5775de8606"},
2130
+ {file = "xxhash-3.5.0-cp39-cp39-win32.whl", hash = "sha256:5ed9ebc46f24cf91034544b26b131241b699edbfc99ec5e7f8f3d02d6eb7fba4"},
2131
+ {file = "xxhash-3.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:220f3f896c6b8d0316f63f16c077d52c412619e475f9372333474ee15133a558"},
2132
+ {file = "xxhash-3.5.0-cp39-cp39-win_arm64.whl", hash = "sha256:a7b1d8315d9b5e9f89eb2933b73afae6ec9597a258d52190944437158b49d38e"},
2133
+ {file = "xxhash-3.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2014c5b3ff15e64feecb6b713af12093f75b7926049e26a580e94dcad3c73d8c"},
2134
+ {file = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fab81ef75003eda96239a23eda4e4543cedc22e34c373edcaf744e721a163986"},
2135
+ {file = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2febf914ace002132aa09169cc572e0d8959d0f305f93d5828c4836f9bc5a6"},
2136
+ {file = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5d3a10609c51da2a1c0ea0293fc3968ca0a18bd73838455b5bca3069d7f8e32b"},
2137
+ {file = "xxhash-3.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a74f23335b9689b66eb6dbe2a931a88fcd7a4c2cc4b1cb0edba8ce381c7a1da"},
2138
+ {file = "xxhash-3.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2b4154c00eb22e4d543f472cfca430e7962a0f1d0f3778334f2e08a7ba59363c"},
2139
+ {file = "xxhash-3.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d30bbc1644f726b825b3278764240f449d75f1a8bdda892e641d4a688b1494ae"},
2140
+ {file = "xxhash-3.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fa0b72f2423e2aa53077e54a61c28e181d23effeaafd73fcb9c494e60930c8e"},
2141
+ {file = "xxhash-3.5.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13de2b76c1835399b2e419a296d5b38dc4855385d9e96916299170085ef72f57"},
2142
+ {file = "xxhash-3.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:0691bfcc4f9c656bcb96cc5db94b4d75980b9d5589f2e59de790091028580837"},
2143
+ {file = "xxhash-3.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:297595fe6138d4da2c8ce9e72a04d73e58725bb60f3a19048bc96ab2ff31c692"},
2144
+ {file = "xxhash-3.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc1276d369452040cbb943300dc8abeedab14245ea44056a2943183822513a18"},
2145
+ {file = "xxhash-3.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2061188a1ba352fc699c82bff722f4baacb4b4b8b2f0c745d2001e56d0dfb514"},
2146
+ {file = "xxhash-3.5.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38c384c434021e4f62b8d9ba0bc9467e14d394893077e2c66d826243025e1f81"},
2147
+ {file = "xxhash-3.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e6a4dd644d72ab316b580a1c120b375890e4c52ec392d4aef3c63361ec4d77d1"},
2148
+ {file = "xxhash-3.5.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:531af8845aaadcadf951b7e0c1345c6b9c68a990eeb74ff9acd8501a0ad6a1c9"},
2149
+ {file = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ce379bcaa9fcc00f19affa7773084dd09f5b59947b3fb47a1ceb0179f91aaa1"},
2150
+ {file = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd1b2281d01723f076df3c8188f43f2472248a6b63118b036e641243656b1b0f"},
2151
+ {file = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c770750cc80e8694492244bca7251385188bc5597b6a39d98a9f30e8da984e0"},
2152
+ {file = "xxhash-3.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b150b8467852e1bd844387459aa6fbe11d7f38b56e901f9f3b3e6aba0d660240"},
2153
+ {file = "xxhash-3.5.0.tar.gz", hash = "sha256:84f2caddf951c9cbf8dc2e22a89d4ccf5d86391ac6418fe81e3c67d0cf60b45f"},
2154
+ ]
2155
+
2156
  [[package]]
2157
  name = "zep-cloud"
2158
  version = "2.12.1"
 
2286
  [metadata]
2287
  lock-version = "2.1"
2288
  python-versions = "^3.12"
2289
+ content-hash = "ecf9a8b4cd13afeac7a43e99a62dae386c72cc2656e8c7c2e9bced60e3983757"
api/prompts/__init__.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.prompts import (
2
+ ChatPromptTemplate,
3
+ HumanMessagePromptTemplate,
4
+ MessagesPlaceholder,
5
+ SystemMessagePromptTemplate,
6
+ MessagesPlaceholder,
7
+ )
8
+ from langchain_core.messages import (
9
+ BaseMessage,
10
+ FunctionMessage,
11
+ HumanMessage,
12
+ SystemMessage,
13
+ ToolMessage,
14
+ AIMessage,
15
+ )
16
+
17
+ from .system_prompts import casual_fan_prompt, super_fan_prompt
18
+
19
+ casual_fan_prompt = ChatPromptTemplate.from_messages([
20
+ SystemMessagePromptTemplate.from_template(casual_fan_prompt),
21
+ MessagesPlaceholder("input")
22
+ ])
23
+
24
+ super_fan_prompt = ChatPromptTemplate.from_messages([
25
+ SystemMessagePromptTemplate.from_template(super_fan_prompt),
26
+ MessagesPlaceholder("input")
27
+ ])
api/prompts/system_prompts.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ casual_fan_prompt = """
3
+ Current date: {now}
4
+ PERSONA DIRECTIVE: CASUAL FAN MODE — SOCCER / HUGE LEAGUE
5
+
6
+ You are speaking to a casual soccer fan of Huge League. You MUST:
7
+ 1. Keep explanations BRIEF (3-4 sentences max)
8
+ 2. Use EVERYDAY LANGUAGE, avoid technical soccer jargon
9
+ 3. EMPHASIZE exciting plays, goals, and star players
10
+ 4. FOCUS on "big moments" and "highlight-reel" goals
11
+ 5. AVOID deep tactics or technical analysis
12
+ 6. CREATE a sense of belonging using "we" and "our team"
13
+ 7. INCLUDE at least one exclamation point in longer responses for excitement!
14
+
15
+ Casual soccer fans don't care about: formations, advanced tactics, or contract details.
16
+ Casual soccer fans DO care about: goals, stars, rivalries, and feeling part of the action.
17
+
18
+ ABOUT HUGE LEAGUE:
19
+ - International soccer league, 23-player squads, 4-3-3 base formation.
20
+ - Teams:
21
+ • Yucatán Force (Mérida, Mexico): Mayan pride, fortress stadium "El Templo del Sol".
22
+ • Tierra Alta FC (San José, Costa Rica): Highlanders, eco-friendly, smart play.
23
+ • Everglade FC (Miami, USA): Flashy, wild, South Florida flair.
24
+ • Fraser Valley United (Abbotsford, Canada): Vineyard roots, top youth academy.
25
+
26
+ EXAMPLE RESPONSE FOR CASUAL FAN (about the draft):
27
+ "Everglade FC did a great job picking up some exciting young players! There's a speedy winger who could score some highlight-reel goals for us next season. The team focused on adding instant impact, which is just what we needed!"
28
+
29
+ <CONTEXT>{zep_context}</CONTEXT>
30
+
31
+ """
32
+
33
+
34
+ super_fan_prompt = """
35
+ Current date: {now}
36
+ PERSONA DIRECTIVE: SUPER FAN MODE — SOCCER / HUGE LEAGUE
37
+
38
+ You MUST speak to a die-hard Huge League soccer super fan with deep knowledge. You MUST:
39
+ 1. Provide DETAILED analysis beyond surface-level info
40
+ 2. Use SPECIFIC soccer terminology and tactical concepts
41
+ 3. REFERENCE role players and their contributions, not just stars
42
+ 4. ANALYZE strategic elements of matches, transfers, and team building
43
+ 5. COMPARE current scenarios to club and league history
44
+ 6. INCLUDE stats, metrics, or technical details in your analysis
45
+ 7. ACKNOWLEDGE the complexity of soccer decisions; avoid oversimplifying
46
+
47
+ Super fans expect: tactical breakdowns, transfer/contract details, advanced stats, and historical context.
48
+ Super fans value: strategic insights, player development, and recognition of unsung contributors.
49
+
50
+ ABOUT HUGE LEAGUE:
51
+ - International soccer league, 23-player squads, 4-3-3 base formation.
52
+ - Teams:
53
+ • Yucatán Force (Mérida, Mexico): Mayan pride, fortress stadium "El Templo del Sol".
54
+ • Tierra Alta FC (San José, Costa Rica): Highlanders, eco-friendly, smart play.
55
+ • Everglade FC (Miami, USA): Flashy, wild, South Florida flair.
56
+ • Fraser Valley United (Abbotsford, Canada): Vineyard roots, top youth academy.
57
+
58
+ EXAMPLE RESPONSE FOR SUPER FAN (about the draft):
59
+ "Everglade FC's draft was a masterclass in squad optimization. By targeting a left-footed winger with high xG/90 from open play, they add width and unpredictability to their 4-3-3. Their emphasis on youth aligns with the club's recent pivot toward academy integration, mirroring Fraser Valley United's model. The only concern is squad depth at fullback, but the technical staff seems to be betting on positional flexibility and internal development."
60
+
61
+ <CONTEXT>{zep_context}</CONTEXT>
62
+
63
+ """
api/pyproject.toml CHANGED
@@ -20,6 +20,9 @@ langchain-core = "^0.3.59"
20
  python-slugify = "^8.0.4"
21
  numpy = "^2.2.5"
22
  zep-cloud = "^2.12.1"
 
 
 
23
 
24
  [tool.poetry.group.dev.dependencies]
25
  pytest = "^7.4.0"
 
20
  python-slugify = "^8.0.4"
21
  numpy = "^2.2.5"
22
  zep-cloud = "^2.12.1"
23
+ colorama = "^0.4.6"
24
+ langchain = "^0.3.25"
25
+ langgraph = "^0.4.3"
26
 
27
  [tool.poetry.group.dev.dependencies]
28
  pytest = "^7.4.0"
api/scripts/temp.py ADDED
File without changes
api/scripts/vectorstore_search.py CHANGED
@@ -8,8 +8,13 @@ vector_store = InMemoryVectorStore.load("/code/data/vectorstore.json", embedding
8
 
9
  # query = "ryan brown"
10
  # query = "defensive midfielder"
11
- query = "goaly"
12
  results = vector_store.similarity_search(query, k=3)
 
 
 
 
 
13
 
14
  for result in results:
15
  pprint(result.page_content)
 
8
 
9
  # query = "ryan brown"
10
  # query = "defensive midfielder"
11
+ query = "* FC Everglade"
12
  results = vector_store.similarity_search(query, k=3)
13
+ results = vector_store.similarity_search(
14
+ query,
15
+ k=3,
16
+ filter=lambda doc: doc.metadata.get("type") == "player",
17
+ )
18
 
19
  for result in results:
20
  pprint(result.page_content)
api/scripts/workflow_playground.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from workflows.base import build_workflow_with_state
3
+ from event_handlers import PrintEventHandler
4
+ from langchain_core.messages import HumanMessage
5
+
6
+ from prompts import (
7
+ casual_fan_prompt,
8
+ HumanMessage,
9
+ AIMessage,
10
+ )
11
+
12
+
13
+ workflow, state = build_workflow_with_state(
14
+ handler=PrintEventHandler(),
15
+ session_id='5aed14ff09fb415ba77439409f458909',
16
+ messages=[
17
+ HumanMessage(content="tell me about some players in everglade fc"),
18
+ ],
19
+ )
20
+
21
+ async def main():
22
+ await workflow.ainvoke(state)
23
+
24
+ if __name__ == "__main__":
25
+ asyncio.run(main())
api/scripts/zep_playground.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uuid
3
+ import datetime
4
+ from zep_cloud.client import Zep
5
+ from zep_cloud.types import Message
6
+ from langchain.chat_models import init_chat_model
7
+ import colorama
8
+ from colorama import Fore, Style
9
+ from pprint import pprint, pformat
10
+
11
+ from prompts import (
12
+ casual_fan_prompt,
13
+ HumanMessage,
14
+ AIMessage,
15
+ )
16
+ from tools import (
17
+ PlayerSearchTool,
18
+ GameSearchTool,
19
+ )
20
+
21
+ API_KEY = os.environ.get('ZEP_API_KEY')
22
+
23
+ client = Zep(
24
+ api_key=API_KEY,
25
+ )
26
+ model = init_chat_model("gpt-4o-mini", model_provider="openai")
27
+ available_tools = [
28
+ PlayerSearchTool(),
29
+ GameSearchTool(),
30
+ ]
31
+
32
+
33
+ def create_user(email, first_name, last_name):
34
+ # Create a new user
35
+ new_user = client.user.add(
36
+ user_id=email,
37
+ email=email,
38
+ first_name=first_name,
39
+ last_name=last_name,
40
+ )
41
+ return new_user
42
+
43
+
44
+ def create_session(user_id):
45
+ # Generate a unique session ID
46
+ session_id = uuid.uuid4().hex
47
+ # Create a new session for the user
48
+ client.memory.add_session(
49
+ session_id=session_id,
50
+ user_id=user_id,
51
+ )
52
+ return session_id
53
+
54
+
55
+ def add_fact(user_id, fact):
56
+ new_episode = client.graph.add(
57
+ user_id=user_id,
58
+ type="text",
59
+ data=fact,
60
+ )
61
+ return new_episode
62
+
63
+
64
+ history = []
65
+ def send_message(session_id, message):
66
+ global history
67
+ history.append(HumanMessage(content=message))
68
+ # always cap history at last 6 messages
69
+ history = history[-6:]
70
+
71
+ memory = client.memory.get(session_id=session_id)
72
+ print(Fore.LIGHTBLACK_EX + "\nMemory retrieved." + Style.RESET_ALL)
73
+ # print(Fore.YELLOW + pformat(memory.context, compact=False, width=120) + "\n" + Style.RESET_ALL)
74
+
75
+ prompt = casual_fan_prompt.format(
76
+ zep_context=memory.context,
77
+ input=history,
78
+ now=datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d'),
79
+ )
80
+
81
+ print(Fore.YELLOW + pformat(prompt, compact=False, width=120) + "\n" + Style.RESET_ALL)
82
+
83
+ chunks = []
84
+ for chunk in model.stream(prompt, tools=available_tools):
85
+ chunks.append(chunk)
86
+ print(Fore.GREEN + chunk.content + Style.RESET_ALL, end="", flush=True)
87
+
88
+ messages = [
89
+ Message(
90
+ role="user",
91
+ content=message,
92
+ role_type="user",
93
+ ),
94
+ Message(
95
+ role="assistant",
96
+ content="".join([chunk.content for chunk in chunks]),
97
+ role_type="assistant",
98
+ ),
99
+ ]
100
+ client.memory.add(session_id=session_id, messages=messages)
101
+ print(Fore.LIGHTBLACK_EX + "\nMemory updated." + Style.RESET_ALL)
102
+
103
+ history.append(
104
+ AIMessage(content="".join([chunk.content for chunk in chunks]))
105
+ )
106
+
107
+ return chunks
108
+
109
+
110
+ user_id = '[email protected]'
111
+ # session_id = 'f0bfaa5b4b11486391e1c52bcebe0ad3' # blue sky
112
+ # session_id = '9f0a03443fa44eb9a1e9967ad2ab137a'
113
+ session_id = '5aed14ff09fb415ba77439409f458909'
114
+
115
+ # user = client.user.get(user_id)
116
+ # memory = client.memory.get(session_id=session_id)
117
+ # print(memory)
118
+
119
+
120
+ # if __name__ == "__main__":
121
+ # """
122
+ # Simple REPL loop for sending messages to the LLM.
123
+ # Prompts with '>', sends input to send_message, and prints response in green.
124
+ # Type 'exit' or press Ctrl+C to quit.
125
+ # """
126
+ # colorama.init(autoreset=True)
127
+
128
+ # print("\nType 'exit' or press Ctrl+C to quit.\n")
129
+ # try:
130
+ # while True:
131
+ # user_input = input("> ")
132
+ # if user_input.strip().lower() == "exit":
133
+ # print("Exiting.")
134
+ # break
135
+ # # Call send_message and print LLM response in green
136
+ # chunks = send_message(session_id, user_input)
137
+ # print("") # Newline after response
138
+ # except KeyboardInterrupt:
139
+ # print("\nExiting.")
140
+
141
+
142
+ # from prompts import (
143
+ # casual_fan_prompt,
144
+ # HumanMessage,
145
+ # AIMessage,
146
+ # )
147
+
148
+
149
+
150
+ memory = client.memory.get(session_id=session_id)
151
+
152
+ history = [
153
+ HumanMessage(content="tell me about some players in everglade fc"),
154
+ # AIMessage(content="soccer is the best sport ever"),
155
+ ]
156
+
157
+ prompt = casual_fan_prompt.format(
158
+ zep_context=memory.context,
159
+ input=history,
160
+ now=datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d'),
161
+ )
162
+
163
+ print(prompt)
api/tools/__init__.py CHANGED
@@ -1,5 +1,7 @@
1
  from .player_search import PlayerSearchTool
 
2
 
3
  __all__ = [
4
  "PlayerSearchTool",
 
5
  ]
 
1
  from .player_search import PlayerSearchTool
2
+ from .game_search import GameSearchTool
3
 
4
  __all__ = [
5
  "PlayerSearchTool",
6
+ "GameSearchTool",
7
  ]
api/tools/game_search.py CHANGED
@@ -1,8 +1,11 @@
1
  from langchain_core.tools import BaseTool
2
  from pydantic import BaseModel, Field
3
  from langchain_core.documents import Document
4
- from typing import Type, List
5
-
 
 
 
6
  from data.vectorstore_singleton import get_vector_store
7
 
8
  vector_store = get_vector_store()
@@ -23,9 +26,11 @@ class GameSearchTool(BaseTool):
23
  name: str = "game_search"
24
  description: str = "Search for games in the vector store"
25
  args_schema: Type[BaseModel] = GameSearchSchema
26
- description: str = ""
27
-
28
- def _run(self, query: str) -> List[Document]:
 
 
29
  result = vector_store.similarity_search(
30
  "",
31
  k=20,
@@ -33,7 +38,10 @@ class GameSearchTool(BaseTool):
33
  )
34
  return sorted(result, key=lambda doc: int(doc.id.split("_")[-1]))
35
 
36
- async def _arun(self, query: str) -> List[Document]:
 
 
 
37
  result = await vector_store.asimilarity_search(
38
  "",
39
  k=20,
 
1
  from langchain_core.tools import BaseTool
2
  from pydantic import BaseModel, Field
3
  from langchain_core.documents import Document
4
+ from typing import Type, List, Optional
5
+ from langchain.callbacks.manager import (
6
+ AsyncCallbackManagerForToolRun,
7
+ CallbackManagerForToolRun,
8
+ )
9
  from data.vectorstore_singleton import get_vector_store
10
 
11
  vector_store = get_vector_store()
 
26
  name: str = "game_search"
27
  description: str = "Search for games in the vector store"
28
  args_schema: Type[BaseModel] = GameSearchSchema
29
+
30
+ def _run(self,
31
+ query: str,
32
+ run_manager: Optional[CallbackManagerForToolRun] = None,
33
+ ) -> List[Document]:
34
  result = vector_store.similarity_search(
35
  "",
36
  k=20,
 
38
  )
39
  return sorted(result, key=lambda doc: int(doc.id.split("_")[-1]))
40
 
41
+ async def _arun(self,
42
+ query: str,
43
+ run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
44
+ ) -> List[Document]:
45
  result = await vector_store.asimilarity_search(
46
  "",
47
  k=20,
api/tools/player_search.py CHANGED
@@ -1,33 +1,55 @@
1
- from langchain_core.tools import BaseTool
2
  from pydantic import BaseModel, Field
 
3
  from langchain_core.documents import Document
4
- from typing import Type, List
5
-
 
 
 
6
  from data.vectorstore_singleton import get_vector_store
7
 
8
  vector_store = get_vector_store()
9
 
10
 
11
  class PlayerSearchSchema(BaseModel):
12
- query: str = Field(description="The search query to identify a player. Examples: 'Deebo Samuel', '49ers QB', 'Number 19 on the 49ers'")
 
 
 
 
 
 
 
 
 
13
 
14
 
15
  class PlayerSearchTool(BaseTool):
16
  name: str = "player_search"
17
- description: str = "Search for players in the vector store"
18
  args_schema: Type[BaseModel] = PlayerSearchSchema
19
- description: str = "Search for players in the vector store based on their name, position, or other identifying information. Returns a list of documents with player details, stats, headshots, social media links, etc."
 
 
 
20
 
21
- def _run(self, query: str) -> List[Document]:
 
 
 
 
22
  return vector_store.similarity_search(
23
  query,
24
- k=3,
25
- filter={"type": "player"},
26
  )
27
 
28
- async def _arun(self, query: str) -> List[Document]:
29
- return vector_store.asimilarity_search(
 
 
 
 
30
  query,
31
- k=3,
32
- filter={"type": "player"},
33
  )
 
 
1
  from pydantic import BaseModel, Field
2
+ from langchain.tools import BaseTool, StructuredTool, tool
3
  from langchain_core.documents import Document
4
+ from typing import Type, List, Optional
5
+ from langchain.callbacks.manager import (
6
+ AsyncCallbackManagerForToolRun,
7
+ CallbackManagerForToolRun,
8
+ )
9
  from data.vectorstore_singleton import get_vector_store
10
 
11
  vector_store = get_vector_store()
12
 
13
 
14
  class PlayerSearchSchema(BaseModel):
15
+ query: str = Field(description=(
16
+ "The search query to identify a soccer player in the fictional league. "
17
+ "You can search by player name, position, or use team and number (e.g., 'Number 10 on Everglade FC'). "
18
+ "To get random players from a team, send an asterisk '*' as the query (e.g., '* Everglade FC'). "
19
+ "Available teams:\n"
20
+ " • Yucatán Force (Mérida, Mexico): Mayan pride, fortress stadium 'El Templo del Sol'.\n"
21
+ " • Tierra Alta FC (San José, Costa Rica): Highlanders, eco-friendly, smart play.\n"
22
+ " • Everglade FC (Miami, USA): Flashy, wild, South Florida flair.\n"
23
+ " • Fraser Valley United (Abbotsford, Canada): Vineyard roots, top youth academy."
24
+ ))
25
 
26
 
27
  class PlayerSearchTool(BaseTool):
28
  name: str = "player_search"
 
29
  args_schema: Type[BaseModel] = PlayerSearchSchema
30
+ description: str = (
31
+ "Search for soccer players in the fictional league based on their name, position, or other identifying information. "
32
+ "Returns a list of documents with player details, stats, headshots, social media links, etc. "
33
+ )
34
 
35
+ def _run(self,
36
+ query: str,
37
+ run_manager: Optional[CallbackManagerForToolRun] = None,
38
+ ) -> List[Document]:
39
+ k = 5 if query[0] == "*" else 3
40
  return vector_store.similarity_search(
41
  query,
42
+ k=k,
43
+ filter=lambda doc: doc.metadata.get("type") == "player",
44
  )
45
 
46
+ async def _arun(self,
47
+ query: str,
48
+ run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
49
+ ) -> List[Document]:
50
+ k = 5 if query[0] == "*" else 3
51
+ return await vector_store.asimilarity_search(
52
  query,
53
+ k=k,
54
+ filter=lambda doc: doc.metadata.get("type") == "player",
55
  )
api/tools/team_search.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # TODO: returns news; in this case recaps of the semi-final games
api/utils/__init__.py ADDED
File without changes
api/utils/zep_helpers.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from functools import lru_cache
2
+ from langchain_core.messages import BaseMessage
3
+ from zep_cloud.client import AsyncZep
4
+ from zep_cloud.types import Message
5
+
6
+
7
+ @lru_cache(maxsize=1)
8
+ def get_zep_client():
9
+ return AsyncZep()
10
+
11
+
12
+ async def record_session(session_id: str, messages: list[BaseMessage]):
13
+ if len(messages) >= 2:
14
+ user_message = messages[0]
15
+ assistant_message = messages[-1]
16
+ messages = [
17
+ Message(
18
+ role="user",
19
+ content=user_message.content,
20
+ role_type="user",
21
+ ),
22
+ Message(
23
+ role="assistant",
24
+ content=assistant_message.content,
25
+ role_type="assistant",
26
+ ),
27
+ ]
28
+ zep_client = get_zep_client()
29
+ await zep_client.memory.add(session_id=session_id, messages=messages)
30
+
api/workflows/__init__.py ADDED
File without changes
api/workflows/base.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import datetime
3
+ import operator
4
+ from functools import partial
5
+ from typing import TypedDict, Annotated, Sequence
6
+ from langchain_openai import ChatOpenAI
7
+ from langchain_core.messages import (
8
+ BaseMessage,
9
+ AIMessage,
10
+ FunctionMessage,
11
+ HumanMessage,
12
+ SystemMessage,
13
+ ToolMessage,
14
+ )
15
+ from langgraph.graph import StateGraph, END
16
+ from langchain_core.callbacks import AsyncCallbackHandler
17
+ from langgraph.prebuilt import ToolNode
18
+
19
+
20
+ from utils.zep_helpers import (
21
+ get_zep_client,
22
+ record_session,
23
+ )
24
+ from prompts import (
25
+ casual_fan_prompt,
26
+ )
27
+ from tools import (
28
+ PlayerSearchTool,
29
+ GameSearchTool,
30
+ )
31
+
32
+
33
+ available_tools = [
34
+ GameSearchTool(),
35
+ PlayerSearchTool(),
36
+ ]
37
+ tool_node = ToolNode(available_tools)
38
+
39
+ llm = ChatOpenAI(model="gpt-4o-mini")
40
+ llm_with_tools = llm.bind_tools(tools=available_tools)
41
+
42
+ zep_client = get_zep_client()
43
+
44
+
45
+ class AgentState(TypedDict):
46
+ session_id: str
47
+ messages: Annotated[Sequence[BaseMessage], operator.add]
48
+
49
+
50
+ async def call_model(state: AgentState, handler: AsyncCallbackHandler) -> dict:
51
+ session_id = state["session_id"]
52
+ memory = await zep_client.memory.get(session_id=session_id)
53
+ messages = state["messages"]
54
+
55
+ prompt = casual_fan_prompt.format(
56
+ zep_context=memory.context,
57
+ input=messages,
58
+ now=datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d'),
59
+ )
60
+
61
+ # response = await llm_with_tools.ainvoke(prompt, stream=True,
62
+ # config={"callbacks" :[handler]})
63
+ response = await llm_with_tools.with_config(callbacks=[handler]).ainvoke(prompt, stream=True)
64
+
65
+ return {'messages': [response]}
66
+
67
+
68
+ async def call_tool(state: AgentState, handler: AsyncCallbackHandler) -> dict:
69
+ messages = state["messages"]
70
+ last_message = messages[-1]
71
+ tools_by_name = {tool.name: tool for tool in available_tools}
72
+
73
+ observations = []
74
+ for tool_call in last_message.tool_calls:
75
+ tool = tools_by_name[tool_call["name"]]
76
+ observations.append(
77
+ tool.with_config(callbacks=[handler]).ainvoke(tool_call["args"])
78
+ )
79
+
80
+ # await all observations
81
+ observations = await asyncio.gather(*observations)
82
+
83
+ results = []
84
+ for observation, tool_call in zip(observations, last_message.tool_calls):
85
+ results.append(ToolMessage(content=observation, tool_call_id=tool_call["id"]))
86
+ return {"messages": results}
87
+
88
+
89
+ async def should_continue(state):
90
+ messages = state["messages"]
91
+ last_message = messages[-1]
92
+ if 'tool_calls' not in last_message.additional_kwargs:
93
+ # inform zep of final response
94
+ await record_session(state["session_id"], messages)
95
+ return 'end'
96
+ return 'continue'
97
+
98
+
99
+ def build_workflow(handler: AsyncCallbackHandler):
100
+ workflow = StateGraph(AgentState)
101
+ workflow.add_node('agent', partial(call_model, handler=handler))
102
+ workflow.add_node('tools', partial(call_tool, handler=handler))
103
+ workflow.set_entry_point('agent')
104
+
105
+ workflow.add_conditional_edges(
106
+ 'agent',
107
+ should_continue,
108
+ {
109
+ 'continue': 'tools',
110
+ 'end': END,
111
+ }
112
+ )
113
+
114
+ workflow.add_edge('tools', 'agent')
115
+
116
+ return workflow.compile()
117
+
118
+
119
+ def build_workflow_with_state(handler: AsyncCallbackHandler, session_id: str, messages=None):
120
+ """
121
+ Utility to build workflow and initial state in one step.
122
+ Args:
123
+ handler: AsyncCallbackHandler for this workflow
124
+ session_id: unique session identifier
125
+ messages: optional initial message list
126
+ Returns:
127
+ (workflow, state) tuple ready for execution
128
+ """
129
+ workflow = build_workflow(handler)
130
+ state = {
131
+ "session_id": session_id,
132
+ "messages": messages or [],
133
+ }
134
+ return workflow, state