Add tone support

This commit is contained in:
2025-04-08 18:38:07 +03:00
parent 8082eae230
commit 3fb4afd4fa
8 changed files with 53 additions and 18 deletions

View File

@@ -2,7 +2,7 @@
<div class="flex justify-between items-center gap-4"> <div class="flex justify-between items-center gap-4">
<div> <div>
<div class="font-semibold"><slot name="title" /></div> <div class="font-semibold"><slot name="title" /></div>
<div class="text-slate-600 text-sm"> <div class="text-slate-600 text-sm hidden md:block">
<slot name="description" /> <slot name="description" />
</div> </div>
</div> </div>

View File

@@ -13,9 +13,10 @@ interface FormData {
const preferences = useState<FormData>("preferences", () => ({ const preferences = useState<FormData>("preferences", () => ({
enabled: false, enabled: false,
language: "English", language: "English",
tone: "Casual",
})); }));
const { status, refresh } = useFetch("/api/preferences", { const { status } = useFetch("/api/preferences", {
onResponse({ error, response }) { onResponse({ error, response }) {
if (error) { if (error) {
return; return;
@@ -86,6 +87,20 @@ const saveOp = watchPausable(
/> />
</template> </template>
</CardField> </CardField>
<CardField>
<template #title> Model tone </template>
<template #description>
Tone used for generated titles and descriptions.
</template>
<template #value>
<USelect
class="min-w-28"
v-model="preferences.tone"
:items="tones"
/>
</template>
</CardField>
</div> </div>
</UCard> </UCard>
</UContainer> </UContainer>

View File

@@ -1,7 +0,0 @@
export const languages = ref([
"English",
"Greek",
"German",
"Italian",
"Polish",
]);

20
app/utils/model.ts Normal file
View File

@@ -0,0 +1,20 @@
export const languages = ref([
"English",
"Greek",
"German",
"Italian",
"Polish",
]);
export const tones = ref([
"Motivational",
"Casual",
"Funny",
"Epic",
"Minimalist",
"Reflective",
"Poetic",
"Competitive",
"Adventure",
"Snarky",
]);

View File

@@ -9,6 +9,7 @@ export default defineEventHandler(async (event) => {
data: { data: {
enabled: body.enabled, enabled: body.enabled,
language: body.language, language: body.language,
tone: body.tone,
}, },
}) })
.where(eq(tables.preferences.userId, session.user.id)) .where(eq(tables.preferences.userId, session.user.id))

View File

@@ -28,7 +28,7 @@ export const users = sqliteTable("users", {
sex: text("sex"), sex: text("sex"),
weight: integer("weight"), weight: integer("weight"),
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn( createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
() => new Date() () => new Date(),
), ),
}); });
@@ -43,10 +43,12 @@ export const preferences = sqliteTable("preferences", {
.$type<{ .$type<{
enabled: boolean; enabled: boolean;
language: string; language: string;
tone: string;
}>() }>()
.$defaultFn(() => ({ .$defaultFn(() => ({
enabled: true, enabled: true,
language: "English", language: "English",
tone: "Casual",
})), })),
}); });

View File

@@ -55,7 +55,8 @@ export default defineOAuthStravaEventHandler({
userId: user.id, userId: user.id,
data: { data: {
enabled: true, enabled: true,
language: "english", language: "English",
tone: "Casual",
}, },
}) })
.onConflictDoNothing(); .onConflictDoNothing();

View File

@@ -1,4 +1,4 @@
import { get } from "radash"; import { get, omit } from "radash";
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const body = await readBody(event); const body = await readBody(event);
@@ -19,9 +19,9 @@ export default defineEventHandler(async (event) => {
const strava = await useStrava(body.owner_id); const strava = await useStrava(body.owner_id);
const activity = await strava!(`/activities/${body.object_id}`); const activity = (await strava!(`/activities/${body.object_id}`)) as any;
const aiResponse = await ai.run("@cf/meta/llama-3-8b-instruct", { const aiResponse = await ai.run("@cf/meta/llama-3.1-8b-instruct", {
response_format: { response_format: {
type: "json_schema", type: "json_schema",
json_schema: { json_schema: {
@@ -34,20 +34,23 @@ export default defineEventHandler(async (event) => {
}, },
}, },
prompt: ` prompt: `
Generate a title and a short description for my strava activity. Use my preferred language. Make sure to include emojis and make it fun. Generate a title and a short description for my strava activity. Use my preferred language.
Use ${user?.preferences.data.tone} tone to generate content.
Add emojis unless tone is set to minimalist.
My user profile: My user profile:
Sex: ${user?.sex} Sex: ${user?.sex}
City: ${user?.city}
Country: ${user?.country}
Weight: ${user?.weight} Weight: ${user?.weight}
Language: ${user?.preferences.data.language} Language: ${user?.preferences.data.language}
The activity data in json format: The activity data in json format:
${JSON.stringify(activity)} ${JSON.stringify(omit(activity, ["map", "laps", "stats_visibility", "embed_token", "private_note"]))}
`, `,
}); });
// console.log(activity);
// console.log(aiResponse.response.title);
// console.log(aiResponse.response.description);
await strava!(`activities/${body.object_id}`, { await strava!(`activities/${body.object_id}`, {
method: "PUT", method: "PUT",
body: { body: {