@langwatch/mcp-server 0.7.0 → 0.8.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 (225) hide show
  1. package/.release-please-shim +1 -0
  2. package/CHANGELOG.md +66 -0
  3. package/dist/{archive-scenario-WJ2A7ETN.js → archive-scenario-YKGLJ4MZ.js} +4 -4
  4. package/dist/{archive-suite-4JOM4SSL.js → archive-suite-QFNDO3Y3.js} +4 -4
  5. package/dist/{assign-prompt-tag-GL7EAAF3.js → assign-prompt-tag-Y2B4CBBT.js} +3 -3
  6. package/dist/{chunk-E5JYYU3J.js → chunk-B57MZ4WI.js} +89 -83
  7. package/dist/{chunk-CCWCIJJ3.js → chunk-CPUPGDNA.js} +2 -2
  8. package/dist/{chunk-LUMEZEHL.js → chunk-FBRKHHJV.js} +2 -2
  9. package/dist/{chunk-HYMIWO3U.js → chunk-HDJDFKZR.js} +2 -2
  10. package/dist/{chunk-BWWY5KEF.js → chunk-KOO5733S.js} +3 -2
  11. package/dist/{chunk-EUQDVOSU.js → chunk-KZNBCKWG.js} +2 -2
  12. package/dist/{chunk-IE4M5OGE.js → chunk-L6QENXYA.js} +2 -2
  13. package/dist/{chunk-2GT7IFWK.js → chunk-NACSR6B7.js} +2 -2
  14. package/dist/{chunk-WQG2DFHX.js → chunk-OVQF3D5R.js} +2 -2
  15. package/dist/{chunk-ZVS4UKN2.js → chunk-PO7FM7IX.js} +2 -2
  16. package/dist/{chunk-EGH5RPXM.js → chunk-PZUWCWOS.js} +2 -2
  17. package/dist/{chunk-2WPLXEKF.js → chunk-YH2IBTEL.js} +7 -3
  18. package/dist/{chunk-4AUB2BIA.js → chunk-YI3OG4PI.js} +3 -3
  19. package/dist/config.js +1 -1
  20. package/dist/{create-agent-MBOOT3XK.js → create-agent-YRSDH7P7.js} +4 -4
  21. package/dist/{create-annotation-XMV6A7ED.js → create-annotation-FYQNKMVJ.js} +4 -4
  22. package/dist/{create-dashboard-VRKLFVZJ.js → create-dashboard-CORBR4YQ.js} +4 -4
  23. package/dist/{create-dataset-7HQPZCRE.js → create-dataset-ZC63T6BB.js} +4 -4
  24. package/dist/{create-dataset-records-2NIVFYTV.js → create-dataset-records-ILVNVKVR.js} +4 -4
  25. package/dist/{create-evaluator-WYFRFLRC.js → create-evaluator-2AU3PXFB.js} +4 -4
  26. package/dist/create-mcp-server.js +2 -2
  27. package/dist/{create-prompt-IEN7O6JT.js → create-prompt-NKRJ47YY.js} +3 -3
  28. package/dist/{create-prompt-tag-CAEZ45VO.js → create-prompt-tag-S4JX3ULL.js} +3 -3
  29. package/dist/{create-scenario-6YHSMGLP.js → create-scenario-BPRF75KF.js} +4 -4
  30. package/dist/{create-suite-H5XOFDE5.js → create-suite-4YN7D6K2.js} +4 -4
  31. package/dist/{delete-agent-JKTNBWAA.js → delete-agent-Y72R2YQA.js} +4 -4
  32. package/dist/{delete-annotation-ACMDV6QO.js → delete-annotation-UHWDMHSH.js} +4 -4
  33. package/dist/{delete-dashboard-VJSR7CRU.js → delete-dashboard-LPWT36KN.js} +4 -4
  34. package/dist/{delete-dataset-RTTTWP4D.js → delete-dataset-GGPQRHKX.js} +4 -4
  35. package/dist/{delete-dataset-records-KNQTIPQK.js → delete-dataset-records-LTG5LT26.js} +4 -4
  36. package/dist/{delete-evaluator-7FVC5WM4.js → delete-evaluator-F7QLXDHU.js} +4 -4
  37. package/dist/{delete-prompt-tag-ZMZUAGFW.js → delete-prompt-tag-B5UKZL45.js} +3 -3
  38. package/dist/{delete-workflow-EYQ3T4RQ.js → delete-workflow-4DGUDIDE.js} +4 -4
  39. package/dist/{get-agent-E3QSTVKG.js → get-agent-YEVICUX4.js} +4 -4
  40. package/dist/{get-analytics-2OHV763I.js → get-analytics-3W5CMU3F.js} +3 -3
  41. package/dist/{get-dashboard-PC7JDHH6.js → get-dashboard-NCQHN6MW.js} +4 -4
  42. package/dist/{get-dataset-H5IK5FVU.js → get-dataset-KBK6PH36.js} +4 -4
  43. package/dist/{get-evaluator-UWVUPYTM.js → get-evaluator-QDUL5LXR.js} +4 -4
  44. package/dist/{get-prompt-WZUOLLQC.js → get-prompt-XCSSNRKR.js} +3 -3
  45. package/dist/{get-scenario-Q6LCNUYN.js → get-scenario-FNRKOY7E.js} +4 -4
  46. package/dist/{get-simulation-run-Z2XKO256.js → get-simulation-run-WOEKUF7K.js} +4 -4
  47. package/dist/{get-suite-BXK5TN7P.js → get-suite-U5AOD5TC.js} +4 -4
  48. package/dist/{get-trace-4EJAYVBG.js → get-trace-MUWEJM2Z.js} +3 -3
  49. package/dist/{get-workflow-O34QJLHD.js → get-workflow-SOA7MT7L.js} +4 -4
  50. package/dist/{http-server-ISHF7NJX.js → http-server-7DMOCB75.js} +3 -3
  51. package/dist/index.js +423 -241
  52. package/dist/{langwatch-api-annotations-ERBG27RF.js → langwatch-api-annotations-Q57NDUVR.js} +4 -4
  53. package/dist/{langwatch-api-dashboards-G6TR7VVO.js → langwatch-api-dashboards-VBWWXV3Y.js} +4 -4
  54. package/dist/{langwatch-api-monitors-WSXZLS2B.js → langwatch-api-monitors-L3IY7FDT.js} +3 -3
  55. package/dist/{langwatch-api-secrets-RR5DKG2X.js → langwatch-api-secrets-S5HHF3XR.js} +3 -3
  56. package/dist/{langwatch-api-triggers-2RTNSWQY.js → langwatch-api-triggers-ME33QE26.js} +3 -3
  57. package/dist/langwatch-api-workflows-4CJQAYP2.js +15 -0
  58. package/dist/{list-agents-AW3P6FJV.js → list-agents-3HGIBJFM.js} +4 -4
  59. package/dist/{list-annotations-QNCGWPQ3.js → list-annotations-KWXYVEPI.js} +4 -4
  60. package/dist/{list-dashboards-R7RK2IXL.js → list-dashboards-VQ2LH666.js} +4 -4
  61. package/dist/{list-dataset-records-WVCSQP7P.js → list-dataset-records-RNRGROJP.js} +4 -4
  62. package/dist/{list-datasets-KEXRLDEU.js → list-datasets-I4A2LT2S.js} +4 -4
  63. package/dist/{list-evaluators-7R2LB4JH.js → list-evaluators-AKKRJ5MX.js} +4 -4
  64. package/dist/{list-model-providers-OBYJCKBX.js → list-model-providers-DVFEHFHZ.js} +4 -4
  65. package/dist/{list-prompt-tags-6LY3ZPYI.js → list-prompt-tags-PL5OISUA.js} +3 -3
  66. package/dist/{list-prompts-VWEZ4CDE.js → list-prompts-7VTFWE2Z.js} +3 -3
  67. package/dist/{list-scenarios-TXD4W2ZJ.js → list-scenarios-5BZWZ6ZN.js} +4 -4
  68. package/dist/{list-simulation-runs-RHPOLMFI.js → list-simulation-runs-WCZ6RLPE.js} +4 -4
  69. package/dist/{list-suites-FSGBX27Z.js → list-suites-RRQ2JX5Y.js} +4 -4
  70. package/dist/{list-workflows-VRGEZ3EN.js → list-workflows-UQB5FCX5.js} +4 -4
  71. package/dist/{rename-prompt-tag-VOJJLX4M.js → rename-prompt-tag-TURD6KYU.js} +3 -3
  72. package/dist/{run-agent-KTCC7TB7.js → run-agent-BEJ4K4CM.js} +4 -4
  73. package/dist/{run-evaluation-2X3V3Q6L.js → run-evaluation-AJ7WZNQD.js} +3 -3
  74. package/dist/{run-suite-BTMHGI2D.js → run-suite-U7V432G2.js} +4 -4
  75. package/dist/{run-workflow-IGAYGKJL.js → run-workflow-5WX7DK5T.js} +4 -4
  76. package/dist/{search-traces-VYFUIMXH.js → search-traces-ZCHNOMTX.js} +3 -3
  77. package/dist/{set-model-provider-W5IUI326.js → set-model-provider-6CFHMCNE.js} +4 -4
  78. package/dist/{update-agent-4BB7EYLR.js → update-agent-UE6UWLZP.js} +4 -4
  79. package/dist/{update-dataset-CXBKZ4W3.js → update-dataset-4XQZZE4S.js} +4 -4
  80. package/dist/{update-dataset-record-HOHAMHXG.js → update-dataset-record-GNNM5TKM.js} +4 -4
  81. package/dist/{update-evaluator-IVOR6FTR.js → update-evaluator-LHVDXIZD.js} +4 -4
  82. package/dist/{update-prompt-OWQAKE7K.js → update-prompt-3XEHECJ7.js} +3 -3
  83. package/dist/{update-scenario-GDFVILPN.js → update-scenario-DFPREYCD.js} +4 -4
  84. package/dist/{update-suite-BXYUYSPT.js → update-suite-RATU5THO.js} +4 -4
  85. package/package.json +6 -6
  86. package/src/__tests__/all-tools.integration.test.ts +9 -0
  87. package/src/__tests__/datasets.integration.test.ts +17 -0
  88. package/src/__tests__/datasets.unit.test.ts +4 -0
  89. package/src/__tests__/scenario-tools.unit.test.ts +3 -0
  90. package/src/config.ts +2 -0
  91. package/src/langwatch-api.ts +5 -1
  92. package/uv.lock +188 -530
  93. package/Dockerfile +0 -22
  94. package/build.js +0 -12
  95. package/dist/archive-scenario-WJ2A7ETN.js.map +0 -1
  96. package/dist/archive-suite-4JOM4SSL.js.map +0 -1
  97. package/dist/assign-prompt-tag-GL7EAAF3.js.map +0 -1
  98. package/dist/chunk-2GT7IFWK.js.map +0 -1
  99. package/dist/chunk-2WPLXEKF.js.map +0 -1
  100. package/dist/chunk-4AUB2BIA.js.map +0 -1
  101. package/dist/chunk-BWWY5KEF.js.map +0 -1
  102. package/dist/chunk-CCWCIJJ3.js.map +0 -1
  103. package/dist/chunk-E5JYYU3J.js.map +0 -1
  104. package/dist/chunk-EGH5RPXM.js.map +0 -1
  105. package/dist/chunk-EUQDVOSU.js.map +0 -1
  106. package/dist/chunk-HYMIWO3U.js.map +0 -1
  107. package/dist/chunk-IE4M5OGE.js.map +0 -1
  108. package/dist/chunk-LUMEZEHL.js.map +0 -1
  109. package/dist/chunk-NUFPTHKU.js.map +0 -1
  110. package/dist/chunk-WQG2DFHX.js.map +0 -1
  111. package/dist/chunk-WVI5CJ6S.js.map +0 -1
  112. package/dist/chunk-ZVS4UKN2.js.map +0 -1
  113. package/dist/chunk-ZXKLPC2E.js.map +0 -1
  114. package/dist/config.js.map +0 -1
  115. package/dist/create-agent-MBOOT3XK.js.map +0 -1
  116. package/dist/create-annotation-XMV6A7ED.js.map +0 -1
  117. package/dist/create-dashboard-VRKLFVZJ.js.map +0 -1
  118. package/dist/create-dataset-7HQPZCRE.js.map +0 -1
  119. package/dist/create-dataset-records-2NIVFYTV.js.map +0 -1
  120. package/dist/create-evaluator-WYFRFLRC.js.map +0 -1
  121. package/dist/create-mcp-server.js.map +0 -1
  122. package/dist/create-prompt-IEN7O6JT.js.map +0 -1
  123. package/dist/create-prompt-tag-CAEZ45VO.js.map +0 -1
  124. package/dist/create-scenario-6YHSMGLP.js.map +0 -1
  125. package/dist/create-suite-H5XOFDE5.js.map +0 -1
  126. package/dist/delete-agent-JKTNBWAA.js.map +0 -1
  127. package/dist/delete-annotation-ACMDV6QO.js.map +0 -1
  128. package/dist/delete-dashboard-VJSR7CRU.js.map +0 -1
  129. package/dist/delete-dataset-RTTTWP4D.js.map +0 -1
  130. package/dist/delete-dataset-records-KNQTIPQK.js.map +0 -1
  131. package/dist/delete-evaluator-7FVC5WM4.js.map +0 -1
  132. package/dist/delete-prompt-tag-ZMZUAGFW.js.map +0 -1
  133. package/dist/delete-workflow-EYQ3T4RQ.js.map +0 -1
  134. package/dist/discover-evaluator-schema-H23XCLNE.js.map +0 -1
  135. package/dist/discover-scenario-schema-MEEEVND7.js.map +0 -1
  136. package/dist/discover-schema-3T52ORPB.js.map +0 -1
  137. package/dist/get-agent-E3QSTVKG.js.map +0 -1
  138. package/dist/get-analytics-2OHV763I.js.map +0 -1
  139. package/dist/get-dashboard-PC7JDHH6.js.map +0 -1
  140. package/dist/get-dataset-H5IK5FVU.js.map +0 -1
  141. package/dist/get-evaluator-UWVUPYTM.js.map +0 -1
  142. package/dist/get-prompt-WZUOLLQC.js.map +0 -1
  143. package/dist/get-scenario-Q6LCNUYN.js.map +0 -1
  144. package/dist/get-simulation-run-Z2XKO256.js.map +0 -1
  145. package/dist/get-suite-BXK5TN7P.js.map +0 -1
  146. package/dist/get-trace-4EJAYVBG.js.map +0 -1
  147. package/dist/get-workflow-O34QJLHD.js.map +0 -1
  148. package/dist/http-server-ISHF7NJX.js.map +0 -1
  149. package/dist/index.js.map +0 -1
  150. package/dist/langwatch-api-annotations-ERBG27RF.js.map +0 -1
  151. package/dist/langwatch-api-dashboards-G6TR7VVO.js.map +0 -1
  152. package/dist/langwatch-api-monitors-WSXZLS2B.js.map +0 -1
  153. package/dist/langwatch-api-secrets-RR5DKG2X.js.map +0 -1
  154. package/dist/langwatch-api-triggers-2RTNSWQY.js.map +0 -1
  155. package/dist/langwatch-api-workflows-VJRIIDZ7.js +0 -15
  156. package/dist/langwatch-api-workflows-VJRIIDZ7.js.map +0 -1
  157. package/dist/list-agents-AW3P6FJV.js.map +0 -1
  158. package/dist/list-annotations-QNCGWPQ3.js.map +0 -1
  159. package/dist/list-dashboards-R7RK2IXL.js.map +0 -1
  160. package/dist/list-dataset-records-WVCSQP7P.js.map +0 -1
  161. package/dist/list-datasets-KEXRLDEU.js.map +0 -1
  162. package/dist/list-evaluators-7R2LB4JH.js.map +0 -1
  163. package/dist/list-model-providers-OBYJCKBX.js.map +0 -1
  164. package/dist/list-prompt-tags-6LY3ZPYI.js.map +0 -1
  165. package/dist/list-prompts-VWEZ4CDE.js.map +0 -1
  166. package/dist/list-scenarios-TXD4W2ZJ.js.map +0 -1
  167. package/dist/list-simulation-runs-RHPOLMFI.js.map +0 -1
  168. package/dist/list-suites-FSGBX27Z.js.map +0 -1
  169. package/dist/list-workflows-VRGEZ3EN.js.map +0 -1
  170. package/dist/rename-prompt-tag-VOJJLX4M.js.map +0 -1
  171. package/dist/run-agent-KTCC7TB7.js.map +0 -1
  172. package/dist/run-evaluation-2X3V3Q6L.js.map +0 -1
  173. package/dist/run-suite-BTMHGI2D.js.map +0 -1
  174. package/dist/run-workflow-IGAYGKJL.js.map +0 -1
  175. package/dist/search-traces-VYFUIMXH.js.map +0 -1
  176. package/dist/set-model-provider-W5IUI326.js.map +0 -1
  177. package/dist/update-agent-4BB7EYLR.js.map +0 -1
  178. package/dist/update-dataset-CXBKZ4W3.js.map +0 -1
  179. package/dist/update-dataset-record-HOHAMHXG.js.map +0 -1
  180. package/dist/update-evaluator-IVOR6FTR.js.map +0 -1
  181. package/dist/update-prompt-OWQAKE7K.js.map +0 -1
  182. package/dist/update-scenario-GDFVILPN.js.map +0 -1
  183. package/dist/update-suite-BXYUYSPT.js.map +0 -1
  184. package/tests/evaluations.ipynb +0 -649
  185. package/tests/fixtures/azure/azure_openai_stream_bot_expected.py +0 -102
  186. package/tests/fixtures/azure/azure_openai_stream_bot_input.py +0 -78
  187. package/tests/fixtures/dspy/dspy_bot_expected.py +0 -61
  188. package/tests/fixtures/dspy/dspy_bot_input.py +0 -53
  189. package/tests/fixtures/fastapi/fastapi_app_expected.py +0 -68
  190. package/tests/fixtures/fastapi/fastapi_app_input.py +0 -60
  191. package/tests/fixtures/fastapi/prompt_management_fastapi_expected.py +0 -114
  192. package/tests/fixtures/fastapi/prompt_management_fastapi_input.py +0 -88
  193. package/tests/fixtures/haystack/haystack_bot_expected.py +0 -141
  194. package/tests/fixtures/haystack/haystack_bot_input.py +0 -69
  195. package/tests/fixtures/langchain/langchain_bot_expected.py +0 -53
  196. package/tests/fixtures/langchain/langchain_bot_input.py +0 -45
  197. package/tests/fixtures/langchain/langchain_bot_with_memory_expected.py +0 -69
  198. package/tests/fixtures/langchain/langchain_bot_with_memory_input.py +0 -61
  199. package/tests/fixtures/langchain/langchain_rag_bot_expected.py +0 -97
  200. package/tests/fixtures/langchain/langchain_rag_bot_input.py +0 -77
  201. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_expected.py +0 -116
  202. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_input.py +0 -81
  203. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_expected.py +0 -331
  204. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_input.py +0 -106
  205. package/tests/fixtures/litellm/litellm_bot_expected.py +0 -40
  206. package/tests/fixtures/litellm/litellm_bot_input.py +0 -35
  207. package/tests/fixtures/openai/openai_bot_expected.py +0 -43
  208. package/tests/fixtures/openai/openai_bot_function_call_expected.py +0 -91
  209. package/tests/fixtures/openai/openai_bot_function_call_input.py +0 -82
  210. package/tests/fixtures/openai/openai_bot_input.py +0 -36
  211. package/tests/fixtures/openai/openai_bot_rag_expected.py +0 -73
  212. package/tests/fixtures/openai/openai_bot_rag_input.py +0 -51
  213. package/tests/fixtures/opentelemetry/openinference_dspy_bot_expected.py +0 -63
  214. package/tests/fixtures/opentelemetry/openinference_dspy_bot_input.py +0 -58
  215. package/tests/fixtures/opentelemetry/openinference_langchain_bot_expected.py +0 -53
  216. package/tests/fixtures/opentelemetry/openinference_langchain_bot_input.py +0 -52
  217. package/tests/fixtures/opentelemetry/openinference_openai_bot_expected.py +0 -49
  218. package/tests/fixtures/opentelemetry/openinference_openai_bot_input.py +0 -41
  219. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_expected.py +0 -44
  220. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_input.py +0 -40
  221. package/tests/fixtures/strands/strands_bot_expected.py +0 -84
  222. package/tests/fixtures/strands/strands_bot_input.py +0 -52
  223. package/tests/scenario-openai.test.ts +0 -160
  224. package/tsup.config.ts +0 -14
  225. package/vitest.config.js +0 -7
