|
1 | 1 | <script lang="ts"> |
2 | 2 | import AppPage from "../../../../app_page.svelte" |
3 | | - import { current_task, load_available_prompts } from "$lib/stores" |
| 3 | + import { current_task } from "$lib/stores" |
4 | 4 | import { page } from "$app/stores" |
5 | | - import FormContainer from "$lib/utils/form_container.svelte" |
6 | | - import FormElement from "$lib/utils/form_element.svelte" |
7 | 5 | import { client } from "$lib/api_client" |
8 | 6 | import { createKilnError, KilnError } from "$lib/utils/error_handlers" |
9 | | - import { goto } from "$app/navigation" |
10 | | - import posthog from "posthog-js" |
11 | 7 | import { onMount } from "svelte" |
12 | 8 | import { prompt_generator_categories } from "../prompt_generators/prompt_generators" |
13 | 9 | import { generate_memorable_name } from "$lib/utils/name_generator" |
| 10 | + import PromptForm from "../prompt_form.svelte" |
14 | 11 |
|
15 | 12 | $: project_id = $page.params.project_id! |
16 | 13 | $: task_id = $page.params.task_id! |
17 | 14 |
|
18 | 15 | let generator_name = "" |
19 | | - let prompt_name = generate_memorable_name() |
20 | | - let prompt = "" |
21 | | - let is_chain_of_thought = false |
22 | | - let chain_of_thought_instructions = |
23 | | - "Think step by step, explaining your reasoning." |
24 | | - let create_error: KilnError | null = null |
25 | | - let create_loading = false |
26 | | - let warn_before_unload = false |
| 16 | + let initial_prompt_name = generate_memorable_name() |
| 17 | + let initial_prompt = "" |
| 18 | + let loading_error: KilnError | null = null |
27 | 19 |
|
28 | 20 | let generator_id: string | null = null |
29 | | - let loading_generator = false |
| 21 | + let loading = true |
30 | 22 | let is_custom = true |
31 | 23 |
|
32 | | - let initial_prompt_name = "" |
33 | | - let initial_prompt = "" |
34 | | - let initial_loaded = false |
35 | | -
|
36 | 24 | onMount(async () => { |
37 | 25 | generator_id = $page.url.searchParams.get("generator_id") || null |
38 | 26 | is_custom = !generator_id |
39 | 27 |
|
40 | 28 | if (generator_id) { |
41 | | - loading_generator = true |
42 | 29 | try { |
43 | 30 | const { data: prompt_response, error: get_error } = await client.GET( |
44 | 31 | "/api/projects/{project_id}/tasks/{task_id}/gen_prompt/{prompt_id}", |
|
55 | 42 | if (get_error) { |
56 | 43 | throw get_error |
57 | 44 | } |
58 | | - prompt = prompt_response.prompt |
| 45 | + initial_prompt = prompt_response.prompt |
59 | 46 |
|
60 | 47 | const template = prompt_generator_categories |
61 | 48 | .flatMap((c) => c.templates) |
62 | 49 | .find((t) => t.generator_id === generator_id) |
63 | 50 | generator_name = template?.name || generator_id |
64 | 51 | } catch (e) { |
65 | | - create_error = createKilnError(e) |
66 | | - } finally { |
67 | | - loading_generator = false |
| 52 | + loading_error = createKilnError(e) |
68 | 53 | } |
69 | 54 | } else { |
70 | 55 | generator_name = "Custom" |
71 | 56 |
|
72 | 57 | if ($current_task?.instruction) { |
73 | | - prompt = $current_task.instruction |
| 58 | + initial_prompt = $current_task.instruction |
74 | 59 | } |
75 | 60 | } |
76 | 61 |
|
77 | | - initial_prompt_name = prompt_name |
78 | | - initial_prompt = prompt |
79 | | - initial_loaded = true |
| 62 | + loading = false |
80 | 63 | }) |
81 | | -
|
82 | | - async function create_prompt() { |
83 | | - try { |
84 | | - create_loading = true |
85 | | - create_error = null |
86 | | - const { data, error } = await client.POST( |
87 | | - "/api/projects/{project_id}/tasks/{task_id}/prompts", |
88 | | - { |
89 | | - params: { |
90 | | - path: { |
91 | | - project_id, |
92 | | - task_id, |
93 | | - }, |
94 | | - }, |
95 | | - body: { |
96 | | - generator_id: generator_id, |
97 | | - name: prompt_name, |
98 | | - prompt: prompt, |
99 | | - chain_of_thought_instructions: |
100 | | - is_custom && is_chain_of_thought |
101 | | - ? chain_of_thought_instructions |
102 | | - : null, |
103 | | - }, |
104 | | - }, |
105 | | - ) |
106 | | - if (error) { |
107 | | - throw error |
108 | | - } |
109 | | - if (!data || !data.id) { |
110 | | - throw new Error("Invalid response from server") |
111 | | - } |
112 | | - posthog.capture("create_prompt", { |
113 | | - is_chain_of_thought: is_chain_of_thought, |
114 | | - from_generator: generator_id, |
115 | | - }) |
116 | | -
|
117 | | - await load_available_prompts(true) |
118 | | -
|
119 | | - warn_before_unload = false |
120 | | - const from = $page.url.searchParams.get("from") |
121 | | - if (from === "optimize") { |
122 | | - goto( |
123 | | - `/optimize/${project_id}/${task_id}/run_config/create?prompt_id=${encodeURIComponent(`id::${data.id}`)}`, |
124 | | - ) |
125 | | - } else { |
126 | | - goto(`/prompts/${project_id}/${task_id}/saved/id::${data.id}`) |
127 | | - } |
128 | | - } catch (e) { |
129 | | - create_error = createKilnError(e) |
130 | | - } finally { |
131 | | - create_loading = false |
132 | | - } |
133 | | - } |
134 | | -
|
135 | | - $: if (initial_loaded) { |
136 | | - warn_before_unload = |
137 | | - prompt !== initial_prompt || |
138 | | - prompt_name !== initial_prompt_name || |
139 | | - (is_custom && is_chain_of_thought) |
140 | | - } |
141 | 64 | </script> |
142 | 65 |
|
143 | 66 | <div class="max-w-[1400px]"> |
144 | 67 | <AppPage |
145 | 68 | title="Create Prompt" |
146 | | - subtitle={`${generator_name}`} |
| 69 | + subtitle={generator_name} |
147 | 70 | sub_subtitle="Read the Docs" |
148 | 71 | sub_subtitle_link="https://docs.kiln.tech/docs/prompts" |
149 | 72 | breadcrumbs={[ |
|
157 | 80 | }, |
158 | 81 | ]} |
159 | 82 | > |
160 | | - {#if loading_generator} |
| 83 | + {#if loading} |
161 | 84 | <div class="w-full min-h-[50vh] flex justify-center items-center"> |
162 | 85 | <div class="loading loading-spinner loading-lg"></div> |
163 | 86 | </div> |
164 | | - {:else} |
165 | | - <div class="max-w-[800px]"> |
166 | | - <FormContainer |
167 | | - submit_label="Create Prompt" |
168 | | - on:submit={create_prompt} |
169 | | - bind:error={create_error} |
170 | | - bind:submitting={create_loading} |
171 | | - {warn_before_unload} |
172 | | - > |
173 | | - <FormElement |
174 | | - label="Prompt Name" |
175 | | - id="prompt_name" |
176 | | - bind:value={prompt_name} |
177 | | - description="A name to identify this prompt." |
178 | | - max_length={120} |
179 | | - /> |
180 | | - |
181 | | - <FormElement |
182 | | - label="Prompt" |
183 | | - id="prompt" |
184 | | - bind:value={prompt} |
185 | | - inputType="textarea" |
186 | | - height="large" |
187 | | - description="A prompt to use for this task." |
188 | | - info_description="Model prompt such as 'You are a helpful assistant.'. This prompt is specific to this task. To use this prompt after creation, select it from the prompts dropdown." |
189 | | - /> |
190 | | - {#if is_custom} |
191 | | - <FormElement |
192 | | - label="Chain of Thought" |
193 | | - id="is_chain_of_thought" |
194 | | - bind:value={is_chain_of_thought} |
195 | | - description="Should this prompt use chain of thought?" |
196 | | - inputType="select" |
197 | | - select_options={[ |
198 | | - [false, "Disabled"], |
199 | | - [true, "Enabled"], |
200 | | - ]} |
201 | | - /> |
202 | | - {#if is_chain_of_thought} |
203 | | - <FormElement |
204 | | - label="Chain of Thought Instructions" |
205 | | - id="chain_of_thought_instructions" |
206 | | - bind:value={chain_of_thought_instructions} |
207 | | - inputType="textarea" |
208 | | - description="Instructions for the model's 'thinking' prior to answering. Required for chain of thought prompting." |
209 | | - /> |
210 | | - {/if} |
211 | | - {/if} |
212 | | - </FormContainer> |
| 87 | + {:else if loading_error} |
| 88 | + <div class="text-error text-sm"> |
| 89 | + {loading_error.getMessage() || "An unknown error occurred"} |
213 | 90 | </div> |
| 91 | + {:else} |
| 92 | + <PromptForm |
| 93 | + {project_id} |
| 94 | + {task_id} |
| 95 | + {generator_id} |
| 96 | + show_chain_of_thought={is_custom} |
| 97 | + {initial_prompt_name} |
| 98 | + {initial_prompt} |
| 99 | + redirect_from={$page.url.searchParams.get("from")} |
| 100 | + /> |
214 | 101 | {/if} |
215 | 102 | </AppPage> |
216 | 103 | </div> |
0 commit comments