Skip to content

Commit f4fc656

Browse files
authored
Add ability to add prompty app as processor (#236)
1 parent 9e20299 commit f4fc656

File tree

10 files changed

+745
-214
lines changed

10 files changed

+745
-214
lines changed

llmstack/apps/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def get_data(self, obj):
187187
)
188188
if asset_data and "url" in asset_data:
189189
app_data.data["config"]["assistant_image"] = asset_data["url"]
190-
return app_data.data
190+
return {**app_data.data, "version": app_data.version}
191191
return None
192192

193193
def get_has_live_version(self, obj):

llmstack/client/src/components/ThemedJsonForm.jsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ const StreamingVoiceInputWidget = lazy(
4242
() => import("./form/StreamingVoiceInputWidget"),
4343
);
4444

45+
const PromptlyAppSelector = lazy(
46+
() => import("./form/PromptlyAppSelectorWidget"),
47+
);
48+
4549
function CustomGdriveFileWidget(props) {
4650
return <GdriveFileSelector {...props} />;
4751
}
@@ -50,6 +54,10 @@ function CustomWebpageURLExtractorWidget(props) {
5054
return <WebpageURLExtractorWidget {...props} />;
5155
}
5256

57+
function PromptlyAppSelectorWidget(props) {
58+
return <PromptlyAppSelector {...props} />;
59+
}
60+
5361
function FieldTemplate(props) {
5462
const {
5563
id,
@@ -391,6 +399,7 @@ const ThemedJsonForm = ({
391399
richtext: RichTextWidget,
392400
voice: VoiceWidget,
393401
app_version: AppVersionSelectorWidget,
402+
promptlyapp_select: PromptlyAppSelectorWidget,
394403
},
395404
...widgets,
396405
}}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { useRecoilValue } from "recoil";
2+
import { appsState } from "../../data/atoms";
3+
import { MenuItem, Select, Stack } from "@mui/material";
4+
import { useEffect, useState } from "react";
5+
import validator from "@rjsf/validator-ajv8";
6+
import { getJSONSchemaFromInputFields } from "../../data/utils";
7+
import ThemedJsonForm from "../ThemedJsonForm";
8+
9+
export default function PromptlyAppSelectorWidget(props) {
10+
const { value, onChange } = props;
11+
const apps = useRecoilValue(appsState);
12+
const published_apps = apps.filter((app) => app.is_published);
13+
14+
const [selectedApp, setSelectedApp] = useState(null);
15+
const [inputSchema, setInputSchema] = useState({});
16+
const [inputUiSchema, setInputUiSchema] = useState({});
17+
const [jsonValue, setJsonValue] = useState({});
18+
19+
useEffect(() => {
20+
try {
21+
setJsonValue(JSON.parse(value));
22+
} catch (e) {
23+
console.error(e);
24+
}
25+
}, [value]);
26+
27+
useEffect(() => {
28+
if (jsonValue) {
29+
const selectedApp = published_apps.find(
30+
(app) => app.published_uuid === jsonValue?.promptly_app_published_uuid,
31+
);
32+
setSelectedApp(selectedApp);
33+
}
34+
}, [jsonValue, published_apps, setSelectedApp]);
35+
36+
useEffect(() => {
37+
if (selectedApp) {
38+
if (selectedApp.data.input_fields) {
39+
const { schema, uiSchema } = getJSONSchemaFromInputFields(
40+
selectedApp.data.input_fields,
41+
);
42+
setInputSchema(schema);
43+
setInputUiSchema(uiSchema);
44+
}
45+
}
46+
}, [selectedApp]);
47+
48+
return (
49+
<Stack>
50+
<Select
51+
labelId="app-select-label"
52+
id="app-select"
53+
value={jsonValue?.promptly_app_published_uuid || ""}
54+
label="Select an application"
55+
onChange={(event) => {
56+
const appData = published_apps.find(
57+
(app) => app.published_uuid === event.target.value,
58+
);
59+
props.onChange(
60+
JSON.stringify({
61+
promptly_app_published_uuid: event.target.value,
62+
promptly_app_input_fields: appData?.data.input_fields || [],
63+
promptly_app_version: appData?.version || 0,
64+
promptly_app_uuid: appData?.uuid || "",
65+
}),
66+
);
67+
}}
68+
variant="filled"
69+
sx={{ lineHeight: "0.5em" }}
70+
>
71+
{published_apps.map((app) => (
72+
<MenuItem key={app.published_uuid} value={app.published_uuid}>
73+
{app.name}
74+
</MenuItem>
75+
))}
76+
</Select>
77+
<ThemedJsonForm
78+
schema={inputSchema}
79+
uiSchema={inputUiSchema}
80+
formData={jsonValue?.input || {}}
81+
onChange={({ formData }) => {
82+
onChange(
83+
JSON.stringify({
84+
promptly_app_published_uuid:
85+
jsonValue.promptly_app_published_uuid,
86+
promptly_app_input_fields: jsonValue.promptly_app_input_fields,
87+
promptly_app_version: jsonValue.promptly_app_version,
88+
promptly_app_uuid: jsonValue.promptly_app_uuid,
89+
input: formData,
90+
}),
91+
);
92+
}}
93+
validator={validator}
94+
disableAdvanced={true}
95+
/>
96+
</Stack>
97+
);
98+
}

llmstack/common/utils/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,5 +460,7 @@ def get_tool_json_schema_from_input_fields(name="", input_fields=[]):
460460
"type": value["type"],
461461
"description": value.get("description", ""),
462462
}
463+
if value["type"] == "array":
464+
tool_schema["properties"][key]["items"] = value["items"]
463465

464466
return tool_schema

llmstack/processors/providers/promptly/app.py

Lines changed: 0 additions & 71 deletions
This file was deleted.

llmstack/processors/providers/promptly/echo.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22

33
from asgiref.sync import async_to_sync
4+
from pydantic import Field
45

56
from llmstack.apps.schemas import OutputTemplate
67
from llmstack.processors.providers.api_processor_interface import (
@@ -12,7 +13,7 @@
1213

1314

1415
class EchoProcessorInput(ApiProcessorSchema):
15-
input_str: str = "Hello World!"
16+
input_str: str = Field(description="The input string to echo", widget="textarea", default="Hello, World!")
1617
stream: bool = False
1718

1819

0 commit comments

Comments
 (0)