@langwatch/mcp-server 0.7.0 → 0.9.0

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 (256) hide show
  1. package/.release-please-shim +1 -0
  2. package/CHANGELOG.md +87 -0
  3. package/LICENSE +7 -0
  4. package/dist/archive-project-HZBRPR2S.js +19 -0
  5. package/dist/{archive-scenario-WJ2A7ETN.js → archive-scenario-P5RRITRM.js} +4 -4
  6. package/dist/{archive-suite-4JOM4SSL.js → archive-suite-NUUFD2EM.js} +4 -4
  7. package/dist/{assign-prompt-tag-GL7EAAF3.js → assign-prompt-tag-FKCCZPML.js} +3 -3
  8. package/dist/{chunk-2WPLXEKF.js → chunk-42ZHHHIJ.js} +20 -5
  9. package/dist/chunk-ADSJ2FDA.js +44 -0
  10. package/dist/{chunk-IE4M5OGE.js → chunk-BB7EOKHR.js} +2 -2
  11. package/dist/chunk-BBJ5WAJB.js +24 -0
  12. package/dist/{chunk-EGH5RPXM.js → chunk-BYWYM2RP.js} +2 -2
  13. package/dist/{chunk-2GT7IFWK.js → chunk-CCM4ZFGF.js} +2 -2
  14. package/dist/{chunk-LUMEZEHL.js → chunk-CHKCEZBP.js} +2 -2
  15. package/dist/{chunk-ZVS4UKN2.js → chunk-HKY3GW45.js} +2 -2
  16. package/dist/{chunk-EUQDVOSU.js → chunk-JHOSVOHT.js} +2 -2
  17. package/dist/{chunk-E5JYYU3J.js → chunk-JVLJKQJG.js} +669 -94
  18. package/dist/{chunk-BWWY5KEF.js → chunk-KOO5733S.js} +3 -2
  19. package/dist/{chunk-HYMIWO3U.js → chunk-R7C7OUVG.js} +2 -2
  20. package/dist/{chunk-WQG2DFHX.js → chunk-TROIWSEQ.js} +2 -2
  21. package/dist/{chunk-CCWCIJJ3.js → chunk-X2SEURT2.js} +2 -2
  22. package/dist/{chunk-4AUB2BIA.js → chunk-XC62KJIT.js} +3 -3
  23. package/dist/config.js +1 -1
  24. package/dist/{create-agent-MBOOT3XK.js → create-agent-K5Q7BFGZ.js} +4 -4
  25. package/dist/{create-annotation-XMV6A7ED.js → create-annotation-KN3GE3DK.js} +4 -4
  26. package/dist/create-api-key-OQI5PUNQ.js +26 -0
  27. package/dist/{create-dashboard-VRKLFVZJ.js → create-dashboard-G4QA5AXP.js} +4 -4
  28. package/dist/{create-dataset-7HQPZCRE.js → create-dataset-WQSC37N7.js} +4 -4
  29. package/dist/{create-dataset-records-2NIVFYTV.js → create-dataset-records-B4RL3FLC.js} +4 -4
  30. package/dist/{create-evaluator-WYFRFLRC.js → create-evaluator-YFFQIR7E.js} +4 -4
  31. package/dist/create-mcp-server.js +3 -2
  32. package/dist/create-project-CUVQ67VN.js +44 -0
  33. package/dist/{create-prompt-IEN7O6JT.js → create-prompt-NGXKSP4X.js} +3 -3
  34. package/dist/{create-prompt-tag-CAEZ45VO.js → create-prompt-tag-IUKYPVHH.js} +3 -3
  35. package/dist/{create-scenario-6YHSMGLP.js → create-scenario-FNBXALH3.js} +4 -4
  36. package/dist/{create-suite-H5XOFDE5.js → create-suite-DJEPD4ZB.js} +4 -4
  37. package/dist/{delete-agent-JKTNBWAA.js → delete-agent-TJI5XBBM.js} +4 -4
  38. package/dist/{delete-annotation-ACMDV6QO.js → delete-annotation-KRP53TUU.js} +4 -4
  39. package/dist/{delete-dashboard-VJSR7CRU.js → delete-dashboard-N5SZJIR3.js} +4 -4
  40. package/dist/{delete-dataset-RTTTWP4D.js → delete-dataset-KDUOHL2P.js} +4 -4
  41. package/dist/{delete-dataset-records-KNQTIPQK.js → delete-dataset-records-DM4W3PAW.js} +4 -4
  42. package/dist/{delete-evaluator-7FVC5WM4.js → delete-evaluator-7ZATLJOA.js} +4 -4
  43. package/dist/{delete-prompt-tag-ZMZUAGFW.js → delete-prompt-tag-I6HNMSVJ.js} +3 -3
  44. package/dist/{delete-workflow-EYQ3T4RQ.js → delete-workflow-QEO74JQR.js} +4 -4
  45. package/dist/{get-agent-E3QSTVKG.js → get-agent-3KDWCP5N.js} +4 -4
  46. package/dist/{get-analytics-2OHV763I.js → get-analytics-GPVJX7SF.js} +3 -3
  47. package/dist/{get-dashboard-PC7JDHH6.js → get-dashboard-YPTIE5YY.js} +4 -4
  48. package/dist/{get-dataset-H5IK5FVU.js → get-dataset-6DQFYITM.js} +4 -4
  49. package/dist/{get-evaluator-UWVUPYTM.js → get-evaluator-PCM6XQAU.js} +4 -4
  50. package/dist/get-project-JCMWXVLU.js +26 -0
  51. package/dist/{get-prompt-WZUOLLQC.js → get-prompt-5XAGWWBG.js} +3 -3
  52. package/dist/{get-scenario-Q6LCNUYN.js → get-scenario-7XBCDZWX.js} +4 -4
  53. package/dist/{get-simulation-run-Z2XKO256.js → get-simulation-run-AV24FJWI.js} +4 -4
  54. package/dist/{get-suite-BXK5TN7P.js → get-suite-4DBVHFEM.js} +4 -4
  55. package/dist/{get-trace-4EJAYVBG.js → get-trace-MRBDS3HJ.js} +3 -3
  56. package/dist/{get-workflow-O34QJLHD.js → get-workflow-UR4Y6UFX.js} +4 -4
  57. package/dist/{http-server-ISHF7NJX.js → http-server-DEGNV5EP.js} +4 -3
  58. package/dist/index.js +1453 -431
  59. package/dist/{langwatch-api-annotations-ERBG27RF.js → langwatch-api-annotations-ZJDRB4JH.js} +4 -4
  60. package/dist/{langwatch-api-dashboards-G6TR7VVO.js → langwatch-api-dashboards-WARLI6NF.js} +4 -4
  61. package/dist/{langwatch-api-monitors-WSXZLS2B.js → langwatch-api-monitors-4XKXHYCG.js} +3 -3
  62. package/dist/{langwatch-api-secrets-RR5DKG2X.js → langwatch-api-secrets-6SHK5G7Q.js} +3 -3
  63. package/dist/{langwatch-api-triggers-2RTNSWQY.js → langwatch-api-triggers-5SX6R2WU.js} +3 -3
  64. package/dist/langwatch-api-workflows-NLJENNXE.js +15 -0
  65. package/dist/{list-agents-AW3P6FJV.js → list-agents-NECO7MPI.js} +4 -4
  66. package/dist/{list-annotations-QNCGWPQ3.js → list-annotations-3OJEO774.js} +4 -4
  67. package/dist/list-api-keys-AWW7ROLB.js +37 -0
  68. package/dist/{list-dashboards-R7RK2IXL.js → list-dashboards-DVPVVVKW.js} +4 -4
  69. package/dist/{list-dataset-records-WVCSQP7P.js → list-dataset-records-I4BYORF5.js} +4 -4
  70. package/dist/{list-datasets-KEXRLDEU.js → list-datasets-WUAE5HGX.js} +4 -4
  71. package/dist/{list-evaluators-7R2LB4JH.js → list-evaluators-B6OSVAM2.js} +4 -4
  72. package/dist/{list-model-providers-OBYJCKBX.js → list-model-providers-NL6IP4UZ.js} +4 -4
  73. package/dist/list-projects-5FHMJ4PQ.js +42 -0
  74. package/dist/{list-prompt-tags-6LY3ZPYI.js → list-prompt-tags-Z2DD6FLQ.js} +3 -3
  75. package/dist/{list-prompts-VWEZ4CDE.js → list-prompts-VNXKHK7T.js} +3 -3
  76. package/dist/{list-scenarios-TXD4W2ZJ.js → list-scenarios-CFZHXL76.js} +4 -4
  77. package/dist/{list-simulation-runs-RHPOLMFI.js → list-simulation-runs-AM2BXLBW.js} +4 -4
  78. package/dist/{list-suites-FSGBX27Z.js → list-suites-ZDOHAAXF.js} +4 -4
  79. package/dist/{list-workflows-VRGEZ3EN.js → list-workflows-WBRBKLIT.js} +4 -4
  80. package/dist/{rename-prompt-tag-VOJJLX4M.js → rename-prompt-tag-A4RJUK7Z.js} +3 -3
  81. package/dist/revoke-api-key-ZSPSPF5G.js +15 -0
  82. package/dist/{run-agent-KTCC7TB7.js → run-agent-JFNDY7MR.js} +4 -4
  83. package/dist/{run-suite-BTMHGI2D.js → run-suite-TH7LO5TJ.js} +4 -4
  84. package/dist/{run-workflow-IGAYGKJL.js → run-workflow-CK3JP5U2.js} +4 -4
  85. package/dist/{search-traces-VYFUIMXH.js → search-traces-3BBVYPC3.js} +3 -3
  86. package/dist/{set-model-provider-W5IUI326.js → set-model-provider-WOC5FNMV.js} +4 -4
  87. package/dist/{update-agent-4BB7EYLR.js → update-agent-YMEV5MTL.js} +4 -4
  88. package/dist/{update-dataset-CXBKZ4W3.js → update-dataset-EYT5POFM.js} +4 -4
  89. package/dist/{update-dataset-record-HOHAMHXG.js → update-dataset-record-VFF5JTX4.js} +4 -4
  90. package/dist/{update-evaluator-IVOR6FTR.js → update-evaluator-6IJHFG2E.js} +4 -4
  91. package/dist/update-project-OIT4WPFI.js +24 -0
  92. package/dist/{update-prompt-OWQAKE7K.js → update-prompt-ZU2DD6KM.js} +3 -3
  93. package/dist/{update-scenario-GDFVILPN.js → update-scenario-3VUTPDRU.js} +4 -4
  94. package/dist/{update-suite-BXYUYSPT.js → update-suite-C6JFDQHL.js} +4 -4
  95. package/package.json +7 -7
  96. package/pnpm-workspace.yaml +2 -0
  97. package/pyproject.toml +3 -0
  98. package/src/__tests__/all-tools.integration.test.ts +9 -0
  99. package/src/__tests__/datasets.integration.test.ts +17 -0
  100. package/src/__tests__/datasets.unit.test.ts +4 -0
  101. package/src/__tests__/experiment-list-tools.unit.test.ts +157 -0
  102. package/src/__tests__/get-experiment-results.unit.test.ts +222 -0
  103. package/src/__tests__/project-api-key-tools.unit.test.ts +451 -0
  104. package/src/__tests__/scenario-tools.unit.test.ts +3 -0
  105. package/src/config.ts +2 -0
  106. package/src/create-mcp-server.ts +257 -13
  107. package/src/langwatch-api-api-keys.ts +54 -0
  108. package/src/langwatch-api-projects.ts +82 -0
  109. package/src/langwatch-api.ts +22 -4
  110. package/src/tools/archive-project.ts +14 -0
  111. package/src/tools/create-api-key.ts +29 -0
  112. package/src/tools/create-project.ts +45 -0
  113. package/src/tools/get-experiment-results.ts +273 -0
  114. package/src/tools/get-project.ts +20 -0
  115. package/src/tools/list-api-keys.ts +33 -0
  116. package/src/tools/list-experiment-runs.ts +142 -0
  117. package/src/tools/list-experiments.ts +95 -0
  118. package/src/tools/list-projects.ts +41 -0
  119. package/src/tools/revoke-api-key.ts +9 -0
  120. package/src/tools/{run-evaluation.ts → run-experiment.ts} +5 -5
  121. package/src/tools/update-project.ts +22 -0
  122. package/uv.lock +192 -530
  123. package/Dockerfile +0 -22
  124. package/build.js +0 -12
  125. package/dist/archive-scenario-WJ2A7ETN.js.map +0 -1
  126. package/dist/archive-suite-4JOM4SSL.js.map +0 -1
  127. package/dist/assign-prompt-tag-GL7EAAF3.js.map +0 -1
  128. package/dist/chunk-2GT7IFWK.js.map +0 -1
  129. package/dist/chunk-2WPLXEKF.js.map +0 -1
  130. package/dist/chunk-4AUB2BIA.js.map +0 -1
  131. package/dist/chunk-BWWY5KEF.js.map +0 -1
  132. package/dist/chunk-CCWCIJJ3.js.map +0 -1
  133. package/dist/chunk-E5JYYU3J.js.map +0 -1
  134. package/dist/chunk-EGH5RPXM.js.map +0 -1
  135. package/dist/chunk-EUQDVOSU.js.map +0 -1
  136. package/dist/chunk-HYMIWO3U.js.map +0 -1
  137. package/dist/chunk-IE4M5OGE.js.map +0 -1
  138. package/dist/chunk-LUMEZEHL.js.map +0 -1
  139. package/dist/chunk-NUFPTHKU.js.map +0 -1
  140. package/dist/chunk-WQG2DFHX.js.map +0 -1
  141. package/dist/chunk-WVI5CJ6S.js.map +0 -1
  142. package/dist/chunk-ZVS4UKN2.js.map +0 -1
  143. package/dist/chunk-ZXKLPC2E.js.map +0 -1
  144. package/dist/config.js.map +0 -1
  145. package/dist/create-agent-MBOOT3XK.js.map +0 -1
  146. package/dist/create-annotation-XMV6A7ED.js.map +0 -1
  147. package/dist/create-dashboard-VRKLFVZJ.js.map +0 -1
  148. package/dist/create-dataset-7HQPZCRE.js.map +0 -1
  149. package/dist/create-dataset-records-2NIVFYTV.js.map +0 -1
  150. package/dist/create-evaluator-WYFRFLRC.js.map +0 -1
  151. package/dist/create-mcp-server.js.map +0 -1
  152. package/dist/create-prompt-IEN7O6JT.js.map +0 -1
  153. package/dist/create-prompt-tag-CAEZ45VO.js.map +0 -1
  154. package/dist/create-scenario-6YHSMGLP.js.map +0 -1
  155. package/dist/create-suite-H5XOFDE5.js.map +0 -1
  156. package/dist/delete-agent-JKTNBWAA.js.map +0 -1
  157. package/dist/delete-annotation-ACMDV6QO.js.map +0 -1
  158. package/dist/delete-dashboard-VJSR7CRU.js.map +0 -1
  159. package/dist/delete-dataset-RTTTWP4D.js.map +0 -1
  160. package/dist/delete-dataset-records-KNQTIPQK.js.map +0 -1
  161. package/dist/delete-evaluator-7FVC5WM4.js.map +0 -1
  162. package/dist/delete-prompt-tag-ZMZUAGFW.js.map +0 -1
  163. package/dist/delete-workflow-EYQ3T4RQ.js.map +0 -1
  164. package/dist/discover-evaluator-schema-H23XCLNE.js.map +0 -1
  165. package/dist/discover-scenario-schema-MEEEVND7.js.map +0 -1
  166. package/dist/discover-schema-3T52ORPB.js.map +0 -1
  167. package/dist/get-agent-E3QSTVKG.js.map +0 -1
  168. package/dist/get-analytics-2OHV763I.js.map +0 -1
  169. package/dist/get-dashboard-PC7JDHH6.js.map +0 -1
  170. package/dist/get-dataset-H5IK5FVU.js.map +0 -1
  171. package/dist/get-evaluator-UWVUPYTM.js.map +0 -1
  172. package/dist/get-prompt-WZUOLLQC.js.map +0 -1
  173. package/dist/get-scenario-Q6LCNUYN.js.map +0 -1
  174. package/dist/get-simulation-run-Z2XKO256.js.map +0 -1
  175. package/dist/get-suite-BXK5TN7P.js.map +0 -1
  176. package/dist/get-trace-4EJAYVBG.js.map +0 -1
  177. package/dist/get-workflow-O34QJLHD.js.map +0 -1
  178. package/dist/http-server-ISHF7NJX.js.map +0 -1
  179. package/dist/index.js.map +0 -1
  180. package/dist/langwatch-api-annotations-ERBG27RF.js.map +0 -1
  181. package/dist/langwatch-api-dashboards-G6TR7VVO.js.map +0 -1
  182. package/dist/langwatch-api-monitors-WSXZLS2B.js.map +0 -1
  183. package/dist/langwatch-api-secrets-RR5DKG2X.js.map +0 -1
  184. package/dist/langwatch-api-triggers-2RTNSWQY.js.map +0 -1
  185. package/dist/langwatch-api-workflows-VJRIIDZ7.js +0 -15
  186. package/dist/langwatch-api-workflows-VJRIIDZ7.js.map +0 -1
  187. package/dist/list-agents-AW3P6FJV.js.map +0 -1
  188. package/dist/list-annotations-QNCGWPQ3.js.map +0 -1
  189. package/dist/list-dashboards-R7RK2IXL.js.map +0 -1
  190. package/dist/list-dataset-records-WVCSQP7P.js.map +0 -1
  191. package/dist/list-datasets-KEXRLDEU.js.map +0 -1
  192. package/dist/list-evaluators-7R2LB4JH.js.map +0 -1
  193. package/dist/list-model-providers-OBYJCKBX.js.map +0 -1
  194. package/dist/list-prompt-tags-6LY3ZPYI.js.map +0 -1
  195. package/dist/list-prompts-VWEZ4CDE.js.map +0 -1
  196. package/dist/list-scenarios-TXD4W2ZJ.js.map +0 -1
  197. package/dist/list-simulation-runs-RHPOLMFI.js.map +0 -1
  198. package/dist/list-suites-FSGBX27Z.js.map +0 -1
  199. package/dist/list-workflows-VRGEZ3EN.js.map +0 -1
  200. package/dist/rename-prompt-tag-VOJJLX4M.js.map +0 -1
  201. package/dist/run-agent-KTCC7TB7.js.map +0 -1
  202. package/dist/run-evaluation-2X3V3Q6L.js +0 -64
  203. package/dist/run-evaluation-2X3V3Q6L.js.map +0 -1
  204. package/dist/run-suite-BTMHGI2D.js.map +0 -1
  205. package/dist/run-workflow-IGAYGKJL.js.map +0 -1
  206. package/dist/search-traces-VYFUIMXH.js.map +0 -1
  207. package/dist/set-model-provider-W5IUI326.js.map +0 -1
  208. package/dist/update-agent-4BB7EYLR.js.map +0 -1
  209. package/dist/update-dataset-CXBKZ4W3.js.map +0 -1
  210. package/dist/update-dataset-record-HOHAMHXG.js.map +0 -1
  211. package/dist/update-evaluator-IVOR6FTR.js.map +0 -1
  212. package/dist/update-prompt-OWQAKE7K.js.map +0 -1
  213. package/dist/update-scenario-GDFVILPN.js.map +0 -1
  214. package/dist/update-suite-BXYUYSPT.js.map +0 -1
  215. package/tests/evaluations.ipynb +0 -649
  216. package/tests/fixtures/azure/azure_openai_stream_bot_expected.py +0 -102
  217. package/tests/fixtures/azure/azure_openai_stream_bot_input.py +0 -78
  218. package/tests/fixtures/dspy/dspy_bot_expected.py +0 -61
  219. package/tests/fixtures/dspy/dspy_bot_input.py +0 -53
  220. package/tests/fixtures/fastapi/fastapi_app_expected.py +0 -68
  221. package/tests/fixtures/fastapi/fastapi_app_input.py +0 -60
  222. package/tests/fixtures/fastapi/prompt_management_fastapi_expected.py +0 -114
  223. package/tests/fixtures/fastapi/prompt_management_fastapi_input.py +0 -88
  224. package/tests/fixtures/haystack/haystack_bot_expected.py +0 -141
  225. package/tests/fixtures/haystack/haystack_bot_input.py +0 -69
  226. package/tests/fixtures/langchain/langchain_bot_expected.py +0 -53
  227. package/tests/fixtures/langchain/langchain_bot_input.py +0 -45
  228. package/tests/fixtures/langchain/langchain_bot_with_memory_expected.py +0 -69
  229. package/tests/fixtures/langchain/langchain_bot_with_memory_input.py +0 -61
  230. package/tests/fixtures/langchain/langchain_rag_bot_expected.py +0 -97
  231. package/tests/fixtures/langchain/langchain_rag_bot_input.py +0 -77
  232. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_expected.py +0 -116
  233. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_input.py +0 -81
  234. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_expected.py +0 -331
  235. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_input.py +0 -106
  236. package/tests/fixtures/litellm/litellm_bot_expected.py +0 -40
  237. package/tests/fixtures/litellm/litellm_bot_input.py +0 -35
  238. package/tests/fixtures/openai/openai_bot_expected.py +0 -43
  239. package/tests/fixtures/openai/openai_bot_function_call_expected.py +0 -91
  240. package/tests/fixtures/openai/openai_bot_function_call_input.py +0 -82
  241. package/tests/fixtures/openai/openai_bot_input.py +0 -36
  242. package/tests/fixtures/openai/openai_bot_rag_expected.py +0 -73
  243. package/tests/fixtures/openai/openai_bot_rag_input.py +0 -51
  244. package/tests/fixtures/opentelemetry/openinference_dspy_bot_expected.py +0 -63
  245. package/tests/fixtures/opentelemetry/openinference_dspy_bot_input.py +0 -58
  246. package/tests/fixtures/opentelemetry/openinference_langchain_bot_expected.py +0 -53
  247. package/tests/fixtures/opentelemetry/openinference_langchain_bot_input.py +0 -52
  248. package/tests/fixtures/opentelemetry/openinference_openai_bot_expected.py +0 -49
  249. package/tests/fixtures/opentelemetry/openinference_openai_bot_input.py +0 -41
  250. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_expected.py +0 -44
  251. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_input.py +0 -40
  252. package/tests/fixtures/strands/strands_bot_expected.py +0 -84
  253. package/tests/fixtures/strands/strands_bot_input.py +0 -52
  254. package/tests/scenario-openai.test.ts +0 -160
  255. package/tsup.config.ts +0 -14
  256. package/vitest.config.js +0 -7
