langflow-base-nightly 0.5.0.dev29__py3-none-any.whl → 0.5.0.dev31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langflow/api/router.py +2 -0
- langflow/api/v1/__init__.py +2 -0
- langflow/api/v1/knowledge_bases.py +437 -0
- langflow/base/data/kb_utils.py +104 -0
- langflow/base/models/openai_constants.py +29 -0
- langflow/components/data/__init__.py +4 -0
- langflow/components/data/kb_ingest.py +585 -0
- langflow/components/data/kb_retrieval.py +254 -0
- langflow/frontend/assets/{SlackIcon-D2PxMQjX.js → SlackIcon-Bikuxo8x.js} +1 -1
- langflow/frontend/assets/{Wikipedia-BNM0lBPs.js → Wikipedia-B6aCFf5-.js} +1 -1
- langflow/frontend/assets/{Wolfram-COQyGyeC.js → Wolfram-CekL_M-a.js} +1 -1
- langflow/frontend/assets/{index-CTpfN0Cy.js → index-09CVJwsY.js} +1 -1
- langflow/frontend/assets/{index-DWUG3nTC.js → index-1MEYR1La.js} +1 -1
- langflow/frontend/assets/{index-Ds9y6kEK.js → index-2vQdFIK_.js} +1 -1
- langflow/frontend/assets/{index-DRdKSzTn.js → index-4Tl3Nxdo.js} +1 -1
- langflow/frontend/assets/{index-O_vPh7iD.js → index-5G402gB8.js} +1 -1
- langflow/frontend/assets/{index-D15h4ir2.js → index-5hW8VleF.js} +1 -1
- langflow/frontend/assets/{index-BydnMWnM.js → index-6GWpsedd.js} +1 -1
- langflow/frontend/assets/{index-4vIU43o6.js → index-7x3wNZ-4.js} +1 -1
- langflow/frontend/assets/{index-DrFpyu9Z.js → index-9gkURvG2.js} +1 -1
- langflow/frontend/assets/{index-DRe5h2N_.js → index-AOX7bbjJ.js} +1 -1
- langflow/frontend/assets/{index-fJyq3ZWN.js → index-B20KmxhS.js} +1 -1
- langflow/frontend/assets/{index-D_sHnnuS.js → index-B2EmwqKj.js} +1 -1
- langflow/frontend/assets/{index-DEc_2ba8.js → index-B4AtFbkN.js} +1 -1
- langflow/frontend/assets/{index-D_zQiboE.js → index-B4xLpgbM.js} +1 -1
- langflow/frontend/assets/{index-Db8Xgs-K.js → index-B9KRIJFi.js} +1 -1
- langflow/frontend/assets/{index-BzCZNz2f.js → index-B9uOBe6Y.js} +1 -1
- langflow/frontend/assets/{index-pFTvwRsJ.js → index-BDmbsLY2.js} +1 -1
- langflow/frontend/assets/{index-CGef2axA.js → index-BIKbxmIh.js} +1 -1
- langflow/frontend/assets/{index-BTl_mLju.js → index-BIjUtp6d.js} +1 -1
- langflow/frontend/assets/{index-Jze67eTW.js → index-BJIsQS8D.js} +1 -1
- langflow/frontend/assets/{index-DV-gdr7l.js → index-BO4fl1uU.js} +1 -1
- langflow/frontend/assets/{index-BUVmswbg.js → index-BRE8A4Q_.js} +1 -1
- langflow/frontend/assets/{index-CTzWsu8S.js → index-BRNhftot.js} +1 -1
- langflow/frontend/assets/{index-DFYBo38q.js → index-BRizlHaN.js} +1 -1
- langflow/frontend/assets/{index-DbPP5vss.js → index-BRwkzs92.js} +1 -1
- langflow/frontend/assets/{index-BzE7oL1n.js → index-BZCt_UnJ.js} +1 -1
- langflow/frontend/assets/{index-BhRSkpxu.js → index-B_ytx_iA.js} +1 -1
- langflow/frontend/assets/{index-ByCunkn4.js → index-BcqeL_f4.js} +1 -1
- langflow/frontend/assets/{index-CAAZbdRp.js → index-Bgd7yLoW.js} +1 -1
- langflow/frontend/assets/{index-DpDbxNdQ.js → index-BlRTHXW5.js} +1 -1
- langflow/frontend/assets/{index-jXSPQ_JS.js → index-BllNr21U.js} +1 -1
- langflow/frontend/assets/{index-fpMcQS2L.js → index-Bm7a2vMS.js} +1 -1
- langflow/frontend/assets/{index-BFQzmLDT.js → index-Bn4HAVDG.js} +1 -1
- langflow/frontend/assets/{index-D8EpAMC3.js → index-BwlYjc56.js} +1 -1
- langflow/frontend/assets/{index-BcCN9mpu.js → index-BzCjyHto.js} +1 -1
- langflow/frontend/assets/{index-D6-jZ4sc.js → index-C3RZz8WE.js} +1 -1
- langflow/frontend/assets/{index-D66JmFlL.js → index-C69gdJqw.js} +1 -1
- langflow/frontend/assets/{index-pYD0BTGu.js → index-C6P0vvSP.js} +1 -1
- langflow/frontend/assets/{index-CIjw_ZkP.js → index-C7wDSVVH.js} +1 -1
- langflow/frontend/assets/{index-BCTEK38J.js → index-CAzSTGAM.js} +1 -1
- langflow/frontend/assets/{index-8FjgS_Vj.js → index-CEn_71Wk.js} +1 -1
- langflow/frontend/assets/{index-BFiCUM5l.js → index-CGVDXKtN.js} +1 -1
- langflow/frontend/assets/{index-BIH2K0v8.js → index-CIYzjH2y.js} +1 -1
- langflow/frontend/assets/{index-gM8j2Wvk.js → index-COqjpsdy.js} +1 -1
- langflow/frontend/assets/{index-2q8IFBNP.js → index-CP0tFKwN.js} +1 -1
- langflow/frontend/assets/{index-CXpZa4H9.js → index-CPIdMJkX.js} +1 -1
- langflow/frontend/assets/{index-B-YjnRWx.js → index-CSRizl2S.js} +1 -1
- langflow/frontend/assets/{index-DFo0yfS5.js → index-CUe1ivTn.js} +1 -1
- langflow/frontend/assets/{index-C2x5hzgY.js → index-CVphnxXi.js} +1 -1
- langflow/frontend/assets/{index-Bz3QnhLZ.js → index-CY6LUi4V.js} +1 -1
- langflow/frontend/assets/{index-Cq6gk34q.js → index-C_2G2ZqJ.js} +1 -1
- langflow/frontend/assets/{index-CSXUVElo.js → index-C_K6Tof7.js} +1 -1
- langflow/frontend/assets/{index-1D7jZ8vz.js → index-C_UkF-RJ.js} +1 -1
- langflow/frontend/assets/{index-BVGZcHHC.js → index-Cbwk3f-p.js} +1 -1
- langflow/frontend/assets/{index-kiqvo0Zi.js → index-CdwjD4IX.js} +1 -1
- langflow/frontend/assets/{index-BNy3Al2s.js → index-CgbINWS8.js} +1 -1
- langflow/frontend/assets/{index-BXJpd9hg.js → index-CglSqvB5.js} +1 -1
- langflow/frontend/assets/{index-D9CF_54p.js → index-CmiRgF_-.js} +1 -1
- langflow/frontend/assets/{index-ez1EW657.js → index-Cp7Pmn03.js} +1 -1
- langflow/frontend/assets/{index-aypzjPzG.js → index-Cq30cQcP.js} +1 -1
- langflow/frontend/assets/index-CqS7zir1.css +1 -0
- langflow/frontend/assets/{index-DKv0y9Dp.js → index-Cr2oy5K2.js} +1 -1
- langflow/frontend/assets/{index-DrfwVxtD.js → index-Crq_yhkG.js} +1 -1
- langflow/frontend/assets/{index-CzJzRS6i.js → index-Cs_jt3dj.js} +1 -1
- langflow/frontend/assets/{index-DO0mS8FQ.js → index-Cy-ZEfWh.js} +1 -1
- langflow/frontend/assets/{index-Q0bwuTZY.js → index-Cyk3aCmP.js} +1 -1
- langflow/frontend/assets/{index-DToZROdu.js → index-D-HTZ68O.js} +1 -1
- langflow/frontend/assets/{index-C0AEZF1v.js → index-D1RgjMON.js} +1 -1
- langflow/frontend/assets/{index-DilRRF2S.js → index-D29n5mus.js} +1 -1
- langflow/frontend/assets/{index-CKLOrtrx.js → index-D2nHdRne.js} +1 -1
- langflow/frontend/assets/{index-sfFDGjjd.js → index-D7Vx6mgS.js} +1 -1
- langflow/frontend/assets/{index-BAHhLqW9.js → index-D7nFs6oq.js} +1 -1
- langflow/frontend/assets/{index-C7jY4x98.js → index-DAJafn16.js} +1 -1
- langflow/frontend/assets/{index-BefwTGbP.js → index-DDcpxWU4.js} +1 -1
- langflow/frontend/assets/{index-CTZ9iXFr.js → index-DEuXrfXH.js} +1 -1
- langflow/frontend/assets/{index-DFfr0xSt.js → index-DF0oWRdd.js} +1 -1
- langflow/frontend/assets/{index-Bh5pQAZC.js → index-DI0zAExi.js} +1 -1
- langflow/frontend/assets/{index-CG-Suo0F.js → index-DJs6FoYC.js} +1 -1
- langflow/frontend/assets/{index-dvTTQhKz.js → index-DNS4La1f.js} +1 -1
- langflow/frontend/assets/{index-nLDaeeZg.js → index-DOI0ceS-.js} +1 -1
- langflow/frontend/assets/{index-DakdEtbq.js → index-DOb9c2bf.js} +1 -1
- langflow/frontend/assets/{index-CEVnRp4_.js → index-DS4F_Phe.js} +1 -1
- langflow/frontend/assets/{index-DGRg2M1l.js → index-DTJX3yQa.js} +1 -1
- langflow/frontend/assets/{index-BjAsd-Vo.js → index-DVV_etfW.js} +1 -1
- langflow/frontend/assets/{index-BrIuZD2A.js → index-DX_InNVT.js} +1 -1
- langflow/frontend/assets/{index-jG-zLXRN.js → index-DbmqjLy6.js} +1 -1
- langflow/frontend/assets/{index-DSvOFGJR.js → index-Dc0p1Oxl.js} +1 -1
- langflow/frontend/assets/{index-87GFtXu5.js → index-DkJCCraf.js} +1 -1
- langflow/frontend/assets/{index-BXidWkLM.js → index-DlMAYATX.js} +1 -1
- langflow/frontend/assets/{index-sbTxhltT.js → index-DmaQAn3K.js} +1 -1
- langflow/frontend/assets/{index-DkC5vMvx.js → index-DmvjdU1N.js} +1 -1
- langflow/frontend/assets/{index-CSUglByd.js → index-DnusMCK1.js} +1 -1
- langflow/frontend/assets/{index-DZOTHXs0.js → index-DoFlaGDx.js} +1 -1
- langflow/frontend/assets/{index-CZkMjaa8.js → index-DqDQk0Cu.js} +1 -1
- langflow/frontend/assets/{index-lc10GnwG.js → index-DrvRK4_i.js} +1 -1
- langflow/frontend/assets/{index-BNm-yAYc.js → index-DtCsjX48.js} +1 -1
- langflow/frontend/assets/{index-BeLnhfG-.js → index-Dy7ehgeV.js} +1 -1
- langflow/frontend/assets/{index-RGG9hk9J.js → index-Dz0r9Idb.js} +1 -1
- langflow/frontend/assets/{index-Bcq2yA-p.js → index-DzDNhMMW.js} +1 -1
- langflow/frontend/assets/{index-P3f-GeAm.js → index-FYcoJPMP.js} +1 -1
- langflow/frontend/assets/{index-DQwvl_Rp.js → index-Iamzh9ZT.js} +1 -1
- langflow/frontend/assets/{index-Cy6n8tA9.js → index-J0pvFqLk.js} +1 -1
- langflow/frontend/assets/{index-D1XTMye3.js → index-J98sU-1p.js} +1 -1
- langflow/frontend/assets/{index-BZ0rL0tK.js → index-JHCxbvlW.js} +1 -1
- langflow/frontend/assets/{index-DmSH63k1.js → index-KnS52ylc.js} +1 -1
- langflow/frontend/assets/{index-WGZ88ShH.js → index-L7FKc9QN.js} +1 -1
- langflow/frontend/assets/{index-BIoFnUtx.js → index-RveG4dl9.js} +1 -1
- langflow/frontend/assets/{index-BDdkPrzu.js → index-T2jJOG85.js} +1 -1
- langflow/frontend/assets/{index-2839k6WO.js → index-TRyDa01A.js} +1 -1
- langflow/frontend/assets/{index-DvOdMz35.js → index-U7J1YiWE.js} +1 -1
- langflow/frontend/assets/{index-DzUx1-Bl.js → index-UI2ws3qp.js} +1984 -1984
- langflow/frontend/assets/{index-8Fx5I2fx.js → index-VO-pk-Hg.js} +1 -1
- langflow/frontend/assets/{index-e-RKmhti.js → index-_3qag0I4.js} +1 -1
- langflow/frontend/assets/{index-X67tRPXo.js → index-dfaj9-hY.js} +1 -1
- langflow/frontend/assets/{index-CHexGuNQ.js → index-eJwu5YEi.js} +1 -1
- langflow/frontend/assets/{index-Dz5YIK1W.js → index-in188l0A.js} +1 -1
- langflow/frontend/assets/{index-CTwkLLMr.js → index-pkOi9P45.js} +1 -1
- langflow/frontend/assets/{index-D6BaTmee.js → index-qXcoVIRo.js} +1 -1
- langflow/frontend/assets/{index-euS8RcNY.js → index-xVx59Op-.js} +1 -1
- langflow/frontend/assets/{index-C4WueQ4k.js → index-yIh6-LZT.js} +1 -1
- langflow/frontend/assets/lazyIconImports-kvf_Kak2.js +2 -0
- langflow/frontend/assets/{use-post-add-user-CA-_peAV.js → use-post-add-user-Bt6vZvvT.js} +1 -1
- langflow/frontend/index.html +2 -2
- langflow/initial_setup/starter_projects/Knowledge Ingestion.json +1052 -0
- langflow/initial_setup/starter_projects/Knowledge Retrieval.json +707 -0
- langflow/services/settings/base.py +3 -0
- {langflow_base_nightly-0.5.0.dev29.dist-info → langflow_base_nightly-0.5.0.dev31.dist-info}/METADATA +2 -1
- {langflow_base_nightly-0.5.0.dev29.dist-info → langflow_base_nightly-0.5.0.dev31.dist-info}/RECORD +141 -135
- langflow/frontend/assets/index-DIcdzk44.css +0 -1
- langflow/frontend/assets/lazyIconImports-lnczjBhY.js +0 -2
- {langflow_base_nightly-0.5.0.dev29.dist-info → langflow_base_nightly-0.5.0.dev31.dist-info}/WHEEL +0 -0
- {langflow_base_nightly-0.5.0.dev29.dist-info → langflow_base_nightly-0.5.0.dev31.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,707 @@
|
|
|
1
|
+
{
|
|
2
|
+
"data": {
|
|
3
|
+
"edges": [
|
|
4
|
+
{
|
|
5
|
+
"className": "",
|
|
6
|
+
"data": {
|
|
7
|
+
"sourceHandle": {
|
|
8
|
+
"dataType": "TextInput",
|
|
9
|
+
"id": "TextInput-Z3rM3",
|
|
10
|
+
"name": "text",
|
|
11
|
+
"output_types": [
|
|
12
|
+
"Message"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"targetHandle": {
|
|
16
|
+
"fieldName": "search_query",
|
|
17
|
+
"id": "KBRetrieval-tGoBR",
|
|
18
|
+
"inputTypes": [
|
|
19
|
+
"Message"
|
|
20
|
+
],
|
|
21
|
+
"type": "str"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"id": "xy-edge__TextInput-Z3rM3{œdataTypeœ:œTextInputœ,œidœ:œTextInput-Z3rM3œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-KBRetrieval-tGoBR{œfieldNameœ:œsearch_queryœ,œidœ:œKBRetrieval-tGoBRœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
|
|
25
|
+
"source": "TextInput-Z3rM3",
|
|
26
|
+
"sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-Z3rM3œ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}",
|
|
27
|
+
"target": "KBRetrieval-tGoBR",
|
|
28
|
+
"targetHandle": "{œfieldNameœ: œsearch_queryœ, œidœ: œKBRetrieval-tGoBRœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"className": "",
|
|
32
|
+
"data": {
|
|
33
|
+
"sourceHandle": {
|
|
34
|
+
"dataType": "KBRetrieval",
|
|
35
|
+
"id": "KBRetrieval-tGoBR",
|
|
36
|
+
"name": "chroma_kb_data",
|
|
37
|
+
"output_types": [
|
|
38
|
+
"DataFrame"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"targetHandle": {
|
|
42
|
+
"fieldName": "input_value",
|
|
43
|
+
"id": "ChatOutput-tixOe",
|
|
44
|
+
"inputTypes": [
|
|
45
|
+
"Data",
|
|
46
|
+
"DataFrame",
|
|
47
|
+
"Message"
|
|
48
|
+
],
|
|
49
|
+
"type": "other"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"id": "xy-edge__KBRetrieval-tGoBR{œdataTypeœ:œKBRetrievalœ,œidœ:œKBRetrieval-tGoBRœ,œnameœ:œchroma_kb_dataœ,œoutput_typesœ:[œDataFrameœ]}-ChatOutput-tixOe{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-tixOeœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}",
|
|
53
|
+
"source": "KBRetrieval-tGoBR",
|
|
54
|
+
"sourceHandle": "{œdataTypeœ: œKBRetrievalœ, œidœ: œKBRetrieval-tGoBRœ, œnameœ: œchroma_kb_dataœ, œoutput_typesœ: [œDataFrameœ]}",
|
|
55
|
+
"target": "ChatOutput-tixOe",
|
|
56
|
+
"targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-tixOeœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œotherœ}"
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"nodes": [
|
|
60
|
+
{
|
|
61
|
+
"data": {
|
|
62
|
+
"id": "note-YyBfz",
|
|
63
|
+
"node": {
|
|
64
|
+
"description": "## Knowledge Retrieval\n\nA stand-alone component handles the retrieval of ingested knowledge from existing knowledge bases. To retrieve knowledge:\n\n1. Select your knowledge base from the Knowledge Base dropdown. If you do not see it, choose \"Refresh List\".\n2. (Optional) Enter a Search Query to be performed against the knowledge base.\n\nNote that by default, 5 results are returned, which can be configured by clicking Controls at the top of the component.\n",
|
|
65
|
+
"display_name": "",
|
|
66
|
+
"documentation": "",
|
|
67
|
+
"template": {}
|
|
68
|
+
},
|
|
69
|
+
"type": "note"
|
|
70
|
+
},
|
|
71
|
+
"dragging": false,
|
|
72
|
+
"height": 384,
|
|
73
|
+
"id": "note-YyBfz",
|
|
74
|
+
"measured": {
|
|
75
|
+
"height": 384,
|
|
76
|
+
"width": 371
|
|
77
|
+
},
|
|
78
|
+
"position": {
|
|
79
|
+
"x": -215.63964109627526,
|
|
80
|
+
"y": -365.1224988685513
|
|
81
|
+
},
|
|
82
|
+
"resizing": false,
|
|
83
|
+
"selected": false,
|
|
84
|
+
"type": "noteNode",
|
|
85
|
+
"width": 371
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"data": {
|
|
89
|
+
"id": "TextInput-Z3rM3",
|
|
90
|
+
"node": {
|
|
91
|
+
"base_classes": [
|
|
92
|
+
"Message"
|
|
93
|
+
],
|
|
94
|
+
"beta": false,
|
|
95
|
+
"conditional_paths": [],
|
|
96
|
+
"custom_fields": {},
|
|
97
|
+
"description": "Get user text inputs.",
|
|
98
|
+
"display_name": "Text Input",
|
|
99
|
+
"documentation": "https://docs.langflow.org/components-io#text-input",
|
|
100
|
+
"edited": false,
|
|
101
|
+
"field_order": [
|
|
102
|
+
"input_value"
|
|
103
|
+
],
|
|
104
|
+
"frozen": false,
|
|
105
|
+
"icon": "type",
|
|
106
|
+
"legacy": false,
|
|
107
|
+
"lf_version": "1.5.0.post1",
|
|
108
|
+
"metadata": {
|
|
109
|
+
"code_hash": "efdcba3771af",
|
|
110
|
+
"module": "langflow.components.input_output.text.TextInputComponent"
|
|
111
|
+
},
|
|
112
|
+
"minimized": false,
|
|
113
|
+
"output_types": [],
|
|
114
|
+
"outputs": [
|
|
115
|
+
{
|
|
116
|
+
"allows_loop": false,
|
|
117
|
+
"cache": true,
|
|
118
|
+
"display_name": "Output Text",
|
|
119
|
+
"group_outputs": false,
|
|
120
|
+
"method": "text_response",
|
|
121
|
+
"name": "text",
|
|
122
|
+
"selected": "Message",
|
|
123
|
+
"tool_mode": true,
|
|
124
|
+
"types": [
|
|
125
|
+
"Message"
|
|
126
|
+
],
|
|
127
|
+
"value": "__UNDEFINED__"
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"pinned": false,
|
|
131
|
+
"template": {
|
|
132
|
+
"_type": "Component",
|
|
133
|
+
"code": {
|
|
134
|
+
"advanced": true,
|
|
135
|
+
"dynamic": true,
|
|
136
|
+
"fileTypes": [],
|
|
137
|
+
"file_path": "",
|
|
138
|
+
"info": "",
|
|
139
|
+
"list": false,
|
|
140
|
+
"load_from_db": false,
|
|
141
|
+
"multiline": true,
|
|
142
|
+
"name": "code",
|
|
143
|
+
"password": false,
|
|
144
|
+
"placeholder": "",
|
|
145
|
+
"required": true,
|
|
146
|
+
"show": true,
|
|
147
|
+
"title_case": false,
|
|
148
|
+
"type": "code",
|
|
149
|
+
"value": "from langflow.base.io.text import TextComponent\nfrom langflow.io import MultilineInput, Output\nfrom langflow.schema.message import Message\n\n\nclass TextInputComponent(TextComponent):\n display_name = \"Text Input\"\n description = \"Get user text inputs.\"\n documentation: str = \"https://docs.langflow.org/components-io#text-input\"\n icon = \"type\"\n name = \"TextInput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Text to be passed as input.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Output Text\", name=\"text\", method=\"text_response\"),\n ]\n\n def text_response(self) -> Message:\n return Message(\n text=self.input_value,\n )\n"
|
|
150
|
+
},
|
|
151
|
+
"input_value": {
|
|
152
|
+
"_input_type": "MultilineInput",
|
|
153
|
+
"advanced": false,
|
|
154
|
+
"copy_field": false,
|
|
155
|
+
"display_name": "Text",
|
|
156
|
+
"dynamic": false,
|
|
157
|
+
"info": "Text to be passed as input.",
|
|
158
|
+
"input_types": [
|
|
159
|
+
"Message"
|
|
160
|
+
],
|
|
161
|
+
"list": false,
|
|
162
|
+
"list_add_label": "Add More",
|
|
163
|
+
"load_from_db": false,
|
|
164
|
+
"multiline": true,
|
|
165
|
+
"name": "input_value",
|
|
166
|
+
"placeholder": "",
|
|
167
|
+
"required": false,
|
|
168
|
+
"show": true,
|
|
169
|
+
"title_case": false,
|
|
170
|
+
"tool_mode": false,
|
|
171
|
+
"trace_as_input": true,
|
|
172
|
+
"trace_as_metadata": true,
|
|
173
|
+
"type": "str",
|
|
174
|
+
"value": "IBM Acquires DataStax"
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"tool_mode": false
|
|
178
|
+
},
|
|
179
|
+
"showNode": true,
|
|
180
|
+
"type": "TextInput"
|
|
181
|
+
},
|
|
182
|
+
"dragging": false,
|
|
183
|
+
"id": "TextInput-Z3rM3",
|
|
184
|
+
"measured": {
|
|
185
|
+
"height": 204,
|
|
186
|
+
"width": 320
|
|
187
|
+
},
|
|
188
|
+
"position": {
|
|
189
|
+
"x": 234.35280633316273,
|
|
190
|
+
"y": -280.9003423728733
|
|
191
|
+
},
|
|
192
|
+
"selected": false,
|
|
193
|
+
"type": "genericNode"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"data": {
|
|
197
|
+
"id": "ChatOutput-tixOe",
|
|
198
|
+
"node": {
|
|
199
|
+
"base_classes": [
|
|
200
|
+
"Message"
|
|
201
|
+
],
|
|
202
|
+
"beta": false,
|
|
203
|
+
"conditional_paths": [],
|
|
204
|
+
"custom_fields": {},
|
|
205
|
+
"description": "Display a chat message in the Playground.",
|
|
206
|
+
"display_name": "Chat Output",
|
|
207
|
+
"documentation": "https://docs.langflow.org/components-io#chat-output",
|
|
208
|
+
"edited": false,
|
|
209
|
+
"field_order": [
|
|
210
|
+
"input_value",
|
|
211
|
+
"should_store_message",
|
|
212
|
+
"sender",
|
|
213
|
+
"sender_name",
|
|
214
|
+
"session_id",
|
|
215
|
+
"data_template",
|
|
216
|
+
"background_color",
|
|
217
|
+
"chat_icon",
|
|
218
|
+
"text_color",
|
|
219
|
+
"clean_data"
|
|
220
|
+
],
|
|
221
|
+
"frozen": false,
|
|
222
|
+
"icon": "MessagesSquare",
|
|
223
|
+
"legacy": false,
|
|
224
|
+
"lf_version": "1.5.0.post1",
|
|
225
|
+
"metadata": {
|
|
226
|
+
"code_hash": "6f74e04e39d5",
|
|
227
|
+
"module": "langflow.components.input_output.chat_output.ChatOutput"
|
|
228
|
+
},
|
|
229
|
+
"minimized": true,
|
|
230
|
+
"output_types": [],
|
|
231
|
+
"outputs": [
|
|
232
|
+
{
|
|
233
|
+
"allows_loop": false,
|
|
234
|
+
"cache": true,
|
|
235
|
+
"display_name": "Output Message",
|
|
236
|
+
"group_outputs": false,
|
|
237
|
+
"method": "message_response",
|
|
238
|
+
"name": "message",
|
|
239
|
+
"selected": "Message",
|
|
240
|
+
"tool_mode": true,
|
|
241
|
+
"types": [
|
|
242
|
+
"Message"
|
|
243
|
+
],
|
|
244
|
+
"value": "__UNDEFINED__"
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"pinned": false,
|
|
248
|
+
"template": {
|
|
249
|
+
"_type": "Component",
|
|
250
|
+
"background_color": {
|
|
251
|
+
"_input_type": "MessageTextInput",
|
|
252
|
+
"advanced": true,
|
|
253
|
+
"display_name": "Background Color",
|
|
254
|
+
"dynamic": false,
|
|
255
|
+
"info": "The background color of the icon.",
|
|
256
|
+
"input_types": [
|
|
257
|
+
"Message"
|
|
258
|
+
],
|
|
259
|
+
"list": false,
|
|
260
|
+
"list_add_label": "Add More",
|
|
261
|
+
"load_from_db": false,
|
|
262
|
+
"name": "background_color",
|
|
263
|
+
"placeholder": "",
|
|
264
|
+
"required": false,
|
|
265
|
+
"show": true,
|
|
266
|
+
"title_case": false,
|
|
267
|
+
"tool_mode": false,
|
|
268
|
+
"trace_as_input": true,
|
|
269
|
+
"trace_as_metadata": true,
|
|
270
|
+
"type": "str",
|
|
271
|
+
"value": ""
|
|
272
|
+
},
|
|
273
|
+
"chat_icon": {
|
|
274
|
+
"_input_type": "MessageTextInput",
|
|
275
|
+
"advanced": true,
|
|
276
|
+
"display_name": "Icon",
|
|
277
|
+
"dynamic": false,
|
|
278
|
+
"info": "The icon of the message.",
|
|
279
|
+
"input_types": [
|
|
280
|
+
"Message"
|
|
281
|
+
],
|
|
282
|
+
"list": false,
|
|
283
|
+
"list_add_label": "Add More",
|
|
284
|
+
"load_from_db": false,
|
|
285
|
+
"name": "chat_icon",
|
|
286
|
+
"placeholder": "",
|
|
287
|
+
"required": false,
|
|
288
|
+
"show": true,
|
|
289
|
+
"title_case": false,
|
|
290
|
+
"tool_mode": false,
|
|
291
|
+
"trace_as_input": true,
|
|
292
|
+
"trace_as_metadata": true,
|
|
293
|
+
"type": "str",
|
|
294
|
+
"value": ""
|
|
295
|
+
},
|
|
296
|
+
"clean_data": {
|
|
297
|
+
"_input_type": "BoolInput",
|
|
298
|
+
"advanced": true,
|
|
299
|
+
"display_name": "Basic Clean Data",
|
|
300
|
+
"dynamic": false,
|
|
301
|
+
"info": "Whether to clean the data",
|
|
302
|
+
"list": false,
|
|
303
|
+
"list_add_label": "Add More",
|
|
304
|
+
"name": "clean_data",
|
|
305
|
+
"placeholder": "",
|
|
306
|
+
"required": false,
|
|
307
|
+
"show": true,
|
|
308
|
+
"title_case": false,
|
|
309
|
+
"tool_mode": false,
|
|
310
|
+
"trace_as_metadata": true,
|
|
311
|
+
"type": "bool",
|
|
312
|
+
"value": true
|
|
313
|
+
},
|
|
314
|
+
"code": {
|
|
315
|
+
"advanced": true,
|
|
316
|
+
"dynamic": true,
|
|
317
|
+
"fileTypes": [],
|
|
318
|
+
"file_path": "",
|
|
319
|
+
"info": "",
|
|
320
|
+
"list": false,
|
|
321
|
+
"load_from_db": false,
|
|
322
|
+
"multiline": true,
|
|
323
|
+
"name": "code",
|
|
324
|
+
"password": false,
|
|
325
|
+
"placeholder": "",
|
|
326
|
+
"required": true,
|
|
327
|
+
"show": true,
|
|
328
|
+
"title_case": false,
|
|
329
|
+
"type": "code",
|
|
330
|
+
"value": "from collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nfrom fastapi.encoders import jsonable_encoder\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.helpers.data import safe_convert\nfrom langflow.inputs.inputs import BoolInput, DropdownInput, HandleInput, MessageTextInput\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.message import Message\nfrom langflow.schema.properties import Source\nfrom langflow.template.field.base import Output\nfrom langflow.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_AI,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n documentation: str = \"https://docs.langflow.org/components-io#chat-output\"\n icon = \"MessagesSquare\"\n name = \"ChatOutput\"\n minimized = True\n\n inputs = [\n HandleInput(\n name=\"input_value\",\n display_name=\"Inputs\",\n info=\"Message to be passed as output.\",\n input_types=[\"Data\", \"DataFrame\", \"Message\"],\n required=True,\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n MessageTextInput(\n name=\"background_color\",\n display_name=\"Background Color\",\n info=\"The background color of the icon.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"chat_icon\",\n display_name=\"Icon\",\n info=\"The icon of the message.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"text_color\",\n display_name=\"Text Color\",\n info=\"The text color of the name\",\n advanced=True,\n ),\n BoolInput(\n name=\"clean_data\",\n display_name=\"Basic Clean Data\",\n value=True,\n info=\"Whether to clean the data\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(\n display_name=\"Output Message\",\n name=\"message\",\n method=\"message_response\",\n ),\n ]\n\n def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n source_dict = {}\n if id_:\n source_dict[\"id\"] = id_\n if display_name:\n source_dict[\"display_name\"] = display_name\n if source:\n # Handle case where source is a ChatOpenAI object\n if hasattr(source, \"model_name\"):\n source_dict[\"source\"] = source.model_name\n elif hasattr(source, \"model\"):\n source_dict[\"source\"] = str(source.model)\n else:\n source_dict[\"source\"] = str(source)\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\n # First convert the input to string if needed\n text = self.convert_to_string()\n\n # Get source properties\n source, icon, display_name, source_id = self.get_properties_from_source_component()\n background_color = self.background_color\n text_color = self.text_color\n if self.chat_icon:\n icon = self.chat_icon\n\n # Create or use existing Message object\n if isinstance(self.input_value, Message):\n message = self.input_value\n # Update message properties\n message.text = text\n else:\n message = Message(text=text)\n\n # Set message properties\n message.sender = self.sender\n message.sender_name = self.sender_name\n message.session_id = self.session_id\n message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n message.properties.source = self._build_source(source_id, display_name, source)\n message.properties.icon = icon\n message.properties.background_color = background_color\n message.properties.text_color = text_color\n\n # Store message if needed\n if self.session_id and self.should_store_message:\n stored_message = await self.send_message(message)\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n\n def _serialize_data(self, data: Data) -> str:\n \"\"\"Serialize Data object to JSON string.\"\"\"\n # Convert data.data to JSON-serializable format\n serializable_data = jsonable_encoder(data.data)\n # Serialize with orjson, enabling pretty printing with indentation\n json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n # Convert bytes to string and wrap in Markdown code blocks\n return \"```json\\n\" + json_bytes.decode(\"utf-8\") + \"\\n```\"\n\n def _validate_input(self) -> None:\n \"\"\"Validate the input data and raise ValueError if invalid.\"\"\"\n if self.input_value is None:\n msg = \"Input data cannot be None\"\n raise ValueError(msg)\n if isinstance(self.input_value, list) and not all(\n isinstance(item, Message | Data | DataFrame | str) for item in self.input_value\n ):\n invalid_types = [\n type(item).__name__\n for item in self.input_value\n if not isinstance(item, Message | Data | DataFrame | str)\n ]\n msg = f\"Expected Data or DataFrame or Message or str, got {invalid_types}\"\n raise TypeError(msg)\n if not isinstance(\n self.input_value,\n Message | Data | DataFrame | str | list | Generator | type(None),\n ):\n type_name = type(self.input_value).__name__\n msg = f\"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}\"\n raise TypeError(msg)\n\n def convert_to_string(self) -> str | Generator[Any, None, None]:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n self._validate_input()\n if isinstance(self.input_value, list):\n return \"\\n\".join([safe_convert(item, clean_data=self.clean_data) for item in self.input_value])\n if isinstance(self.input_value, Generator):\n return self.input_value\n return safe_convert(self.input_value)\n"
|
|
331
|
+
},
|
|
332
|
+
"data_template": {
|
|
333
|
+
"_input_type": "MessageTextInput",
|
|
334
|
+
"advanced": true,
|
|
335
|
+
"display_name": "Data Template",
|
|
336
|
+
"dynamic": false,
|
|
337
|
+
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
|
|
338
|
+
"input_types": [
|
|
339
|
+
"Message"
|
|
340
|
+
],
|
|
341
|
+
"list": false,
|
|
342
|
+
"list_add_label": "Add More",
|
|
343
|
+
"load_from_db": false,
|
|
344
|
+
"name": "data_template",
|
|
345
|
+
"placeholder": "",
|
|
346
|
+
"required": false,
|
|
347
|
+
"show": true,
|
|
348
|
+
"title_case": false,
|
|
349
|
+
"tool_mode": false,
|
|
350
|
+
"trace_as_input": true,
|
|
351
|
+
"trace_as_metadata": true,
|
|
352
|
+
"type": "str",
|
|
353
|
+
"value": "{text}"
|
|
354
|
+
},
|
|
355
|
+
"input_value": {
|
|
356
|
+
"_input_type": "HandleInput",
|
|
357
|
+
"advanced": false,
|
|
358
|
+
"display_name": "Inputs",
|
|
359
|
+
"dynamic": false,
|
|
360
|
+
"info": "Message to be passed as output.",
|
|
361
|
+
"input_types": [
|
|
362
|
+
"Data",
|
|
363
|
+
"DataFrame",
|
|
364
|
+
"Message"
|
|
365
|
+
],
|
|
366
|
+
"list": false,
|
|
367
|
+
"list_add_label": "Add More",
|
|
368
|
+
"name": "input_value",
|
|
369
|
+
"placeholder": "",
|
|
370
|
+
"required": true,
|
|
371
|
+
"show": true,
|
|
372
|
+
"title_case": false,
|
|
373
|
+
"trace_as_metadata": true,
|
|
374
|
+
"type": "other",
|
|
375
|
+
"value": ""
|
|
376
|
+
},
|
|
377
|
+
"sender": {
|
|
378
|
+
"_input_type": "DropdownInput",
|
|
379
|
+
"advanced": true,
|
|
380
|
+
"combobox": false,
|
|
381
|
+
"dialog_inputs": {},
|
|
382
|
+
"display_name": "Sender Type",
|
|
383
|
+
"dynamic": false,
|
|
384
|
+
"info": "Type of sender.",
|
|
385
|
+
"name": "sender",
|
|
386
|
+
"options": [
|
|
387
|
+
"Machine",
|
|
388
|
+
"User"
|
|
389
|
+
],
|
|
390
|
+
"options_metadata": [],
|
|
391
|
+
"placeholder": "",
|
|
392
|
+
"required": false,
|
|
393
|
+
"show": true,
|
|
394
|
+
"title_case": false,
|
|
395
|
+
"toggle": false,
|
|
396
|
+
"tool_mode": false,
|
|
397
|
+
"trace_as_metadata": true,
|
|
398
|
+
"type": "str",
|
|
399
|
+
"value": "Machine"
|
|
400
|
+
},
|
|
401
|
+
"sender_name": {
|
|
402
|
+
"_input_type": "MessageTextInput",
|
|
403
|
+
"advanced": true,
|
|
404
|
+
"display_name": "Sender Name",
|
|
405
|
+
"dynamic": false,
|
|
406
|
+
"info": "Name of the sender.",
|
|
407
|
+
"input_types": [
|
|
408
|
+
"Message"
|
|
409
|
+
],
|
|
410
|
+
"list": false,
|
|
411
|
+
"list_add_label": "Add More",
|
|
412
|
+
"load_from_db": false,
|
|
413
|
+
"name": "sender_name",
|
|
414
|
+
"placeholder": "",
|
|
415
|
+
"required": false,
|
|
416
|
+
"show": true,
|
|
417
|
+
"title_case": false,
|
|
418
|
+
"tool_mode": false,
|
|
419
|
+
"trace_as_input": true,
|
|
420
|
+
"trace_as_metadata": true,
|
|
421
|
+
"type": "str",
|
|
422
|
+
"value": "AI"
|
|
423
|
+
},
|
|
424
|
+
"session_id": {
|
|
425
|
+
"_input_type": "MessageTextInput",
|
|
426
|
+
"advanced": true,
|
|
427
|
+
"display_name": "Session ID",
|
|
428
|
+
"dynamic": false,
|
|
429
|
+
"info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
|
|
430
|
+
"input_types": [
|
|
431
|
+
"Message"
|
|
432
|
+
],
|
|
433
|
+
"list": false,
|
|
434
|
+
"list_add_label": "Add More",
|
|
435
|
+
"load_from_db": false,
|
|
436
|
+
"name": "session_id",
|
|
437
|
+
"placeholder": "",
|
|
438
|
+
"required": false,
|
|
439
|
+
"show": true,
|
|
440
|
+
"title_case": false,
|
|
441
|
+
"tool_mode": false,
|
|
442
|
+
"trace_as_input": true,
|
|
443
|
+
"trace_as_metadata": true,
|
|
444
|
+
"type": "str",
|
|
445
|
+
"value": ""
|
|
446
|
+
},
|
|
447
|
+
"should_store_message": {
|
|
448
|
+
"_input_type": "BoolInput",
|
|
449
|
+
"advanced": true,
|
|
450
|
+
"display_name": "Store Messages",
|
|
451
|
+
"dynamic": false,
|
|
452
|
+
"info": "Store the message in the history.",
|
|
453
|
+
"list": false,
|
|
454
|
+
"list_add_label": "Add More",
|
|
455
|
+
"name": "should_store_message",
|
|
456
|
+
"placeholder": "",
|
|
457
|
+
"required": false,
|
|
458
|
+
"show": true,
|
|
459
|
+
"title_case": false,
|
|
460
|
+
"tool_mode": false,
|
|
461
|
+
"trace_as_metadata": true,
|
|
462
|
+
"type": "bool",
|
|
463
|
+
"value": true
|
|
464
|
+
},
|
|
465
|
+
"text_color": {
|
|
466
|
+
"_input_type": "MessageTextInput",
|
|
467
|
+
"advanced": true,
|
|
468
|
+
"display_name": "Text Color",
|
|
469
|
+
"dynamic": false,
|
|
470
|
+
"info": "The text color of the name",
|
|
471
|
+
"input_types": [
|
|
472
|
+
"Message"
|
|
473
|
+
],
|
|
474
|
+
"list": false,
|
|
475
|
+
"list_add_label": "Add More",
|
|
476
|
+
"load_from_db": false,
|
|
477
|
+
"name": "text_color",
|
|
478
|
+
"placeholder": "",
|
|
479
|
+
"required": false,
|
|
480
|
+
"show": true,
|
|
481
|
+
"title_case": false,
|
|
482
|
+
"tool_mode": false,
|
|
483
|
+
"trace_as_input": true,
|
|
484
|
+
"trace_as_metadata": true,
|
|
485
|
+
"type": "str",
|
|
486
|
+
"value": ""
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
"tool_mode": false
|
|
490
|
+
},
|
|
491
|
+
"showNode": false,
|
|
492
|
+
"type": "ChatOutput"
|
|
493
|
+
},
|
|
494
|
+
"dragging": false,
|
|
495
|
+
"id": "ChatOutput-tixOe",
|
|
496
|
+
"measured": {
|
|
497
|
+
"height": 48,
|
|
498
|
+
"width": 192
|
|
499
|
+
},
|
|
500
|
+
"position": {
|
|
501
|
+
"x": 1043.5413322661916,
|
|
502
|
+
"y": -202.42300688367868
|
|
503
|
+
},
|
|
504
|
+
"selected": false,
|
|
505
|
+
"type": "genericNode"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"data": {
|
|
509
|
+
"id": "KBRetrieval-tGoBR",
|
|
510
|
+
"node": {
|
|
511
|
+
"base_classes": [
|
|
512
|
+
"DataFrame"
|
|
513
|
+
],
|
|
514
|
+
"beta": false,
|
|
515
|
+
"conditional_paths": [],
|
|
516
|
+
"custom_fields": {},
|
|
517
|
+
"description": "Search and retrieve data from knowledge.",
|
|
518
|
+
"display_name": "Knowledge Retrieval",
|
|
519
|
+
"documentation": "",
|
|
520
|
+
"edited": false,
|
|
521
|
+
"field_order": [
|
|
522
|
+
"knowledge_base",
|
|
523
|
+
"api_key",
|
|
524
|
+
"search_query",
|
|
525
|
+
"top_k",
|
|
526
|
+
"include_metadata"
|
|
527
|
+
],
|
|
528
|
+
"frozen": false,
|
|
529
|
+
"icon": "database",
|
|
530
|
+
"last_updated": "2025-08-13T19:46:57.894Z",
|
|
531
|
+
"legacy": false,
|
|
532
|
+
"metadata": {
|
|
533
|
+
"code_hash": "f82365a0977f",
|
|
534
|
+
"module": "langflow.components.data.kb_retrieval.KBRetrievalComponent"
|
|
535
|
+
},
|
|
536
|
+
"minimized": false,
|
|
537
|
+
"output_types": [],
|
|
538
|
+
"outputs": [
|
|
539
|
+
{
|
|
540
|
+
"allows_loop": false,
|
|
541
|
+
"cache": true,
|
|
542
|
+
"display_name": "Results",
|
|
543
|
+
"group_outputs": false,
|
|
544
|
+
"method": "get_chroma_kb_data",
|
|
545
|
+
"name": "chroma_kb_data",
|
|
546
|
+
"selected": "DataFrame",
|
|
547
|
+
"tool_mode": true,
|
|
548
|
+
"types": [
|
|
549
|
+
"DataFrame"
|
|
550
|
+
],
|
|
551
|
+
"value": "__UNDEFINED__"
|
|
552
|
+
}
|
|
553
|
+
],
|
|
554
|
+
"pinned": false,
|
|
555
|
+
"template": {
|
|
556
|
+
"_type": "Component",
|
|
557
|
+
"api_key": {
|
|
558
|
+
"_input_type": "SecretStrInput",
|
|
559
|
+
"advanced": true,
|
|
560
|
+
"display_name": "Embedding Provider API Key",
|
|
561
|
+
"dynamic": false,
|
|
562
|
+
"info": "API key for the embedding provider to generate embeddings.",
|
|
563
|
+
"input_types": [],
|
|
564
|
+
"load_from_db": false,
|
|
565
|
+
"name": "api_key",
|
|
566
|
+
"password": true,
|
|
567
|
+
"placeholder": "",
|
|
568
|
+
"required": false,
|
|
569
|
+
"show": true,
|
|
570
|
+
"title_case": false,
|
|
571
|
+
"type": "str",
|
|
572
|
+
"value": ""
|
|
573
|
+
},
|
|
574
|
+
"code": {
|
|
575
|
+
"advanced": true,
|
|
576
|
+
"dynamic": true,
|
|
577
|
+
"fileTypes": [],
|
|
578
|
+
"file_path": "",
|
|
579
|
+
"info": "",
|
|
580
|
+
"list": false,
|
|
581
|
+
"load_from_db": false,
|
|
582
|
+
"multiline": true,
|
|
583
|
+
"name": "code",
|
|
584
|
+
"password": false,
|
|
585
|
+
"placeholder": "",
|
|
586
|
+
"required": true,
|
|
587
|
+
"show": true,
|
|
588
|
+
"title_case": false,
|
|
589
|
+
"type": "code",
|
|
590
|
+
"value": "import json\nfrom pathlib import Path\nfrom typing import Any\n\nfrom cryptography.fernet import InvalidToken\nfrom langchain_chroma import Chroma\nfrom loguru import logger\n\nfrom langflow.custom import Component\nfrom langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, Output, SecretStrInput\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.services.auth.utils import decrypt_api_key\nfrom langflow.services.deps import get_settings_service\n\nsettings = get_settings_service().settings\nknowledge_directory = settings.knowledge_bases_dir\nif not knowledge_directory:\n msg = \"Knowledge bases directory is not set in the settings.\"\n raise ValueError(msg)\nKNOWLEDGE_BASES_ROOT_PATH = Path(knowledge_directory).expanduser()\n\n\nclass KBRetrievalComponent(Component):\n display_name = \"Knowledge Retrieval\"\n description = \"Search and retrieve data from knowledge.\"\n icon = \"database\"\n name = \"KBRetrieval\"\n\n inputs = [\n DropdownInput(\n name=\"knowledge_base\",\n display_name=\"Knowledge\",\n info=\"Select the knowledge to load data from.\",\n required=True,\n options=[\n str(d.name) for d in KNOWLEDGE_BASES_ROOT_PATH.iterdir() if not d.name.startswith(\".\") and d.is_dir()\n ]\n if KNOWLEDGE_BASES_ROOT_PATH.exists()\n else [],\n refresh_button=True,\n real_time_refresh=True,\n ),\n SecretStrInput(\n name=\"api_key\",\n display_name=\"Embedding Provider API Key\",\n info=\"API key for the embedding provider to generate embeddings.\",\n advanced=True,\n required=False,\n ),\n MessageTextInput(\n name=\"search_query\",\n display_name=\"Search Query\",\n info=\"Optional search query to filter knowledge base data.\",\n ),\n IntInput(\n name=\"top_k\",\n display_name=\"Top K Results\",\n info=\"Number of top results to return from the knowledge base.\",\n value=5,\n advanced=True,\n required=False,\n ),\n BoolInput(\n name=\"include_metadata\",\n display_name=\"Include Metadata\",\n info=\"Whether to include all metadata and embeddings in the output. If false, only content is returned.\",\n value=True,\n advanced=True,\n ),\n ]\n\n outputs = [\n Output(\n name=\"chroma_kb_data\",\n display_name=\"Results\",\n method=\"get_chroma_kb_data\",\n info=\"Returns the data from the selected knowledge base.\",\n ),\n ]\n\n def _get_knowledge_bases(self) -> list[str]:\n \"\"\"Retrieve a list of available knowledge bases.\n\n Returns:\n A list of knowledge base names.\n \"\"\"\n if not KNOWLEDGE_BASES_ROOT_PATH.exists():\n return []\n\n return [str(d.name) for d in KNOWLEDGE_BASES_ROOT_PATH.iterdir() if not d.name.startswith(\".\") and d.is_dir()]\n\n def update_build_config(self, build_config, field_value, field_name=None): # noqa: ARG002\n if field_name == \"knowledge_base\":\n # Update the knowledge base options dynamically\n build_config[\"knowledge_base\"][\"options\"] = self._get_knowledge_bases()\n\n # If the selected knowledge base is not available, reset it\n if build_config[\"knowledge_base\"][\"value\"] not in build_config[\"knowledge_base\"][\"options\"]:\n build_config[\"knowledge_base\"][\"value\"] = None\n\n return build_config\n\n def _get_kb_metadata(self, kb_path: Path) -> dict:\n \"\"\"Load and process knowledge base metadata.\"\"\"\n metadata: dict[str, Any] = {}\n metadata_file = kb_path / \"embedding_metadata.json\"\n if not metadata_file.exists():\n logger.warning(f\"Embedding metadata file not found at {metadata_file}\")\n return metadata\n\n try:\n with metadata_file.open(\"r\", encoding=\"utf-8\") as f:\n metadata = json.load(f)\n except json.JSONDecodeError:\n logger.error(f\"Error decoding JSON from {metadata_file}\")\n return {}\n\n # Decrypt API key if it exists\n if \"api_key\" in metadata and metadata.get(\"api_key\"):\n settings_service = get_settings_service()\n try:\n decrypted_key = decrypt_api_key(metadata[\"api_key\"], settings_service)\n metadata[\"api_key\"] = decrypted_key\n except (InvalidToken, TypeError, ValueError) as e:\n logger.error(f\"Could not decrypt API key. Please provide it manually. Error: {e}\")\n metadata[\"api_key\"] = None\n return metadata\n\n def _build_embeddings(self, metadata: dict):\n \"\"\"Build embedding model from metadata.\"\"\"\n provider = metadata.get(\"embedding_provider\")\n model = metadata.get(\"embedding_model\")\n api_key = metadata.get(\"api_key\")\n chunk_size = metadata.get(\"chunk_size\")\n\n # If user provided a key in the input, it overrides the stored one.\n if self.api_key and self.api_key.get_secret_value():\n api_key = self.api_key.get_secret_value()\n\n # Handle various providers\n if provider == \"OpenAI\":\n from langchain_openai import OpenAIEmbeddings\n\n if not api_key:\n msg = \"OpenAI API key is required. Provide it in the component's advanced settings.\"\n raise ValueError(msg)\n return OpenAIEmbeddings(\n model=model,\n api_key=api_key,\n chunk_size=chunk_size,\n )\n if provider == \"HuggingFace\":\n from langchain_huggingface import HuggingFaceEmbeddings\n\n return HuggingFaceEmbeddings(\n model=model,\n )\n if provider == \"Cohere\":\n from langchain_cohere import CohereEmbeddings\n\n if not api_key:\n msg = \"Cohere API key is required when using Cohere provider\"\n raise ValueError(msg)\n return CohereEmbeddings(\n model=model,\n cohere_api_key=api_key,\n )\n if provider == \"Custom\":\n # For custom embedding models, we would need additional configuration\n msg = \"Custom embedding models not yet supported\"\n raise NotImplementedError(msg)\n # Add other providers here if they become supported in ingest\n msg = f\"Embedding provider '{provider}' is not supported for retrieval.\"\n raise NotImplementedError(msg)\n\n def get_chroma_kb_data(self) -> DataFrame:\n \"\"\"Retrieve data from the selected knowledge base by reading the Chroma collection.\n\n Returns:\n A DataFrame containing the data rows from the knowledge base.\n \"\"\"\n kb_path = KNOWLEDGE_BASES_ROOT_PATH / self.knowledge_base\n\n metadata = self._get_kb_metadata(kb_path)\n if not metadata:\n msg = f\"Metadata not found for knowledge base: {self.knowledge_base}. Ensure it has been indexed.\"\n raise ValueError(msg)\n\n # Build the embedder for the knowledge base\n embedding_function = self._build_embeddings(metadata)\n\n # Load vector store\n chroma = Chroma(\n persist_directory=str(kb_path),\n embedding_function=embedding_function,\n collection_name=self.knowledge_base,\n )\n\n # If a search query is provided, perform a similarity search\n if self.search_query:\n # Use the search query to perform a similarity search\n logger.info(f\"Performing similarity search with query: {self.search_query}\")\n results = chroma.similarity_search_with_score(\n query=self.search_query or \"\",\n k=self.top_k,\n )\n else:\n results = chroma.similarity_search(\n query=self.search_query or \"\",\n k=self.top_k,\n )\n\n # For each result, make it a tuple to match the expected output format\n results = [(doc, 0) for doc in results] # Assign a dummy score of 0\n\n # If metadata is enabled, get embeddings for the results\n id_to_embedding = {}\n if self.include_metadata and results:\n doc_ids = [doc[0].metadata.get(\"_id\") for doc in results if doc[0].metadata.get(\"_id\")]\n\n # Only proceed if we have valid document IDs\n if doc_ids:\n # Access underlying client to get embeddings\n collection = chroma._client.get_collection(name=self.knowledge_base)\n embeddings_result = collection.get(where={\"_id\": {\"$in\": doc_ids}}, include=[\"embeddings\", \"metadatas\"])\n\n # Create a mapping from document ID to embedding\n for i, metadata in enumerate(embeddings_result.get(\"metadatas\", [])):\n if metadata and \"_id\" in metadata:\n id_to_embedding[metadata[\"_id\"]] = embeddings_result[\"embeddings\"][i]\n\n # Build output data based on include_metadata setting\n data_list = []\n for doc in results:\n if self.include_metadata:\n # Include all metadata, embeddings, and content\n kwargs = {\n \"content\": doc[0].page_content,\n **doc[0].metadata,\n }\n if self.search_query:\n kwargs[\"_score\"] = -1 * doc[1]\n kwargs[\"_embeddings\"] = id_to_embedding.get(doc[0].metadata.get(\"_id\"))\n else:\n # Only include content\n kwargs = {\n \"content\": doc[0].page_content,\n }\n\n data_list.append(Data(**kwargs))\n\n # Return the DataFrame containing the data\n return DataFrame(data=data_list)\n"
|
|
591
|
+
},
|
|
592
|
+
"include_metadata": {
|
|
593
|
+
"_input_type": "BoolInput",
|
|
594
|
+
"advanced": true,
|
|
595
|
+
"display_name": "Include Metadata",
|
|
596
|
+
"dynamic": false,
|
|
597
|
+
"info": "Whether to include all metadata and embeddings in the output. If false, only content is returned.",
|
|
598
|
+
"list": false,
|
|
599
|
+
"list_add_label": "Add More",
|
|
600
|
+
"name": "include_metadata",
|
|
601
|
+
"placeholder": "",
|
|
602
|
+
"required": false,
|
|
603
|
+
"show": true,
|
|
604
|
+
"title_case": false,
|
|
605
|
+
"tool_mode": false,
|
|
606
|
+
"trace_as_metadata": true,
|
|
607
|
+
"type": "bool",
|
|
608
|
+
"value": true
|
|
609
|
+
},
|
|
610
|
+
"knowledge_base": {
|
|
611
|
+
"_input_type": "DropdownInput",
|
|
612
|
+
"advanced": false,
|
|
613
|
+
"combobox": false,
|
|
614
|
+
"dialog_inputs": {},
|
|
615
|
+
"display_name": "Knowledge",
|
|
616
|
+
"dynamic": false,
|
|
617
|
+
"info": "Select the knowledge to load data from.",
|
|
618
|
+
"name": "knowledge_base",
|
|
619
|
+
"options": [],
|
|
620
|
+
"options_metadata": [],
|
|
621
|
+
"placeholder": "",
|
|
622
|
+
"real_time_refresh": true,
|
|
623
|
+
"refresh_button": true,
|
|
624
|
+
"required": true,
|
|
625
|
+
"show": true,
|
|
626
|
+
"title_case": false,
|
|
627
|
+
"toggle": false,
|
|
628
|
+
"tool_mode": false,
|
|
629
|
+
"trace_as_metadata": true,
|
|
630
|
+
"type": "str",
|
|
631
|
+
"value": null
|
|
632
|
+
},
|
|
633
|
+
"search_query": {
|
|
634
|
+
"_input_type": "MessageTextInput",
|
|
635
|
+
"advanced": false,
|
|
636
|
+
"display_name": "Search Query",
|
|
637
|
+
"dynamic": false,
|
|
638
|
+
"info": "Optional search query to filter knowledge base data.",
|
|
639
|
+
"input_types": [
|
|
640
|
+
"Message"
|
|
641
|
+
],
|
|
642
|
+
"list": false,
|
|
643
|
+
"list_add_label": "Add More",
|
|
644
|
+
"load_from_db": false,
|
|
645
|
+
"name": "search_query",
|
|
646
|
+
"placeholder": "",
|
|
647
|
+
"required": false,
|
|
648
|
+
"show": true,
|
|
649
|
+
"title_case": false,
|
|
650
|
+
"tool_mode": false,
|
|
651
|
+
"trace_as_input": true,
|
|
652
|
+
"trace_as_metadata": true,
|
|
653
|
+
"type": "str",
|
|
654
|
+
"value": ""
|
|
655
|
+
},
|
|
656
|
+
"top_k": {
|
|
657
|
+
"_input_type": "IntInput",
|
|
658
|
+
"advanced": true,
|
|
659
|
+
"display_name": "Top K Results",
|
|
660
|
+
"dynamic": false,
|
|
661
|
+
"info": "Number of top results to return from the knowledge base.",
|
|
662
|
+
"list": false,
|
|
663
|
+
"list_add_label": "Add More",
|
|
664
|
+
"name": "top_k",
|
|
665
|
+
"placeholder": "",
|
|
666
|
+
"required": false,
|
|
667
|
+
"show": true,
|
|
668
|
+
"title_case": false,
|
|
669
|
+
"tool_mode": false,
|
|
670
|
+
"trace_as_metadata": true,
|
|
671
|
+
"type": "int",
|
|
672
|
+
"value": 5
|
|
673
|
+
}
|
|
674
|
+
},
|
|
675
|
+
"tool_mode": false
|
|
676
|
+
},
|
|
677
|
+
"showNode": true,
|
|
678
|
+
"type": "KBRetrieval"
|
|
679
|
+
},
|
|
680
|
+
"dragging": false,
|
|
681
|
+
"id": "KBRetrieval-tGoBR",
|
|
682
|
+
"measured": {
|
|
683
|
+
"height": 286,
|
|
684
|
+
"width": 320
|
|
685
|
+
},
|
|
686
|
+
"position": {
|
|
687
|
+
"x": 640.6283193600648,
|
|
688
|
+
"y": -313.9694258557284
|
|
689
|
+
},
|
|
690
|
+
"selected": false,
|
|
691
|
+
"type": "genericNode"
|
|
692
|
+
}
|
|
693
|
+
],
|
|
694
|
+
"viewport": {
|
|
695
|
+
"x": 285.0464459586908,
|
|
696
|
+
"y": 588.7377652547386,
|
|
697
|
+
"zoom": 0.9833370380356916
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
"description": "An example of performing a vector search against data in a Knowledge Base to retrieve relevant documents.",
|
|
701
|
+
"endpoint_name": null,
|
|
702
|
+
"id": "670745f6-08b1-480e-bdaf-64ba74967cba",
|
|
703
|
+
"is_component": false,
|
|
704
|
+
"last_tested_version": "1.5.0.post1",
|
|
705
|
+
"name": "Knowledge Retrieval",
|
|
706
|
+
"tags": []
|
|
707
|
+
}
|