From a54d7df974de27129b2b8b5d822964b097965f05 Mon Sep 17 00:00:00 2001 From: jacoblee93 Date: Wed, 18 Oct 2023 19:53:34 -0700 Subject: [PATCH] Adds custom array and text controls --- examples/chain/server.py | 21 +- langserve/playground/.gitignore | 2 + langserve/playground/package.json | 2 + langserve/playground/src/App.css | 6 +- langserve/playground/src/App.tsx | 11 +- .../components/CustomArrayControlRenderer.tsx | 86 + .../src/components/CustomTextAreaCell.tsx | 65 + .../src/components/DeleteDialog.tsx | 84 + .../src/components/MaterialTableControl.tsx | 486 + .../src/components/NoBorderTableCell.tsx | 39 + .../src/components/TableToolbar.tsx | 111 + .../src/components/ValidationIcon.tsx | 49 + langserve/playground/src/main.tsx | 2 +- langserve/playground/yarn.lock | 7889 +++++++++++------ 14 files changed, 6002 insertions(+), 2851 deletions(-) create mode 100644 langserve/playground/src/components/CustomArrayControlRenderer.tsx create mode 100644 langserve/playground/src/components/CustomTextAreaCell.tsx create mode 100644 langserve/playground/src/components/DeleteDialog.tsx create mode 100644 langserve/playground/src/components/MaterialTableControl.tsx create mode 100644 langserve/playground/src/components/NoBorderTableCell.tsx create mode 100644 langserve/playground/src/components/TableToolbar.tsx create mode 100644 langserve/playground/src/components/ValidationIcon.tsx diff --git a/examples/chain/server.py b/examples/chain/server.py index eea7c813..8b0fb0d4 100755 --- a/examples/chain/server.py +++ b/examples/chain/server.py @@ -1,12 +1,16 @@ #!/usr/bin/env python """Example LangChain server exposes a chain composed of a prompt and an LLM.""" +from typing import Any, Dict, List, Optional + from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from langchain.chat_models import ChatOpenAI from langchain.prompts import PromptTemplate + +# from typing_extensions import TypedDict +from langchain.pydantic_v1 import BaseModel from langchain.schema.output_parser import StrOutputParser -from langchain.schema.runnable import ConfigurableField -from typing_extensions import TypedDict +from langchain.schema.runnable import ConfigurableField, RunnablePassthrough from langserve import add_routes @@ -17,7 +21,7 @@ default_key="medium_temp", ) prompt = PromptTemplate.from_template( - "tell me a joke about {topic}" + "tell me a joke about {topic}.\nChat history: {chat_history}" ).configurable_fields( template=ConfigurableField( id="prompt", @@ -25,7 +29,12 @@ description="The prompt to use. Must contain {topic}", ) ) -chain = prompt | model | StrOutputParser() +chain = ( + RunnablePassthrough.assign(chat_history=(lambda x: "\n".join(x))) + | prompt + | model + | StrOutputParser() +) app = FastAPI( title="LangChain Server", @@ -47,11 +56,13 @@ # The input type is automatically inferred from the runnable # interface; however, if you want to override it, you can do so # by passing in the input_type argument to add_routes. -class ChainInput(TypedDict): +class ChainInput(BaseModel): """The input to the chain.""" topic: str """The topic of the joke.""" + chat_history: List[str] + tester: Optional[Dict[str, Any]] = None add_routes(app, chain, input_type=ChainInput, config_keys=["configurable"]) diff --git a/langserve/playground/.gitignore b/langserve/playground/.gitignore index a547bf36..33d989f9 100644 --- a/langserve/playground/.gitignore +++ b/langserve/playground/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +.yarn \ No newline at end of file diff --git a/langserve/playground/package.json b/langserve/playground/package.json index 72a815d7..95e98da1 100644 --- a/langserve/playground/package.json +++ b/langserve/playground/package.json @@ -23,12 +23,14 @@ "dayjs": "^1.11.10", "fast-json-patch": "^3.1.1", "json-schema-defaults": "^0.4.0", + "lodash": "^4.17.21", "lz-string": "^1.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "vaul": "^0.7.3" }, "devDependencies": { + "@types/lodash": "^4.14.200", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@typescript-eslint/eslint-plugin": "^6.0.0", diff --git a/langserve/playground/src/App.css b/langserve/playground/src/App.css index 52be92c6..66dcdbd0 100644 --- a/langserve/playground/src/App.css +++ b/langserve/playground/src/App.css @@ -55,10 +55,14 @@ @apply focus-within:border-ls-blue focus-within:outline focus-within:outline-4 focus-within:outline-ls-blue/20; } -.control > label { +.control > label, .control h6 { @apply text-xs uppercase font-semibold text-ls-gray-100; } +.control div .MuiGrid-item { + @apply pt-0; +} + .control > select { @apply -ml-1; } diff --git a/langserve/playground/src/App.tsx b/langserve/playground/src/App.tsx index c33d1fe6..3b8e7f70 100644 --- a/langserve/playground/src/App.tsx +++ b/langserve/playground/src/App.tsx @@ -36,7 +36,7 @@ import { IntegerCell, NumberCell, SliderCell, - TextAreaCell, + // TextAreaCell, TimeCell, booleanCellTester, dateCellTester, @@ -54,6 +54,8 @@ import { import { useSchemas } from "./useSchemas"; import { RunState, useStreamLog } from "./useStreamLog"; import { JsonFormsCore } from "@jsonforms/core"; +import CustomArrayControlRenderer, { materialArrayControlTester } from "./components/CustomArrayControlRenderer"; +import CustomTextAreaCell from "./components/CustomTextAreaCell"; dayjs.extend(relativeDate); dayjs.extend(utc); @@ -75,6 +77,9 @@ const renderers = [ { tester: materialAllOfControlTester, renderer: MaterialAllOfRenderer }, { tester: materialAnyOfControlTester, renderer: MaterialAnyOfRenderer }, { tester: materialOneOfControlTester, renderer: MaterialOneOfRenderer }, + + // custom renderers + { tester: materialArrayControlTester, renderer: CustomArrayControlRenderer } ]; const cells = [ @@ -85,8 +90,8 @@ const cells = [ { tester: integerCellTester, cell: IntegerCell }, { tester: numberCellTester, cell: NumberCell }, { tester: sliderCellTester, cell: SliderCell }, - { tester: textAreaCellTester, cell: TextAreaCell }, - { tester: textCellTester, cell: TextAreaCell }, + { tester: textAreaCellTester, cell: CustomTextAreaCell }, + { tester: textCellTester, cell: CustomTextAreaCell }, { tester: timeCellTester, cell: TimeCell }, ]; diff --git a/langserve/playground/src/components/CustomArrayControlRenderer.tsx b/langserve/playground/src/components/CustomArrayControlRenderer.tsx new file mode 100644 index 00000000..ae74c744 --- /dev/null +++ b/langserve/playground/src/components/CustomArrayControlRenderer.tsx @@ -0,0 +1,86 @@ +// From https://github.com/eclipsesource/jsonforms/blob/44070b325121ad7173082fdf33be079f42ef96c4/packages/material/src/complex/MaterialArrayControlRenderer.tsx +/* + The MIT License + + Copyright (c) 2017-2019 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +import React, { useCallback, useState } from 'react'; +import { + ArrayLayoutProps, + RankedTester, + isObjectArrayControl, + isPrimitiveArrayControl, + or, + rankWith, +} from '@jsonforms/core'; +import { withJsonFormsArrayLayoutProps } from '@jsonforms/react'; +import { MaterialTableControl } from './MaterialTableControl'; +import { Hidden } from '@mui/material'; +import { DeleteDialog } from './DeleteDialog'; + +export const MaterialArrayControlRenderer = (props: ArrayLayoutProps) => { + const [open, setOpen] = useState(false); + const [path, setPath] = useState(undefined); + const [rowData, setRowData] = useState(undefined); + const { removeItems, visible } = props; + + const openDeleteDialog = useCallback( + (p: string, rowIndex: number) => { + setOpen(true); + setPath(p); + setRowData(rowIndex); + }, + [setOpen, setPath, setRowData] + ); + const deleteCancel = useCallback(() => setOpen(false), [setOpen]); + const deleteConfirm = useCallback(() => { + const p = path.substring(0, path.lastIndexOf('.')); + removeItems(p, [rowData])(); + setOpen(false); + }, [setOpen, path, rowData]); + const deleteClose = useCallback(() => setOpen(false), [setOpen]); + + return ( +
+ + + + +
+ ); +}; + +export const materialArrayControlTester: RankedTester = rankWith( + 999, + or(isObjectArrayControl, isPrimitiveArrayControl) +); + +export default withJsonFormsArrayLayoutProps(MaterialArrayControlRenderer); \ No newline at end of file diff --git a/langserve/playground/src/components/CustomTextAreaCell.tsx b/langserve/playground/src/components/CustomTextAreaCell.tsx new file mode 100644 index 00000000..c88fd443 --- /dev/null +++ b/langserve/playground/src/components/CustomTextAreaCell.tsx @@ -0,0 +1,65 @@ +// From https://github.com/eclipsesource/jsonforms/blob/master/packages/vanilla-renderers/src/cells/TextAreaCell.tsx + +/* + The MIT License + + Copyright (c) 2017-2019 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +import React from 'react'; +import { + CellProps, + isMultiLineControl, + RankedTester, + rankWith, +} from '@jsonforms/core'; +import { withJsonFormsCellProps } from '@jsonforms/react'; +import { withVanillaCellProps, type VanillaRendererProps } from '@jsonforms/vanilla-renderers'; +import merge from 'lodash/merge'; + +export const TextAreaCell = (props: CellProps & VanillaRendererProps) => { + const { data, className, id, enabled, config, uischema, path, handleChange } = + props; + const appliedUiSchemaOptions = merge({}, config, uischema.options); + console.log(config, uischema); + return ( +