@@ -1,141 +0,0 @@
1
- from typing import List
2
- from dotenv import load_dotenv
3
-
4
- from langwatch.types import RAGChunk
5
-
6
- load_dotenv()
7
-
8
- import chainlit as cl
9
-
10
- from haystack import Pipeline, Document, component
11
- from haystack.utils import Secret
12
- from haystack.document_stores.in_memory import InMemoryDocumentStore
13
- from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
14
- from haystack.components.generators import OpenAIGenerator
15
- from haystack.components.builders.prompt_builder import PromptBuilder
16
-
17
- import os
18
- import langwatch
19
-
20
-
21
- # Haystack pipeline
22
-
23
- # Write documents to InMemoryDocumentStore
24
- document_store = InMemoryDocumentStore()
25
- document_store.write_documents(
26
- [
27
- Document(content="My name is Jean and I live in Paris."),
28
- Document(content="My name is Mark and I live in Berlin."),
29
- Document(content="My name is Giorgio and I live in Rome."),
30
- ]
31
- )
32
-
33
- # Build a RAG pipeline
34
- prompt_template = """
35
- Given these documents, answer the question.
36
- Documents:
37
- {% for doc in documents %}
38
- {{ doc.content }}
39
- {% endfor %}
40
- Question: {{question}}
41
- Answer:
42
- """
43
-
44
-
45
- class TrackedInMemoryBM25Retriever(InMemoryBM25Retriever):
46
- @langwatch.span(type="rag")
47
- @component.output_types(documents=List[Document])
48
- def run(self, query: str, **kwargs):
49
- results = super().run(query, **kwargs)
50
- langwatch.get_current_span().update(
51
- contexts=[
52
- RAGChunk(
53
- document_id=document.id,
54
- content=document.content or "",
55
- )
56
- for document in results["documents"]
57
- ]
58
- )
59
- return results
60
-
61
- @component.output_types(documents=List[Document])
62
- async def run_async(self, query: str, **kwargs):
63
- return self.run(query, **kwargs)
64
-
65
-
66
- retriever = TrackedInMemoryBM25Retriever(document_store=document_store)
67
-
68
-
69
- class TrackedPromptBuilder(PromptBuilder):
70
- @langwatch.span()
71
- @component.output_types(prompt=str)
72
- def run(self, template=None, template_variables=None, **kwargs):
73
- return super().run(template, template_variables, **kwargs)
74
-
75
- @component.output_types(prompt=str)
76
- async def run_async(self, template=None, template_variables=None, **kwargs):
77
- return self.run(template, template_variables, **kwargs)
78
-
79
-
80
- prompt_builder = TrackedPromptBuilder(template=prompt_template)
81
-
82
-
83
- class TrackedOpenAIGenerator(OpenAIGenerator):
84
- @langwatch.span(type="llm")
85
- def run(self, prompt: str, **kwargs):
86
- result = super().run(prompt, **kwargs)
87
- langwatch.get_current_span().update(
88
- model=self.model,
89
- output=result["replies"][0],
90
- metrics={
91
- "prompt_tokens": result["meta"][0]["usage"]["prompt_tokens"],
92
- "completion_tokens": result["meta"][0]["usage"]["completion_tokens"],
93
- },
94
- )
95
- return result
96
-
97
- async def run_async(self, prompt: str, **kwargs):
98
- return self.run(prompt, **kwargs)
99
-
100
-
101
- llm = TrackedOpenAIGenerator(
102
- api_key=Secret.from_token(os.environ["OPENAI_API_KEY"]), model="gpt-5"
103
- )
104
-
105
- rag_pipeline = Pipeline()
106
- rag_pipeline.add_component("retriever", retriever)
107
- rag_pipeline.add_component("prompt_builder", prompt_builder)
108
- rag_pipeline.add_component("llm", llm)
109
- rag_pipeline.connect("retriever", "prompt_builder.documents")
110
- rag_pipeline.connect("prompt_builder", "llm")
111
-
112
-
113
- @cl.on_message
114
- @langwatch.trace()
115
- async def main(message: cl.Message):
116
- langwatch.get_current_trace().update(
117
- metadata={"labels": ["haystack", "rag"]},
118
- )
119
-
120
- msg = cl.Message(
121
- content="",
122
- )
123
-
124
- langwatch.get_current_trace().update(
125
- metadata={
126
- "thread_id": message.thread_id,
127
- "user_id": "my-test-user",
128
- "tags": ["User relevant question", "Second tag example"],
129
- "metadata": {"foo": "bar"},
130
- }
131
- )
132
-
133
- results = rag_pipeline.run(
134
- {
135
- "retriever": {"query": message.content},
136
- "prompt_builder": {"question": message.content},
137
- }
138
- )
139
-
140
- msg.content = results["llm"]["replies"][0]
141
- await msg.send()
@@ -1,69 +0,0 @@
1
- from typing import List
2
- from dotenv import load_dotenv
3
-
4
- load_dotenv()
5
-
6
- import chainlit as cl
7
-
8
- from haystack import Pipeline, Document, component
9
- from haystack.utils import Secret
10
- from haystack.document_stores.in_memory import InMemoryDocumentStore
11
- from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
12
- from haystack.components.generators import OpenAIGenerator
13
- from haystack.components.builders.prompt_builder import PromptBuilder
14
-
15
- import os
16
-
17
-
18
- # Haystack pipeline
19
-
20
- # Write documents to InMemoryDocumentStore
21
- document_store = InMemoryDocumentStore()
22
- document_store.write_documents(
23
- [
24
- Document(content="My name is Jean and I live in Paris."),
25
- Document(content="My name is Mark and I live in Berlin."),
26
- Document(content="My name is Giorgio and I live in Rome."),
27
- ]
28
- )
29
-
30
- # Build a RAG pipeline
31
- prompt_template = """
32
- Given these documents, answer the question.
33
- Documents:
34
- {% for doc in documents %}
35
- {{ doc.content }}
36
- {% endfor %}
37
- Question: {{question}}
38
- Answer:
39
- """
40
-
41
- retriever = InMemoryBM25Retriever(document_store=document_store)
42
- prompt_builder = PromptBuilder(template=prompt_template)
43
- llm = OpenAIGenerator(
44
- api_key=Secret.from_token(os.environ["OPENAI_API_KEY"]), model="gpt-5"
45
- )
46
-
47
- rag_pipeline = Pipeline()
48
- rag_pipeline.add_component("retriever", retriever)
49
- rag_pipeline.add_component("prompt_builder", prompt_builder)
50
- rag_pipeline.add_component("llm", llm)
51
- rag_pipeline.connect("retriever", "prompt_builder.documents")
52
- rag_pipeline.connect("prompt_builder", "llm")
53
-
54
-
55
- @cl.on_message
56
- async def main(message: cl.Message):
57
- msg = cl.Message(
58
- content="",
59
- )
60
-
61
- results = rag_pipeline.run(
62
- {
63
- "retriever": {"query": message.content},
64
- "prompt_builder": {"question": message.content},
65
- }
66
- )
67
-
68
- msg.content = results["llm"]["replies"][0]
69
- await msg.send()
@@ -1,53 +0,0 @@
1
- from dotenv import load_dotenv
2
- from langchain_openai import ChatOpenAI
3
-
4
- load_dotenv()
5
-
6
- import chainlit as cl
7
- from langchain.prompts import ChatPromptTemplate
8
- from langchain.schema import StrOutputParser
9
- from langchain.schema.runnable import Runnable
10
- from langchain.schema.runnable.config import RunnableConfig
11
-
12
- import langwatch
13
-
14
-
15
- @cl.on_chat_start
16
- async def on_chat_start():
17
- model = ChatOpenAI(streaming=True)
18
- prompt = ChatPromptTemplate.from_messages(
19
- [
20
- (
21
- "system",
22
- "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis.",
23
- ),
24
- ("human", "{question}"),
25
- ]
26
- )
27
- runnable = prompt | model | StrOutputParser()
28
- cl.user_session.set("runnable", runnable)
29
-
30
-
31
- @cl.on_message
32
- @langwatch.trace()
33
- async def main(message: cl.Message):
34
- runnable: Runnable = cl.user_session.get("runnable") # type: ignore
35
-
36
- msg = cl.Message(content="")
37
-
38
- langwatch.get_current_trace().update(
39
- metadata={"customer_id": "customer_example", "labels": ["langchain"]}
40
- )
41
-
42
- async for chunk in runnable.astream(
43
- {"question": message.content},
44
- config=RunnableConfig(
45
- callbacks=[
46
- cl.LangchainCallbackHandler(),
47
- langwatch.get_current_trace().get_langchain_callback(),
48
- ]
49
- ),
50
- ):
51
- await msg.stream_token(chunk)
52
-
53
- await msg.send()
@@ -1,45 +0,0 @@
1
- from dotenv import load_dotenv
2
- from langchain_openai import ChatOpenAI
3
-
4
- load_dotenv()
5
-
6
- import chainlit as cl
7
- from langchain.prompts import ChatPromptTemplate
8
- from langchain.schema import StrOutputParser
9
- from langchain.schema.runnable import Runnable
10
- from langchain.schema.runnable.config import RunnableConfig
11
-
12
-
13
- @cl.on_chat_start
14
- async def on_chat_start():
15
- model = ChatOpenAI(streaming=True)
16
- prompt = ChatPromptTemplate.from_messages(
17
- [
18
- (
19
- "system",
20
- "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis.",
21
- ),
22
- ("human", "{question}"),
23
- ]
24
- )
25
- runnable = prompt | model | StrOutputParser()
26
- cl.user_session.set("runnable", runnable)
27
-
28
-
29
- @cl.on_message
30
- async def main(message: cl.Message):
31
- runnable: Runnable = cl.user_session.get("runnable") # type: ignore
32
-
33
- msg = cl.Message(content="")
34
-
35
- async for chunk in runnable.astream(
36
- {"question": message.content},
37
- config=RunnableConfig(
38
- callbacks=[
39
- cl.LangchainCallbackHandler(),
40
- ]
41
- ),
42
- ):
43
- await msg.stream_token(chunk)
44
-
45
- await msg.send()
@@ -1,69 +0,0 @@
1
- from dotenv import load_dotenv
2
- from langchain_openai import ChatOpenAI
3
-
4
- load_dotenv()
5
-
6
- import chainlit as cl
7
- from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
8
- from langchain.schema.runnable import Runnable, RunnableMap
9
- from langchain.schema.runnable.config import RunnableConfig
10
- from langchain.memory import ConversationBufferMemory
11
-
12
- import langwatch
13
-
14
-
15
- session_memories: dict = {}
16
-
17
-
18
- @cl.on_chat_start
19
- async def on_chat_start():
20
- memory = session_memories.setdefault(
21
- cl.user_session.get("session_id"),
22
- ConversationBufferMemory(return_messages=True, memory_key="chat_history"),
23
- )
24
- ingress = RunnableMap(
25
- {
26
- "input": lambda x: x["input"],
27
- "chat_history": lambda x: memory.load_memory_variables(x)["chat_history"],
28
- }
29
- )
30
- prompt = ChatPromptTemplate.from_messages(
31
- [
32
- ("system", "You are a helpful assistant."),
33
- MessagesPlaceholder(variable_name="chat_history"),
34
- ("human", "{input}"),
35
- ]
36
- )
37
- llm = ChatOpenAI(temperature=0.3, model="gpt-5", max_tokens=4096)
38
- runnable = ingress | prompt | llm
39
-
40
- cl.user_session.set("runnable", runnable)
41
- cl.user_session.set("memory", memory)
42
-
43
-
44
- @cl.on_message
45
- @langwatch.trace()
46
- async def main(message: cl.Message):
47
- runnable: Runnable = cl.user_session.get("runnable") # type: ignore
48
- memory = cl.user_session.get("memory") # type: ignore
49
-
50
- msg = cl.Message(content="")
51
-
52
- langwatch.get_current_trace().update(
53
- metadata={"customer_id": "customer_example", "labels": ["langchain", "memory"]}
54
- )
55
-
56
- async for chunk in runnable.astream(
57
- {"input": message.content},
58
- config=RunnableConfig(
59
- callbacks=[
60
- cl.LangchainCallbackHandler(),
61
- langwatch.get_current_trace().get_langchain_callback(),
62
- ]
63
- ),
64
- ):
65
- await msg.stream_token(chunk.content)
66
-
67
- memory.save_context({"input": message.content}, {"output": msg.content}) # type: ignore
68
-
69
- await msg.send()
@@ -1,61 +0,0 @@
1
- from dotenv import load_dotenv
2
- from langchain_openai import ChatOpenAI
3
-
4
- load_dotenv()
5
-
6
- import chainlit as cl
7
- from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
8
- from langchain.schema.runnable import Runnable, RunnableMap
9
- from langchain.schema.runnable.config import RunnableConfig
10
- from langchain.memory import ConversationBufferMemory
11
-
12
-
13
- session_memories: dict = {}
14
-
15
-
16
- @cl.on_chat_start
17
- async def on_chat_start():
18
- memory = session_memories.setdefault(
19
- cl.user_session.get("session_id"),
20
- ConversationBufferMemory(return_messages=True, memory_key="chat_history"),
21
- )
22
- ingress = RunnableMap(
23
- {
24
- "input": lambda x: x["input"],
25
- "chat_history": lambda x: memory.load_memory_variables(x)["chat_history"],
26
- }
27
- )
28
- prompt = ChatPromptTemplate.from_messages(
29
- [
30
- ("system", "You are a helpful assistant."),
31
- MessagesPlaceholder(variable_name="chat_history"),
32
- ("human", "{input}"),
33
- ]
34
- )
35
- llm = ChatOpenAI(temperature=0.3, model="gpt-5", max_tokens=4096)
36
- runnable = ingress | prompt | llm
37
-
38
- cl.user_session.set("runnable", runnable)
39
- cl.user_session.set("memory", memory)
40
-
41
-
42
- @cl.on_message
43
- async def main(message: cl.Message):
44
- runnable: Runnable = cl.user_session.get("runnable") # type: ignore
45
- memory = cl.user_session.get("memory") # type: ignore
46
-
47
- msg = cl.Message(content="")
48
-
49
- async for chunk in runnable.astream(
50
- {"input": message.content},
51
- config=RunnableConfig(
52
- callbacks=[
53
- cl.LangchainCallbackHandler(),
54
- ]
55
- ),
56
- ):
57
- await msg.stream_token(chunk.content)
58
-
59
- memory.save_context({"input": message.content}, {"output": msg.content}) # type: ignore
60
-
61
- await msg.send()
@@ -1,97 +0,0 @@
1
- from dotenv import load_dotenv
2
-
3
- from langwatch.types import RAGChunk
4
-
5
- load_dotenv()
6
-
7
- import chainlit as cl
8
- from langchain.prompts import ChatPromptTemplate
9
- from langchain.schema import HumanMessage
10
- from langchain.schema.runnable.config import RunnableConfig
11
-
12
- import langwatch
13
-
14
- from langchain_community.document_loaders import WebBaseLoader
15
- from langchain_community.vectorstores.faiss import FAISS
16
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
17
- from langchain_text_splitters import RecursiveCharacterTextSplitter
18
- from langchain.tools.retriever import create_retriever_tool
19
- from langchain.agents import AgentExecutor, create_tool_calling_agent
20
- from langchain.tools import BaseTool, StructuredTool, tool
21
-
22
- loader = WebBaseLoader("https://docs.langwatch.ai")
23
- docs = loader.load()
24
- documents = RecursiveCharacterTextSplitter(
25
- chunk_size=1000, chunk_overlap=200
26
- ).split_documents(docs)
27
- vector = FAISS.from_documents(documents, OpenAIEmbeddings())
28
- retriever = vector.as_retriever()
29
-
30
-
31
- @cl.on_chat_start
32
- async def on_chat_start():
33
- retriever_tool = create_retriever_tool(
34
- langwatch.langchain.capture_rag_from_retriever(
35
- retriever,
36
- lambda document: RAGChunk(
37
- document_id=document.metadata["source"], content=document.page_content
38
- ),
39
- ),
40
- "langwatch_search",
41
- "Search for information about LangWatch. For any questions about LangWatch, use this tool if you didn't already",
42
- )
43
-
44
- # Alternative approach to retrievers
45
- # wrapped_tool = langwatch.langchain.capture_rag_from_tool(
46
- # retriever_tool, lambda response: [RAGChunk(content=response)]
47
- # )
48
-
49
- tools = [retriever_tool]
50
- model = ChatOpenAI(model="gpt-5", streaming=True)
51
- prompt = ChatPromptTemplate.from_messages(
52
- [
53
- (
54
- "system",
55
- "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis and use tools only once.\n\n{agent_scratchpad}",
56
- ),
57
- ("human", "{question}"),
58
- ]
59
- )
60
- agent = create_tool_calling_agent(model, tools, prompt)
61
- executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # type: ignore
62
- cl.user_session.set("agent", executor)
63
-
64
-
65
- @cl.on_message
66
- @langwatch.trace()
67
- async def main(message: cl.Message):
68
- agent: AgentExecutor = cl.user_session.get("agent") # type: ignore
69
-
70
- msg = cl.Message(content="")
71
-
72
- langwatch.get_current_trace().update(
73
- metadata={"user_id": "user_example", "labels": ["langchain", "rag"]}
74
- )
75
-
76
- async for chunk in agent.astream(
77
- {
78
- "question": message.content,
79
- "messages": [HumanMessage(content="Hoi, dit is een test")],
80
- },
81
- config=RunnableConfig(
82
- callbacks=[
83
- cl.LangchainCallbackHandler(),
84
- langwatch.get_current_trace().get_langchain_callback(),
85
- ]
86
- ),
87
- ):
88
- if "output" in chunk:
89
- await msg.stream_token(chunk["output"])
90
- elif "actions" in chunk:
91
- await msg.stream_token(chunk["actions"][0].log)
92
- elif "steps" in chunk:
93
- await msg.stream_token(chunk["steps"][0].observation + "\n\n")
94
- else:
95
- await msg.stream_token("<unammaped chunk>")
96
-
97
- await msg.send()
@@ -1,77 +0,0 @@
1
- from dotenv import load_dotenv
2
-
3
- load_dotenv()
4
-
5
- import chainlit as cl
6
- from langchain.prompts import ChatPromptTemplate
7
- from langchain.schema import HumanMessage
8
- from langchain.schema.runnable.config import RunnableConfig
9
-
10
- from langchain_community.document_loaders import WebBaseLoader
11
- from langchain_community.vectorstores.faiss import FAISS
12
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
13
- from langchain_text_splitters import RecursiveCharacterTextSplitter
14
- from langchain.tools.retriever import create_retriever_tool
15
- from langchain.agents import AgentExecutor, create_tool_calling_agent
16
- from langchain.tools import BaseTool, StructuredTool, tool
17
-
18
- loader = WebBaseLoader("https://docs.langwatch.ai")
19
- docs = loader.load()
20
- documents = RecursiveCharacterTextSplitter(
21
- chunk_size=1000, chunk_overlap=200
22
- ).split_documents(docs)
23
- vector = FAISS.from_documents(documents, OpenAIEmbeddings())
24
- retriever = vector.as_retriever()
25
-
26
-
27
- @cl.on_chat_start
28
- async def on_chat_start():
29
- retriever_tool = create_retriever_tool(
30
- retriever,
31
- "langwatch_search",
32
- "Search for information about LangWatch. For any questions about LangWatch, use this tool if you didn't already",
33
- )
34
-
35
- tools = [retriever_tool]
36
- model = ChatOpenAI(model="gpt-5", streaming=True)
37
- prompt = ChatPromptTemplate.from_messages(
38
- [
39
- (
40
- "system",
41
- "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis and use tools only once.\n\n{agent_scratchpad}",
42
- ),
43
- ("human", "{question}"),
44
- ]
45
- )
46
- agent = create_tool_calling_agent(model, tools, prompt)
47
- executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # type: ignore
48
- cl.user_session.set("agent", executor)
49
-
50
-
51
- @cl.on_message
52
- async def main(message: cl.Message):
53
- agent: AgentExecutor = cl.user_session.get("agent") # type: ignore
54
-
55
- msg = cl.Message(content="")
56
-
57
- async for chunk in agent.astream(
58
- {
59
- "question": message.content,
60
- "messages": [HumanMessage(content="Hoi, dit is een test")],
61
- },
62
- config=RunnableConfig(
63
- callbacks=[
64
- cl.LangchainCallbackHandler(),
65
- ]
66
- ),
67
- ):
68
- if "output" in chunk:
69
- await msg.stream_token(chunk["output"])
70
- elif "actions" in chunk:
71
- await msg.stream_token(chunk["actions"][0].log)
72
- elif "steps" in chunk:
73
- await msg.stream_token(chunk["steps"][0].observation + "\n\n")
74
- else:
75
- await msg.stream_token("<unammaped chunk>")
76
-
77
- await msg.send()