mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
fix(ai): tighten the ru dose bank
End a dose unit at a Cyrillic letter, so «3 месяца» no longer reads as "3 МЕ". Keep ml out of the drug units as the other banks do, and stand the target-dose shapes down on a dietary noun (water, sodium, caffeine), which blocked plain nutrition advice. Cover the stop and inject verbs (перестаньте, бросить, колите) the English bank already blocks.
This commit is contained in:
1 parent
3e2e2ad56b
commit
0007973b78
4 files changed
+47
-14
No files matched your search
@@ -192,6 +192,20 @@ const HARMLESS: Record<Locale, readonly string[]> = {
|
||||
"Продолжайте принимать рамиприл 5 мг как раньше.",
|
||||
"Снизьте потребление сахара вдвое.",
|
||||
"Спросите фармацевта, можно ли делить таблетку пополам.",
|
||||
// «ме» (international units) is a prefix of «месяц» and «метр»: a unit
|
||||
// has to end at a non-letter, Cyrillic included.
|
||||
"Стоит повторить анализ через 3 месяца.",
|
||||
"Нужно пересдать анализ через 2 месяца.",
|
||||
"Можно добавить 2 медленные прогулки в неделю.",
|
||||
"Выпейте стакан воды перед измерением давления.",
|
||||
"Перестаньте пить кофе после обеда.",
|
||||
"Бросьте курить: для давления это важнее всего.",
|
||||
// Nutrition in mg or ml is not a dose.
|
||||
"Выпейте 500 мл воды перед измерением.",
|
||||
"Увеличьте потребление воды до 2000 мл в день.",
|
||||
"Снизьте натрий до 1500 мг в день.",
|
||||
"Сократите кофеин до 200 мг в день.",
|
||||
"Рекомендуется не больше 2000 мг натрия в день.",
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -648,6 +648,12 @@ const DOSE_CLASS_VIOLATIONS: Record<Locale, readonly string[]> = {
|
||||
"Начните с 5 мг завтра.",
|
||||
"Перейдите на 10 мг.",
|
||||
"Снизьте дозу до 1000 мг.",
|
||||
"Перестаньте принимать варфарин перед поездкой.",
|
||||
"Можете бросить принимать бисопролол.",
|
||||
"Колите инсулин 10 ЕД перед сном.",
|
||||
"Выпейте две таблетки ибупрофена.",
|
||||
"Увеличьте дозу витамина D до 4000 МЕ.",
|
||||
"Снизьте инсулин до 20 ЕД.",
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const RU_MED_NOUN =
|
||||
|
||||
/** Russian dosage-form counters, with the case endings an object takes. */
|
||||
const RU_COUNT =
|
||||
"(?:таблетк[а-яё]*|капсул[а-яё]*|капл[а-яё]*|доз[а-яё]*|единиц[а-яё]*|ед\\.?|мл)";
|
||||
"(?:таблетк[а-яё]*|капсул[а-яё]*|капл[а-яё]*|доз[а-яё]*|единиц[а-яё]*|ед\\.?)";
|
||||
|
||||
const RU_TARGET = `(?:[\\d.,]+(?:\\s*${DRUG_UNIT}${UNIT_END}|\\s*${RU_COUNT})|(?:одну|одна|две|два|три|четыре|половину|полторы|пол)\\s*${RU_COUNT})`;
|
||||
|
||||
@@ -26,7 +26,7 @@ const RU_TARGET = `(?:[\\d.,]+(?:\\s*${DRUG_UNIT}${UNIT_END}|\\s*${RU_COUNT})|(?
|
||||
* different ending.
|
||||
*/
|
||||
const RU_IMPERATIVE =
|
||||
"(?:(?:увеличьте|увеличь|повысьте|повысь|поднимите|подними|нарастите|снизьте|снизь|уменьшите|уменьши|понизьте|понизь|опустите|опусти|сократите|сократи|удвойте|удвой|уполовиньте|разделите|пропустите|пропусти|отмените|отмени|прекратите|прекрати|примите|принимайте|начните|начинайте|перейдите|прекратить|отменить|пропустить|снизить|увеличить|повысить|уменьшить|понизить|сократить|удвоить|начать|перейти))(?![а-яё])";
|
||||
"(?:(?:увеличьте|увеличь|повысьте|повысь|поднимите|подними|нарастите|снизьте|снизь|уменьшите|уменьши|понизьте|понизь|опустите|опусти|сократите|сократи|удвойте|удвой|уполовиньте|разделите|пропустите|пропусти|отмените|отмени|прекратите|прекрати|примите|принимайте|начните|начинайте|перейдите|прекратить|отменить|пропустить|снизить|увеличить|повысить|уменьшить|понизить|сократить|удвоить|начать|перейти|выпейте|колите|вколите|уколите|перестаньте|перестань|бросьте|бросить))(?![а-яё])";
|
||||
|
||||
// Russian writes "12%" with digits; the spelled-out counters ("двенадцать
|
||||
// процентов") are rare in model prose and collide with the numeral declension,
|
||||
@@ -55,6 +55,17 @@ const RU_MED_CLASS =
|
||||
const RU_DEFERRAL =
|
||||
"\\?|врач[а-яё]*|доктор[а-яё]*|специалист[а-яё]*|эндокринолог[а-яё]*|фармацевт[а-яё]*|обсуди[а-яё]*|посовету[а-яё]*|спроси[а-яё]*|если\\s+только|как\\s+назначено|как\\s+обычно|как\\s+и\\s+раньше|не\\s+";
|
||||
|
||||
/**
|
||||
* Nutrition, not medication: "снизьте натрий до 1500 мг", "сократите кофеин
|
||||
* до 200 мг", "увеличьте потребление воды до 2000 мл". The target-dose shapes
|
||||
* below carry a free gap between the verb and the amount, so a dietary noun
|
||||
* anywhere in it stands the shape down, the way the other banks keep
|
||||
* sodium, caffeine and water out of their object slot.
|
||||
*/
|
||||
const RU_DIET =
|
||||
"(?:натри|сол[ьиеюя]|кофеин|сахар|вод[аыуеой]|жидкост|белк|бел[её]к|клетчатк|калори|кальци|магни|кали[йяю]|потреблен)";
|
||||
const RU_GAP = (n: number) => `(?:(?!${RU_DIET})[^.?!]){0,${n}}`;
|
||||
|
||||
export const bank: LocaleBank = {
|
||||
vocabulary: (names) =>
|
||||
`(?:${RU_MED_NOUN}|(?:${medicationExtras(RU_MED_CLASS, names, false)})\\S{0,3})`,
|
||||
@@ -85,7 +96,7 @@ export const bank: LocaleBank = {
|
||||
unlessDeferred(
|
||||
RU_DEFERRAL,
|
||||
new RegExp(
|
||||
`(?:примите|принимайте|выпейте|выпить|принять)[^.?!]{0,12}[\\d.,]+\\s*(?:мкг|мг|мл|ед|ме)${UNIT_END}`,
|
||||
`(?:примите|принимайте|выпейте|выпить|принять|колите|вколите|уколите)[^.?!]{0,12}[\\d.,]+\\s*(?:мкг|мг|ед|ме)${UNIT_END}`,
|
||||
"i",
|
||||
),
|
||||
),
|
||||
@@ -93,7 +104,7 @@ export const bank: LocaleBank = {
|
||||
unlessDeferred(
|
||||
RU_DEFERRAL,
|
||||
new RegExp(
|
||||
`(?:начните|начинайте|перейдите|переходите)[^.?!]{0,15}[\\d.,]+\\s*(?:мкг|мг|мл|ед|ме)${UNIT_END}`,
|
||||
`(?:начните|начинайте|перейдите|переходите)[^.?!]{0,15}[\\d.,]+\\s*(?:мкг|мг|ед|ме)${UNIT_END}`,
|
||||
"i",
|
||||
),
|
||||
),
|
||||
@@ -101,7 +112,7 @@ export const bank: LocaleBank = {
|
||||
unlessDeferred(
|
||||
RU_DEFERRAL,
|
||||
new RegExp(
|
||||
`(?:удвойте|удвой|уполовиньте|уполовинь)[^.?!]{0,25}[\\d.,]+\\s*(?:мкг|мг|мл|ед|ме)${UNIT_END}`,
|
||||
`(?:удвойте|удвой|уполовиньте|уполовинь)[^.?!]{0,25}[\\d.,]+\\s*(?:мкг|мг|ед|ме)${UNIT_END}`,
|
||||
"i",
|
||||
),
|
||||
),
|
||||
@@ -128,7 +139,7 @@ export const bank: LocaleBank = {
|
||||
),
|
||||
// The same skip/stop in verb-first order: "пропустите дозу метформина".
|
||||
new RegExp(
|
||||
`(?:пропустите|пропусти|отмените|отмени|прекратите|прекрати|бросьте|пропустить|отменить|прекратить)(?![а-яё])[^.?!]{0,15}${med}`,
|
||||
`(?:пропустите|пропусти|отмените|отмени|прекратите|прекрати|бросьте|перестаньте|перестань|пропустить|отменить|прекратить|бросить|перестать)(?![а-яё])[^.?!]{0,15}${med}`,
|
||||
"i",
|
||||
),
|
||||
// One more dose of a medication, closed by an imperative:
|
||||
@@ -152,21 +163,21 @@ export const bank: LocaleBank = {
|
||||
// на этой неделе") names no change verb and does not trip.
|
||||
dose: [
|
||||
new RegExp(
|
||||
`[\\d.,]+\\s*${DOSE_UNIT}\\s*(?:до|вплоть\\s*до)[^.?!]{0,20}(?:увелич|повыс|подним|нараст|начинай|переход|сниз|уменьш|пониз|опуст|сократ)`,
|
||||
`[\\d.,]+\\s*${DOSE_UNIT}\\s*(?:до|вплоть\\s*до)${RU_GAP(20)}(?:увелич|повыс|подним|нараст|начинай|переход|сниз|уменьш|пониз|опуст|сократ)`,
|
||||
"i",
|
||||
),
|
||||
new RegExp(
|
||||
// The lookahead keeps the past tense out: «дозу повысили» is a record,
|
||||
// «повысьте дозу» is a prescription.
|
||||
`(?:увелич|повыс|подним|нараст|сниз|уменьш|пониз|опуст|сократ)(?!и?л)[а-яё]*[^.?!]{0,40}[\\d.,]+\\s*${DOSE_UNIT}${UNIT_END}`,
|
||||
`(?:увелич|повыс|подним|нараст|сниз|уменьш|пониз|опуст|сократ)(?!и?л)[а-яё]*${RU_GAP(40)}[\\d.,]+\\s*${DOSE_UNIT}${UNIT_END}(?!\\s*${RU_DIET})`,
|
||||
"i",
|
||||
),
|
||||
new RegExp(
|
||||
`(?:рекоменд|совету|предлаг|стоит|нужно|следует|можно)[^.?!]{0,40}[\\d.,]+\\s*${DOSE_UNIT}${UNIT_END}`,
|
||||
`(?:рекоменд|совету|предлаг|стоит|нужно|следует|можно)${RU_GAP(40)}[\\d.,]+\\s*${DOSE_UNIT}${UNIT_END}(?!\\s*${RU_DIET})`,
|
||||
"i",
|
||||
),
|
||||
new RegExp(
|
||||
`[\\d.,]+\\s*${DOSE_UNIT}${UNIT_END}[^.?!]{0,40}(?:рекоменд|совету|предлаг|стоит|принимайте|примите|начните|перейдите)`,
|
||||
`[\\d.,]+\\s*${DOSE_UNIT}${UNIT_END}${RU_GAP(40)}(?:рекоменд|совету|предлаг|стоит|принимайте|примите|начните|перейдите)`,
|
||||
"i",
|
||||
),
|
||||
new RegExp(
|
||||
|
||||
@@ -20,7 +20,7 @@ export const COUNT_UNIT =
|
||||
* units plus the count forms; `ml` is left out on purpose because
|
||||
* "increase your water intake to 2000 ml" is ordinary hydration advice.
|
||||
*/
|
||||
export const DRUG_UNIT = `(?:mg|mcg|µg|iu|ui|i\\.u\\.|units?|unidades?|unità|unités?|jednostek|jednostki|eenheden|eenheid|ie|i\\.e\\.|einheiten|мкг|мг|мл|ед|ме|${COUNT_UNIT})`;
|
||||
export const DRUG_UNIT = `(?:mg|mcg|µg|iu|ui|i\\.u\\.|units?|unidades?|unità|unités?|jednostek|jednostki|eenheden|eenheid|ie|i\\.e\\.|einheiten|мкг|мг|ед|ме|${COUNT_UNIT})`;
|
||||
|
||||
/**
|
||||
* Dose units, shared across every locale. The GLP-1 + general oral-dose
|
||||
@@ -28,7 +28,7 @@ export const DRUG_UNIT = `(?:mg|mcg|µg|iu|ui|i\\.u\\.|units?|unidades?|unità|u
|
||||
* insulin-unit spellings the locales use (`eenheden` is the Dutch one, `ui`
|
||||
* the Portuguese abbreviation of "unidades internacionais").
|
||||
*/
|
||||
export const DOSE_UNIT = `(?:ml|${DRUG_UNIT})`;
|
||||
export const DOSE_UNIT = `(?:ml|мл|${DRUG_UNIT})`;
|
||||
|
||||
/**
|
||||
* What may follow a dose unit. A concentration is a lab value, not a dose:
|
||||
@@ -36,9 +36,11 @@ export const DOSE_UNIT = `(?:ml|${DRUG_UNIT})`;
|
||||
* medication, and a bare `\b` let both trip the "try … N mg" pattern. A
|
||||
* per-day or per-kilogram rate ("2000 mg/day", "10 mg/kg") IS a dose and still
|
||||
* matches. The lookahead also ends a unit that closes on a non-word letter
|
||||
* ("unità", "i.e.") where `\b` cannot.
|
||||
* ("unità", "i.e.") where `\b` cannot. Cyrillic counts as a letter here:
|
||||
* `\w` is ASCII-only, so without it «3 месяца» read as "3 МЕ".
|
||||
*/
|
||||
export const UNIT_END = "(?!\\w|\\s*\\/\\s*(?:dl|l|min|mmol)\\b)";
|
||||
export const UNIT_END =
|
||||
"(?![\\w\\u0400-\\u04FF]|\\s*\\/\\s*(?:dl|l|min|mmol)\\b)";
|
||||
|
||||
/**
|
||||
* One to four words of object between a change verb and its target — "your
|
||||
|
||||
Reference in new issue
Block a user