@@ -1,116 +0,0 @@
1
- import json
2
- import os
3
- import tempfile
4
- from dotenv import load_dotenv
5
-
6
- from langwatch.types import RAGChunk
7
-
8
- load_dotenv()
9
-
10
- import chainlit as cl
11
- from langchain.prompts import ChatPromptTemplate
12
- from langchain.schema import HumanMessage
13
- from langchain.schema.runnable.config import RunnableConfig
14
-
15
- import langwatch
16
-
17
- from langchain_community.document_loaders import WebBaseLoader
18
- from langchain_community.vectorstores.faiss import FAISS
19
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
20
- from langchain_text_splitters import RecursiveCharacterTextSplitter
21
- from langchain.tools.retriever import create_retriever_tool
22
- from langchain.agents import AgentExecutor, create_tool_calling_agent
23
- from langchain.tools import BaseTool, StructuredTool, tool
24
- from langchain_google_vertexai import ChatVertexAI, VertexAI
25
-
26
- loader = WebBaseLoader("https://docs.langwatch.ai")
27
- docs = loader.load()
28
- documents = RecursiveCharacterTextSplitter(
29
- chunk_size=1000, chunk_overlap=200
30
- ).split_documents(docs)
31
- vector = FAISS.from_documents(documents, OpenAIEmbeddings())
32
- retriever = vector.as_retriever()
33
-
34
-
35
- @cl.on_chat_start
36
- async def on_chat_start():
37
- retriever_tool = create_retriever_tool(
38
- langwatch.langchain.capture_rag_from_retriever(
39
- retriever,
40
- lambda document: RAGChunk(
41
- document_id=document.metadata["source"], content=document.page_content
42
- ),
43
- ),
44
- "langwatch_search",
45
- "Search for information about LangWatch. For any questions about LangWatch, use this tool if you didn't already",
46
- )
47
-
48
- # Alternative approach to retrievers
49
- # wrapped_tool = langwatch.langchain.capture_rag_from_tool(
50
- # retriever_tool, lambda response: [RAGChunk(content=response)]
51
- # )
52
-
53
- try:
54
- credentials_json = json.loads(os.environ["GOOGLE_APPLICATION_CREDENTIALS"])
55
- credentials_file = tempfile.NamedTemporaryFile(mode="w", delete=False)
56
- credentials_file.write(json.dumps(credentials_json))
57
- credentials_file.close()
58
-
59
- os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credentials_file.name
60
- except:
61
- pass
62
-
63
- tools = [retriever_tool]
64
- model = ChatVertexAI(
65
- model_name="gemini-1.5-flash-001",
66
- project=os.environ["VERTEXAI_PROJECT"],
67
- location=os.environ["VERTEXAI_LOCATION"],
68
- streaming=True,
69
- )
70
- prompt = ChatPromptTemplate.from_messages(
71
- [
72
- (
73
- "system",
74
- "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}",
75
- ),
76
- ("human", "{question}"),
77
- ]
78
- )
79
- agent = create_tool_calling_agent(model, tools, prompt)
80
- executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # type: ignore
81
- cl.user_session.set("agent", executor)
82
-
83
-
84
- @cl.on_message
85
- @langwatch.trace()
86
- async def main(message: cl.Message):
87
- agent: AgentExecutor = cl.user_session.get("agent") # type: ignore
88
-
89
- msg = cl.Message(content="")
90
-
91
- langwatch.get_current_trace().update(
92
- metadata={"customer_id": "customer_example", "labels": ["langchain", "rag", "vertex_ai"]}
93
- )
94
-
95
- async for chunk in agent.astream(
96
- {
97
- "question": message.content,
98
- "messages": [HumanMessage(content="Hoi, dit is een test")],
99
- },
100
- config=RunnableConfig(
101
- callbacks=[
102
- cl.LangchainCallbackHandler(),
103
- langwatch.get_current_trace().get_langchain_callback(),
104
- ]
105
- ),
106
- ):
107
- if "output" in chunk:
108
- await msg.stream_token(chunk["output"])
109
- elif "actions" in chunk:
110
- await msg.stream_token(chunk["actions"][0].log)
111
- elif "steps" in chunk:
112
- await msg.stream_token(chunk["steps"][0].observation + "\n\n")
113
- else:
114
- await msg.stream_token("<unammaped chunk>")
115
-
116
- await msg.send()
@@ -1,81 +0,0 @@
1
- import json
2
- import os
3
- import tempfile
4
- from dotenv import load_dotenv
5
-
6
- load_dotenv()
7
-
8
- import chainlit as cl
9
- from langchain.prompts import ChatPromptTemplate
10
- from langchain.schema import HumanMessage
11
- from langchain.schema.runnable.config import RunnableConfig
12
-
13
- from langchain_community.document_loaders import WebBaseLoader
14
- from langchain_community.vectorstores.faiss import FAISS
15
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
16
- from langchain_text_splitters import RecursiveCharacterTextSplitter
17
- from langchain.tools.retriever import create_retriever_tool
18
- from langchain.agents import AgentExecutor, create_tool_calling_agent
19
- from langchain.tools import BaseTool, StructuredTool, tool
20
- from langchain_google_vertexai import ChatVertexAI, VertexAI
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
- retriever,
35
- "langwatch_search",
36
- "Search for information about LangWatch. For any questions about LangWatch, use this tool if you didn't already",
37
- )
38
-
39
- tools = [retriever_tool]
40
- model = ChatVertexAI(model="gemini-pro", streaming=True)
41
- prompt = ChatPromptTemplate.from_messages(
42
- [
43
- (
44
- "system",
45
- "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}",
46
- ),
47
- ("human", "{question}"),
48
- ]
49
- )
50
- agent = create_tool_calling_agent(model, tools, prompt)
51
- executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # type: ignore
52
- cl.user_session.set("agent", executor)
53
-
54
-
55
- @cl.on_message
56
- async def main(message: cl.Message):
57
- agent: AgentExecutor = cl.user_session.get("agent") # type: ignore
58
-
59
- msg = cl.Message(content="")
60
-
61
- async for chunk in agent.astream(
62
- {
63
- "question": message.content,
64
- "messages": [HumanMessage(content="Hoi, dit is een test")],
65
- },
66
- config=RunnableConfig(
67
- callbacks=[
68
- cl.LangchainCallbackHandler(),
69
- ]
70
- ),
71
- ):
72
- if "output" in chunk:
73
- await msg.stream_token(chunk["output"])
74
- elif "actions" in chunk:
75
- await msg.stream_token(chunk["actions"][0].log)
76
- elif "steps" in chunk:
77
- await msg.stream_token(chunk["steps"][0].observation + "\n\n")
78
- else:
79
- await msg.stream_token("<unammaped chunk>")
80
-
81
- await msg.send()
@@ -1,331 +0,0 @@
1
- import os
2
-
3
- os.environ["CHAINLIT_AUTH_SECRET"] = (
4
- "sSgdH4IfqM/%5swBnuwNdZ8rS/VBDW-WiBF?>DW_YPPKm9p9CiO6PPm6Z4Ih7IL"
5
- )
6
-
7
- import datetime
8
- import os.path
9
- import pickle
10
- from typing import Dict, List, Literal, Optional
11
- from dotenv import load_dotenv
12
-
13
- from langwatch.types import RAGChunk
14
-
15
- load_dotenv()
16
-
17
- import chainlit as cl
18
- from langchain.prompts import ChatPromptTemplate
19
- from langchain.schema import HumanMessage
20
- from langchain.schema.runnable.config import RunnableConfig
21
-
22
- import langwatch
23
-
24
- from langchain_community.document_loaders import WebBaseLoader
25
- from langchain_community.vectorstores.faiss import FAISS
26
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
27
- from langchain_text_splitters import RecursiveCharacterTextSplitter
28
- from langchain.tools.retriever import create_retriever_tool
29
- from langchain.agents import AgentExecutor, create_tool_calling_agent
30
- from langchain.tools import BaseTool, StructuredTool, tool
31
- import chainlit as cl
32
- import chainlit.data as cl_data
33
- from chainlit.data.utils import queue_until_user_message
34
- from chainlit.element import Element, ElementDict
35
- from chainlit.socket import persist_user_session
36
- from chainlit.step import StepDict
37
- from chainlit.types import (
38
- Feedback,
39
- PageInfo,
40
- PaginatedResponse,
41
- Pagination,
42
- ThreadDict,
43
- ThreadFilter,
44
- )
45
- from langgraph.graph import StateGraph, START, END, MessagesState
46
- from langgraph.prebuilt import ToolNode
47
- from langgraph.graph.state import CompiledStateGraph
48
-
49
- loader = WebBaseLoader("https://docs.langwatch.ai")
50
- docs = loader.load()
51
- documents = RecursiveCharacterTextSplitter(
52
- chunk_size=1000, chunk_overlap=200
53
- ).split_documents(docs)
54
- vector = FAISS.from_documents(documents, OpenAIEmbeddings())
55
- retriever = vector.as_retriever()
56
-
57
-
58
- now = datetime.datetime.now()
59
-
60
- thread_history = [
61
- {
62
- "id": "test1",
63
- "name": "thread 1",
64
- "createdAt": now,
65
- "userId": "test",
66
- "userIdentifier": "admin",
67
- "steps": [
68
- {
69
- "id": "test1",
70
- "name": "test",
71
- "createdAt": now,
72
- "type": "user_message",
73
- "output": "Message 1",
74
- },
75
- {
76
- "id": "test2",
77
- "name": "test",
78
- "createdAt": now,
79
- "type": "assistant_message",
80
- "output": "Message 2",
81
- },
82
- ],
83
- },
84
- {
85
- "id": "test2",
86
- "createdAt": now,
87
- "userId": "test",
88
- "userIdentifier": "admin",
89
- "name": "thread 2",
90
- "steps": [
91
- {
92
- "id": "test3",
93
- "createdAt": now,
94
- "name": "test",
95
- "type": "user_message",
96
- "output": "Message 3",
97
- },
98
- {
99
- "id": "test4",
100
- "createdAt": now,
101
- "name": "test",
102
- "type": "assistant_message",
103
- "output": "Message 4",
104
- },
105
- ],
106
- },
107
- ]
108
- deleted_thread_ids = []
109
-
110
- THREAD_HISTORY_PICKLE_PATH = os.getenv("THREAD_HISTORY_PICKLE_PATH")
111
- if THREAD_HISTORY_PICKLE_PATH and os.path.exists(THREAD_HISTORY_PICKLE_PATH):
112
- with open(THREAD_HISTORY_PICKLE_PATH, "rb") as f:
113
- thread_history = pickle.load(f)
114
-
115
-
116
- async def save_thread_history():
117
- if THREAD_HISTORY_PICKLE_PATH:
118
- # Force saving of thread history for reload when server restarts
119
- await persist_user_session(
120
- cl.context.session.thread_id, cl.context.session.to_persistable()
121
- )
122
-
123
- with open(THREAD_HISTORY_PICKLE_PATH, "wb") as out_file:
124
- pickle.dump(thread_history, out_file)
125
-
126
-
127
- class TestDataLayer(cl_data.base.BaseDataLayer):
128
- async def get_user(self, identifier: str):
129
- return cl.PersistedUser(
130
- id="test", createdAt=now.isoformat(), identifier=identifier
131
- )
132
-
133
- async def create_user(self, user: cl.User):
134
- return cl.PersistedUser(
135
- id="test", createdAt=now.isoformat(), identifier=user.identifier
136
- )
137
-
138
- async def update_thread(
139
- self,
140
- thread_id: str,
141
- name: Optional[str] = None,
142
- user_id: Optional[str] = None,
143
- metadata: Optional[Dict] = None,
144
- tags: Optional[List[str]] = None,
145
- ):
146
- thread = next((t for t in thread_history if t["id"] == thread_id), None)
147
- if thread:
148
- if name:
149
- thread["name"] = name
150
- if metadata:
151
- thread["metadata"] = metadata
152
- if tags:
153
- thread["tags"] = tags
154
- else:
155
- thread_history.append(
156
- {
157
- "id": thread_id,
158
- "name": name,
159
- "metadata": metadata,
160
- "tags": tags,
161
- "createdAt": now.isoformat(),
162
- "userId": user_id,
163
- "userIdentifier": "admin",
164
- "steps": [],
165
- }
166
- )
167
-
168
- @cl_data.queue_until_user_message()
169
- async def create_step(self, step_dict: StepDict):
170
- thread = next(
171
- (t for t in thread_history if t["id"] == step_dict.get("threadId")), None
172
- )
173
- if thread:
174
- thread["steps"].append(step_dict)
175
-
176
- async def get_thread_author(self, thread_id: str):
177
- return "admin"
178
-
179
- async def list_threads(
180
- self, pagination: Pagination, filters: ThreadFilter
181
- ) -> PaginatedResponse[ThreadDict]:
182
- return PaginatedResponse(
183
- data=[t for t in thread_history if t["id"] not in deleted_thread_ids],
184
- pageInfo=PageInfo(hasNextPage=False, startCursor=None, endCursor=None),
185
- ) # type: ignore
186
-
187
- async def get_thread(self, thread_id: str):
188
- thread = next((t for t in thread_history if t["id"] == thread_id), None)
189
- if not thread:
190
- return None
191
- thread["steps"] = sorted(thread["steps"], key=lambda x: x["createdAt"])
192
- return thread
193
-
194
- async def delete_thread(self, thread_id: str):
195
- deleted_thread_ids.append(thread_id)
196
-
197
- async def delete_feedback(
198
- self,
199
- feedback_id: str,
200
- ) -> bool:
201
- return True
202
-
203
- async def upsert_feedback(
204
- self,
205
- feedback: Feedback,
206
- ) -> str:
207
- return ""
208
-
209
- @queue_until_user_message()
210
- async def create_element(self, element: "Element"):
211
- pass
212
-
213
- async def get_element(
214
- self, thread_id: str, element_id: str
215
- ) -> Optional["ElementDict"]:
216
- pass
217
-
218
- @queue_until_user_message()
219
- async def delete_element(self, element_id: str, thread_id: Optional[str] = None):
220
- pass
221
-
222
- @queue_until_user_message()
223
- async def update_step(self, step_dict: "StepDict"):
224
- pass
225
-
226
- @queue_until_user_message()
227
- async def delete_step(self, step_id: str):
228
- pass
229
-
230
- async def build_debug_url(self) -> str:
231
- return ""
232
-
233
-
234
- cl_data._data_layer = TestDataLayer()
235
-
236
-
237
- retriever_tool = create_retriever_tool(
238
- langwatch.langchain.capture_rag_from_retriever(
239
- retriever,
240
- lambda document: RAGChunk(
241
- document_id=document.metadata["source"], content=document.page_content
242
- ),
243
- ),
244
- "langwatch_search",
245
- "Search for information about LangWatch. For any questions about LangWatch, use this tool if you didn't already",
246
- )
247
-
248
- tools = [retriever_tool]
249
- tool_node = ToolNode(tools)
250
- model = ChatOpenAI(streaming=True).bind_tools(tools)
251
-
252
-
253
- def should_continue(state: MessagesState):
254
- messages = state["messages"]
255
- last_message = messages[-1]
256
- # If the LLM makes a tool call, then we route to the "tools" node
257
- if last_message.tool_calls: # type: ignore
258
- return "tools"
259
- return END
260
-
261
-
262
- def call_model(state):
263
- messages = state["messages"]
264
- response = model.invoke(messages)
265
- # We return a list, because this will get added to the existing list
266
- return {"messages": [response]}
267
-
268
-
269
- # Define the graph
270
- workflow = StateGraph(MessagesState)
271
-
272
- workflow.add_node("agent", call_model)
273
- workflow.add_node("tools", tool_node)
274
-
275
- workflow.add_edge(START, "agent")
276
- workflow.add_conditional_edges("agent", should_continue)
277
- workflow.add_edge("tools", "agent")
278
-
279
- # Compile the graph
280
- app = workflow.compile()
281
-
282
-
283
- @cl.on_message
284
- @langwatch.trace()
285
- async def main(message: cl.Message):
286
- msg = cl.Message(content="")
287
-
288
- langwatch.get_current_trace().update(
289
- metadata={
290
- "labels": ["langchain", "rag", "tools"],
291
- "user_id": getattr(cl.user_session.get("user"), "identifier", "unknown"),
292
- "thread_id": cl.context.session.thread_id,
293
- }
294
- )
295
-
296
- async for event in app.astream(
297
- {"messages": [HumanMessage(content=message.content)]},
298
- config=RunnableConfig(
299
- callbacks=[
300
- cl.LangchainCallbackHandler(),
301
- langwatch.get_current_trace().get_langchain_callback(),
302
- ]
303
- ),
304
- ):
305
- if "agent" in event:
306
- if "messages" in event["agent"]:
307
- for message in event["agent"]["messages"]:
308
- await msg.stream_token(message.content)
309
-
310
- await msg.send()
311
-
312
- await save_thread_history()
313
-
314
-
315
- @cl.password_auth_callback
316
- async def auth_callback(username: str, password: str) -> Optional[cl.User]:
317
- if (username, password) == ("admin", "admin"):
318
- return cl.User(identifier="admin")
319
- else:
320
- return None
321
-
322
-
323
- @cl.on_chat_resume
324
- async def on_chat_resume(thread: ThreadDict):
325
- await cl.Message(f"Welcome back to {thread['name']}").send()
326
- if "metadata" in thread and thread["metadata"]:
327
- await cl.Message(thread["metadata"], author="metadata", language="json").send()
328
- if "tags" in thread and thread["tags"]:
329
- await cl.Message(
330
- ",".join(thread["tags"]), author="tags", language="json"
331
- ).send()
@@ -1,106 +0,0 @@
1
- import os
2
-
3
- os.environ["CHAINLIT_AUTH_SECRET"] = (
4
- "sSgdH4IfqM/%5swBnuwNdZ8rS/VBDW-WiBF?>DW_YPPKm9p9CiO6PPm6Z4Ih7IL"
5
- )
6
-
7
- import datetime
8
- import os.path
9
- import pickle
10
- from typing import Dict, List, Literal, Optional
11
- from dotenv import load_dotenv
12
-
13
- load_dotenv()
14
-
15
- import chainlit as cl
16
- from langchain.prompts import ChatPromptTemplate
17
- from langchain.schema import HumanMessage
18
- from langchain.schema.runnable.config import RunnableConfig
19
-
20
- from langchain_community.document_loaders import WebBaseLoader
21
- from langchain_community.vectorstores.faiss import FAISS
22
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
23
- from langchain_text_splitters import RecursiveCharacterTextSplitter
24
- from langchain.tools.retriever import create_retriever_tool
25
- from langchain.agents import AgentExecutor, create_tool_calling_agent
26
- from langchain.tools import BaseTool, StructuredTool, tool
27
- import chainlit as cl
28
- import chainlit.data as cl_data
29
- from chainlit.data.utils import queue_until_user_message
30
- from chainlit.element import Element, ElementDict
31
- from chainlit.socket import persist_user_session
32
- from chainlit.step import StepDict
33
- from chainlit.types import (
34
- Feedback,
35
- PageInfo,
36
- PaginatedResponse,
37
- Pagination,
38
- ThreadDict,
39
- ThreadFilter,
40
- )
41
- from langgraph.graph import StateGraph, START, END, MessagesState
42
- from langgraph.prebuilt import ToolNode
43
- from langgraph.graph.state import CompiledStateGraph
44
-
45
- loader = WebBaseLoader("https://docs.langwatch.ai")
46
- docs = loader.load()
47
- documents = RecursiveCharacterTextSplitter(
48
- chunk_size=1000, chunk_overlap=200
49
- ).split_documents(docs)
50
- vector = FAISS.from_documents(documents, OpenAIEmbeddings())
51
- retriever = vector.as_retriever()
52
-
53
-
54
- @cl.on_chat_start
55
- async def on_chat_start():
56
- retriever_tool = create_retriever_tool(
57
- retriever,
58
- "langwatch_search",
59
- "Search for information about LangWatch. For any questions about LangWatch, use this tool if you didn't already",
60
- )
61
-
62
- tools = [retriever_tool]
63
- model = ChatOpenAI(model="gpt-5", streaming=True)
64
-
65
- # Create LangGraph workflow
66
- def should_continue(state: MessagesState) -> Literal["tools", END]:
67
- messages = state['messages']
68
- last_message = messages[-1]
69
- if last_message.tool_calls:
70
- return "tools"
71
- return END
72
-
73
- def call_model(state: MessagesState):
74
- messages = state['messages']
75
- response = model.invoke(messages)
76
- return {"messages": [response]}
77
-
78
- workflow = StateGraph(MessagesState)
79
- workflow.add_node("agent", call_model)
80
- workflow.add_node("tools", ToolNode(tools))
81
- workflow.add_edge(START, "agent")
82
- workflow.add_conditional_edges("agent", should_continue)
83
- workflow.add_edge("tools", "agent")
84
-
85
- app = workflow.compile()
86
- cl.user_session.set("agent", app)
87
-
88
-
89
- @cl.on_message
90
- async def main(message: cl.Message):
91
- agent: CompiledStateGraph = cl.user_session.get("agent") # type: ignore
92
-
93
- msg = cl.Message(content="")
94
-
95
- async for chunk in agent.astream(
96
- {"messages": [HumanMessage(content=message.content)]},
97
- config=RunnableConfig(
98
- callbacks=[
99
- cl.LangchainCallbackHandler(),
100
- ]
101
- ),
102
- ):
103
- if "agent" in chunk:
104
- await msg.stream_token(chunk["agent"]["messages"][-1].content)
105
-
106
- await msg.send()
@@ -1,40 +0,0 @@
1
- from typing import cast
2
- from dotenv import load_dotenv
3
-
4
- load_dotenv()
5
-
6
- import chainlit as cl
7
- import litellm
8
- from litellm import CustomStreamWrapper
9
- from litellm.types.utils import StreamingChoices
10
-
11
- import langwatch
12
-
13
-
14
- @cl.on_message
15
- @langwatch.trace()
16
- async def main(message: cl.Message):
17
- langwatch.get_current_trace().autotrack_litellm_calls(litellm)
18
-
19
- msg = cl.Message(
20
- content="",
21
- )
22
-
23
- response = litellm.completion(
24
- model="cerebras/gpt-oss-120b",
25
- messages=[
26
- {
27
- "role": "system",
28
- "content": "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis.",
29
- },
30
- {"role": "user", "content": message.content},
31
- ],
32
- stream=True,
33
- stream_options={"include_usage": True},
34
- )
35
-
36
- for part in cast(CustomStreamWrapper, response):
37
- if token := cast(StreamingChoices, part.choices[0]).delta.content or "":
38
- await msg.stream_token(token)
39
-
40
- await msg.update()