From 37193b00314b022c32729206c4a061eb173c5a7c Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 7 Jun 2024 19:53:04 -0300 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20(monitor.py):=20enhance=20trans?= =?UTF-8?q?action=20response=20with=20additional=20fields=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F=20(base.py):=20refactor=20log=5Ftransaction=20to=20in?= =?UTF-8?q?clude=20flow=5Fid=20for=20better=20traceability=20=E2=99=BB?= =?UTF-8?q?=EF=B8=8F=20(vertex/base.py):=20refactor=20log=5Ftransaction=20?= =?UTF-8?q?to=20include=20flow=5Fid=20for=20better=20traceability=20?= =?UTF-8?q?=E2=9C=A8=20(schema.py):=20add=20flow=5Fid=20and=20make=20outpu?= =?UTF-8?q?ts=20optional=20in=20TransactionModel=20=E2=99=BB=EF=B8=8F=20(s?= =?UTF-8?q?ervice.py):=20update=20SQL=20query=20to=20include=20new=20field?= =?UTF-8?q?s=20and=20order=20by=20timestamp=20=E2=99=BB=EF=B8=8F=20(utils.?= =?UTF-8?q?py):=20update=20log=5Ftransaction=20to=20include=20flow=5Fid=20?= =?UTF-8?q?and=20handle=20optional=20outputs=20=F0=9F=92=84=20(index.tsx):?= =?UTF-8?q?=20fix=20linting=20issues=20and=20update=20button=20component?= =?UTF-8?q?=20=E2=9C=85=20(chatInputOutputUser.spec.ts):=20add=20additiona?= =?UTF-8?q?l=20steps=20to=20end-to-end=20test=20for=20chat=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/base/langflow/api/v1/monitor.py | 17 +++++++++++++- src/backend/base/langflow/graph/graph/base.py | 6 +++-- .../base/langflow/graph/vertex/base.py | 5 +++-- .../base/langflow/services/monitor/schema.py | 9 +++++--- .../base/langflow/services/monitor/service.py | 5 +++-- .../base/langflow/services/monitor/utils.py | 6 +++-- .../components/parameterComponent/index.tsx | 22 ++++++++++--------- .../end-to-end/chatInputOutputUser.spec.ts | 4 ++++ 8 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/backend/base/langflow/api/v1/monitor.py b/src/backend/base/langflow/api/v1/monitor.py index ffd01b470..b748e4955 100644 --- a/src/backend/base/langflow/api/v1/monitor.py +++ b/src/backend/base/langflow/api/v1/monitor.py @@ -117,6 +117,21 @@ async def get_transactions( dicts = monitor_service.get_transactions( source=source, target=target, status=status, order_by=order_by, flow_id=flow_id ) - return [TransactionModelResponse(**d) for d in dicts] + result = [] + for d in dicts: + d = TransactionModelResponse( + index=d["index"], + timestamp=d["timestamp"], + vertex_id=d["vertex_id"], + inputs=d["inputs"], + outputs=d["outputs"], + status=d["status"], + error=d["error"], + flow_id=d["flow_id"], + source=d["vertex_id"], + target=d["target_id"], + ) + result.append(d) + return result except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/src/backend/base/langflow/graph/graph/base.py b/src/backend/base/langflow/graph/graph/base.py index 57ccc6a9d..06074ee1d 100644 --- a/src/backend/base/langflow/graph/graph/base.py +++ b/src/backend/base/langflow/graph/graph/base.py @@ -769,11 +769,13 @@ class Graph: next_runnable_vertices, top_level_vertices = await self.get_next_and_top_level_vertices( lock, set_cache_coro, vertex ) - log_transaction(vertex, status="success") + flow_id = self.flow_id + log_transaction(flow_id, vertex, status="success") return next_runnable_vertices, top_level_vertices, result_dict, params, valid, artifacts, vertex except Exception as exc: logger.exception(f"Error building vertex: {exc}") - log_transaction(vertex, status="failure", error=str(exc)) + flow_id = self.flow_id + log_transaction(flow_id, vertex, status="failure", error=str(exc)) raise exc async def get_next_and_top_level_vertices( diff --git a/src/backend/base/langflow/graph/vertex/base.py b/src/backend/base/langflow/graph/vertex/base.py index 99aed5b02..a94bd7a46 100644 --- a/src/backend/base/langflow/graph/vertex/base.py +++ b/src/backend/base/langflow/graph/vertex/base.py @@ -529,12 +529,13 @@ class Vertex: Returns: The built result if use_result is True, else the built object. """ + flow_id = self.graph.flow_id if not self._built: - log_transaction(vertex=self, target=requester, status="error") + log_transaction(flow_id, vertex=self, target=requester, status="error") raise ValueError(f"Component {self.display_name} has not been built yet") result = self._built_result if self.use_result else self._built_object - log_transaction(vertex=self, target=requester, status="success") + log_transaction(flow_id, vertex=self, target=requester, status="success") return result async def _build_vertex_and_update_params(self, key, vertex: "Vertex"): diff --git a/src/backend/base/langflow/services/monitor/schema.py b/src/backend/base/langflow/services/monitor/schema.py index 8f9c57752..2c3396c7d 100644 --- a/src/backend/base/langflow/services/monitor/schema.py +++ b/src/backend/base/langflow/services/monitor/schema.py @@ -14,9 +14,10 @@ class TransactionModel(BaseModel): vertex_id: str target_id: str | None = None inputs: dict - outputs: dict + outputs: Optional[dict] = None status: str error: Optional[str] = None + flow_id: Optional[str] = Field(default=None, alias="flow_id") class Config: from_attributes = True @@ -35,15 +36,17 @@ class TransactionModel(BaseModel): return json.dumps(v) return v - class TransactionModelResponse(BaseModel): index: Optional[int] = Field(default=None) timestamp: Optional[datetime] = Field(default_factory=datetime.now, alias="timestamp") vertex_id: str inputs: dict - outputs: dict + outputs: Optional[dict] = None status: str error: Optional[str] = None + flow_id: Optional[str] = Field(default=None, alias="flow_id") + source: Optional[str] = None + target: Optional[str] = None class Config: from_attributes = True diff --git a/src/backend/base/langflow/services/monitor/service.py b/src/backend/base/langflow/services/monitor/service.py index e15cb39dd..6f1152fe6 100644 --- a/src/backend/base/langflow/services/monitor/service.py +++ b/src/backend/base/langflow/services/monitor/service.py @@ -168,7 +168,8 @@ class MonitorService(Service): order_by: Optional[str] = "timestamp", flow_id: Optional[str] = None, ): - query = "SELECT index,flow_id, source, target, target_args, status, error, timestamp FROM transactions" + + query = "SELECT index,flow_id, status, error, timestamp, vertex_id, inputs, outputs, target_id FROM transactions" conditions = [] if source: conditions.append(f"source = '{source}'") @@ -183,7 +184,7 @@ class MonitorService(Service): query += " WHERE " + " AND ".join(conditions) if order_by: - query += f" ORDER BY {order_by}" + query += f" ORDER BY {order_by} DESC" with duckdb.connect(str(self.db_path)) as conn: df = conn.execute(query).df() diff --git a/src/backend/base/langflow/services/monitor/utils.py b/src/backend/base/langflow/services/monitor/utils.py index ea7a3bad6..8d62083d2 100644 --- a/src/backend/base/langflow/services/monitor/utils.py +++ b/src/backend/base/langflow/services/monitor/utils.py @@ -178,18 +178,20 @@ def build_clean_params(target: "Vertex") -> dict: return params -def log_transaction(vertex: "Vertex", status, target: Optional["Vertex"] = None, error=None): +def log_transaction(flow_id, vertex: "Vertex", status, target: Optional["Vertex"] = None, error=None): try: + monitor_service = get_monitor_service() clean_params = build_clean_params(vertex) data = { "vertex_id": str(vertex.id), "target_id": str(target.id) if target else None, "inputs": clean_params, - "outputs": vertex.result.model_dump_json(), + "outputs": vertex.result.model_dump_json() if vertex.result else None, "timestamp": monitor_service.get_timestamp(), "status": status, "error": error, + "flow_id": flow_id } monitor_service.add_row(table_name="transactions", data=data) except Exception as e: diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 145eaaf4b..941c86271 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -98,7 +98,7 @@ export default function ParameterComponent({ debouncedHandleUpdateValues, setNode, renderTooltips, - setIsLoading + setIsLoading, ); const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( @@ -107,7 +107,7 @@ export default function ParameterComponent({ takeSnapshot, setNode, updateNodeInternals, - renderTooltips + renderTooltips, ); const { handleRefreshButtonPress: handleRefreshButtonPressHook } = @@ -116,7 +116,7 @@ export default function ParameterComponent({ let disabled = edges.some( (edge) => - edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) + edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id), ) ?? false; const handleRefreshButtonPress = async (name, data) => { @@ -129,12 +129,12 @@ export default function ParameterComponent({ handleUpdateValues, setNode, renderTooltips, - setIsLoading + setIsLoading, ); const handleOnNewValue = async ( newValue: string | string[] | boolean | Object[], - skipSnapshot: boolean | undefined = false + skipSnapshot: boolean | undefined = false, ): Promise => { handleOnNewValueHook(newValue, skipSnapshot); }; @@ -216,7 +216,7 @@ export default function ParameterComponent({ className={classNames( left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", "h-3 w-3 rounded-full border-2 bg-background", - !showNode ? "mt-0" : "" + !showNode ? "mt-0" : "", )} style={{ borderColor: color ?? nodeColors.unknown, @@ -274,7 +274,9 @@ export default function ParameterComponent({ : "Please build the component first" } > - + )} @@ -334,7 +336,7 @@ export default function ParameterComponent({ } className={classNames( left ? "-ml-0.5" : "-mr-0.5", - "h-3 w-3 rounded-full border-2 bg-background" + "h-3 w-3 rounded-full border-2 bg-background", )} style={{ borderColor: color ?? nodeColors.unknown }} onClick={() => setFilterEdge(groupedEdge.current)} diff --git a/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts b/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts index 399d40948..ce1a9ce27 100644 --- a/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts +++ b/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts @@ -227,4 +227,8 @@ test("user must be able to send an image on chat", async ({ page }) => { await page.getByTestId("icon-LucideSend").click(); await page.waitForTimeout(2000); await page.getByText("chain.png").isVisible(); + + await page.getByText("Close", { exact: true }).click(); + await page.getByTestId("icon-ScanEye").last().click(); + await page.getByText("Restart").isHidden(); }); From b3a3e7b8e5ef9c8306c7292544919d513e5d3452 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 7 Jun 2024 19:53:40 -0300 Subject: [PATCH 2/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(schema.py):=20remove?= =?UTF-8?q?=20unnecessary=20blank=20line=20to=20improve=20code=20readabili?= =?UTF-8?q?ty=20=E2=99=BB=EF=B8=8F=20(service.py):=20reformat=20SQL=20quer?= =?UTF-8?q?y=20string=20for=20better=20readability=20=E2=99=BB=EF=B8=8F=20?= =?UTF-8?q?(utils.py):=20remove=20unnecessary=20blank=20line=20to=20clean?= =?UTF-8?q?=20up=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/base/langflow/services/monitor/schema.py | 1 + src/backend/base/langflow/services/monitor/service.py | 5 +++-- src/backend/base/langflow/services/monitor/utils.py | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/backend/base/langflow/services/monitor/schema.py b/src/backend/base/langflow/services/monitor/schema.py index 2c3396c7d..4cb057ccc 100644 --- a/src/backend/base/langflow/services/monitor/schema.py +++ b/src/backend/base/langflow/services/monitor/schema.py @@ -36,6 +36,7 @@ class TransactionModel(BaseModel): return json.dumps(v) return v + class TransactionModelResponse(BaseModel): index: Optional[int] = Field(default=None) timestamp: Optional[datetime] = Field(default_factory=datetime.now, alias="timestamp") diff --git a/src/backend/base/langflow/services/monitor/service.py b/src/backend/base/langflow/services/monitor/service.py index 6f1152fe6..6c37672af 100644 --- a/src/backend/base/langflow/services/monitor/service.py +++ b/src/backend/base/langflow/services/monitor/service.py @@ -168,8 +168,9 @@ class MonitorService(Service): order_by: Optional[str] = "timestamp", flow_id: Optional[str] = None, ): - - query = "SELECT index,flow_id, status, error, timestamp, vertex_id, inputs, outputs, target_id FROM transactions" + query = ( + "SELECT index,flow_id, status, error, timestamp, vertex_id, inputs, outputs, target_id FROM transactions" + ) conditions = [] if source: conditions.append(f"source = '{source}'") diff --git a/src/backend/base/langflow/services/monitor/utils.py b/src/backend/base/langflow/services/monitor/utils.py index 8d62083d2..706d62348 100644 --- a/src/backend/base/langflow/services/monitor/utils.py +++ b/src/backend/base/langflow/services/monitor/utils.py @@ -180,7 +180,6 @@ def build_clean_params(target: "Vertex") -> dict: def log_transaction(flow_id, vertex: "Vertex", status, target: Optional["Vertex"] = None, error=None): try: - monitor_service = get_monitor_service() clean_params = build_clean_params(vertex) data = { @@ -191,7 +190,7 @@ def log_transaction(flow_id, vertex: "Vertex", status, target: Optional["Vertex" "timestamp": monitor_service.get_timestamp(), "status": status, "error": error, - "flow_id": flow_id + "flow_id": flow_id, } monitor_service.add_row(table_name="transactions", data=data) except Exception as e: