Skip to content

Commit 9cbddaf

Browse files
committed
frontend/llm/i18n: tell LLMs to translate to user language – unless disabled in account settings
1 parent 5d9a838 commit 9cbddaf

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

src/packages/frontend/account/other-settings.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { FormattedMessage, useIntl } from "react-intl";
99

1010
import { Checkbox, Panel } from "@cocalc/frontend/antd-bootstrap";
1111
import { Rendered, redux, useTypedRedux } from "@cocalc/frontend/app-framework";
12+
import { useLocalizationCtx } from "@cocalc/frontend/app/localize";
1213
import {
1314
A,
1415
HelpIcon,
@@ -22,7 +23,7 @@ import {
2223
import AIAvatar from "@cocalc/frontend/components/ai-avatar";
2324
import { IS_MOBILE, IS_TOUCH } from "@cocalc/frontend/feature";
2425
import LLMSelector from "@cocalc/frontend/frame-editors/llm/llm-selector";
25-
import { labels } from "@cocalc/frontend/i18n";
26+
import { LOCALIZATIONS, labels } from "@cocalc/frontend/i18n";
2627
import {
2728
VBAR_EXPLANATION,
2829
VBAR_KEY,
@@ -33,6 +34,7 @@ import { NewFilenameFamilies } from "@cocalc/frontend/project/utils";
3334
import track from "@cocalc/frontend/user-tracking";
3435
import { webapp_client } from "@cocalc/frontend/webapp-client";
3536
import { DEFAULT_NEW_FILENAMES, NEW_FILENAMES } from "@cocalc/util/db-schema";
37+
import { OTHER_SETTINGS_REPLY_ENGLISH_KEY } from "@cocalc/util/i18n/const";
3638
import { dark_mode_mins, get_dark_mode_config } from "./dark-mode";
3739
import { I18NSelector, I18N_MESSAGE, I18N_TITLE } from "./i18n-selector";
3840
import Tours from "./tours";
@@ -60,6 +62,7 @@ interface Props {
6062

6163
export function OtherSettings(props: Readonly<Props>): JSX.Element {
6264
const intl = useIntl();
65+
const { locale } = useLocalizationCtx();
6366
const isCoCalcCom = useTypedRedux("customize", "is_cocalc_com");
6467
const user_defined_llm = useTypedRedux("customize", "user_defined_llm");
6568

@@ -552,6 +555,24 @@ export function OtherSettings(props: Readonly<Props>): JSX.Element {
552555
);
553556
}
554557

558+
function render_llm_reply_language(): Rendered {
559+
return (
560+
<Checkbox
561+
checked={!!props.other_settings.get(OTHER_SETTINGS_REPLY_ENGLISH_KEY)}
562+
onChange={(e) => {
563+
on_change(OTHER_SETTINGS_REPLY_ENGLISH_KEY, e.target.checked);
564+
}}
565+
>
566+
<FormattedMessage
567+
id="account.other-settings.llm.reply_language"
568+
defaultMessage={`<strong>Always reply in English</strong>,
569+
If set, the replies are always in English. Otherwise – the default – it replies in your interface language (currently {lang})`}
570+
values={{ lang: intl.formatMessage(LOCALIZATIONS[locale].trans) }}
571+
/>
572+
</Checkbox>
573+
);
574+
}
575+
555576
function render_custom_llm(): Rendered {
556577
// on cocalc.com, do not even show that they're disabled
557578
if (isCoCalcCom && !user_defined_llm) return;
@@ -578,6 +599,7 @@ export function OtherSettings(props: Readonly<Props>): JSX.Element {
578599
>
579600
{render_disable_all_llm()}
580601
{render_language_model()}
602+
{render_llm_reply_language()}
581603
{render_custom_llm()}
582604
</Panel>
583605
);

src/packages/frontend/client/llm.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ import {
2424
import * as message from "@cocalc/util/message";
2525
import type { WebappClient } from "./client";
2626
import type { History } from "./types";
27+
import {
28+
LOCALIZATIONS,
29+
OTHER_SETTINGS_LOCALE_KEY,
30+
OTHER_SETTINGS_REPLY_ENGLISH_KEY,
31+
} from "@cocalc/util/i18n/const";
32+
import { sanitizeLocale } from "@cocalc/frontend/i18n";
2733

2834
interface QueryLLMProps {
2935
input: string;
@@ -111,6 +117,19 @@ export class LLMClient {
111117
}
112118
}
113119

120+
// append a sentence to request to translate the output to the user's language – unless disabled
121+
const other_settings = redux.getStore("account").get("other_settings");
122+
const alwaysEnglish = !!other_settings.get(
123+
OTHER_SETTINGS_REPLY_ENGLISH_KEY,
124+
);
125+
const locale = sanitizeLocale(
126+
other_settings.get(OTHER_SETTINGS_LOCALE_KEY),
127+
);
128+
if (!alwaysEnglish && locale != "en") {
129+
const lang = LOCALIZATIONS[locale].name; // name is always in english
130+
system = `${system}\n\nYour answer must be written in the language ${lang}.`;
131+
}
132+
114133
const is_cocalc_com = redux.getStore("customize").get("is_cocalc_com");
115134

116135
if (!isFreeModel(model, is_cocalc_com)) {

src/packages/frontend/jupyter/llm/cell-tool.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ const ACTIONS: { [mode in Mode]: LLMTool } = {
215215
label: defineMessage({
216216
id: "jupyter.llm.cell-tool.actions.document.label",
217217
defaultMessage: "Document",
218-
description: "Label on a button to write a documentation, i.e. to 'document' this",
218+
description:
219+
"Label on a button to write a documentation, i.e. to 'document' this",
219220
}),
220221
descr: defineMessage({
221222
id: "jupyter.llm.cell-tool.actions.document.descr",

src/packages/util/i18n/const.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export const KEEP_EN_LOCALE = "en-keep";
3939

4040
export const OTHER_SETTINGS_LOCALE_KEY = "i18n";
4141

42+
export const OTHER_SETTINGS_REPLY_ENGLISH_KEY = "llm_reply_english"
43+
4244
// The ordering is a bit "opinionated". The top languages are European ones, and German has the best quality translations.
4345
// Then come other European languges, kind of alphabetical.
4446

0 commit comments

Comments
 (0)