Skip to content

Commit a718753

Browse files
authored
feat: add Japanese support (#140)
1 parent 1e8d0f9 commit a718753

File tree

12 files changed

+671
-15
lines changed

12 files changed

+671
-15
lines changed

assets/cli_demo.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,27 @@
2727
4. **Avoid Repetition**: Provide new information or in-depth content, avoiding repetition of what the user already knows.
2828
5. **Flexible Adjustment**: Dynamically adjust your response style based on user feedback and the context of the conversation.'''
2929

30+
SYS_PROMPT_JA = '''あなたは、パーソナライズされた、親しみやすく、役立つサービスを提供することを目的とした知的なアシスタントです。以下の原則を遵守してください:
31+
1. **パーソナライゼーション**:ユーザーの興味や背景(例: ${user_interests})に基づいて提案を行ってください。ただし、プライバシー侵害は避けてください。
32+
2. **友好的な対話**: 忍耐強く温かい口調を保ち、ユーザーが尊重されサポートされていると感じられるようにしてください。
33+
3. **関連性のある提案**: 適切なタイミングで、ユーザーの興味に関連する有益な提案や話題(例: 食物、旅行)を共有してください。
34+
4. **繰り返しの回避**:ユーザーが既に知っている情報の繰り返しを避け、新しい情報や深い内容を提供してください。
35+
5. **柔軟な調整**:ユーザーのフィードバックや会話の文脈に基づき、応答スタイルを動的に調整してください。'''
36+
3037
_WELCOME_MSG = """Welcome to Memobase, a user profile-based memory system. Type text to chat, :h for help.
31-
(欢迎使用 Memobase,基于用户档案的记忆系统。输入内容开始对话,:h 获取帮助。)"""
38+
(欢迎使用 Memobase,基于用户档案的记忆系统。输入内容开始对话,:h 获取帮助。)
39+
(ユーザープロファイルベースのメモリシステム、Memobaseへようこそ。テキストを入力してチャット、:h でヘルプを表示。)"""
3240
_HELP_MSG = """\
3341
Commands:
34-
:help / :h Show this help message 显示帮助信息
35-
:exit / :quit / :q Exit the demo 退出Demo
36-
:clear / :cl Clear screen 清屏
37-
:clear-history / :clh Clear history 清除对话历史
38-
:history / :his Show history 显示对话历史
39-
:user Show user id 显示用户ID
40-
:user <id> Set user id 设置用户ID
41-
:profile / :pf Show user profile 显示用户已有的配置信息
42-
:flush / :fl Flush buffer 刷新缓冲区
42+
:help / :h Show this help message 显示帮助信息 ヘルプを表示
43+
:exit / :quit / :q Exit the demo 退出Demo デモを終了
44+
:clear / :cl Clear screen 清屏 ターミナルをクリア
45+
:clear-history / :clh Clear history 清除对话历史 ヒストリーを表示
46+
:history / :his Show history 显示对话历史 ヒストリーを表示
47+
:user Show user id 显示用户ID ユーザIDを表示
48+
:user <id> Set user id 设置用户ID ユーザIDを設定
49+
:profile / :pf Show user profile 显示用户已有的配置信息 ユーザのプロファイルを表示
50+
:flush / :fl Flush buffer 刷新缓冲区 バッファをフラッシュ
4351
"""
4452
_ALL_COMMAND_NAMES = [
4553
"help",
@@ -107,6 +115,8 @@ def _get_args():
107115
print("You should set OPENAI_API_KEY environment variable or pass --openai-api-key argument.")
108116
if args.language == 'zh':
109117
args.sys_prompt = SYS_PROMPT_ZH
118+
elif args.language == 'ja':
119+
args.sys_prompt = SYS_PROMPT_JA
110120
else:
111121
args.sys_prompt = SYS_PROMPT_EN
112122
return args
@@ -232,7 +242,7 @@ def _launch_demo(args):
232242
base_url=args.openai_base_url,
233243
)
234244
mb_client = MemoBaseClient(
235-
args.memobase_endpoint,
245+
project_url=args.memobase_endpoint,
236246
api_key=args.memobase_token
237247
)
238248
client = openai_memory(client, mb_client)

docs/site/references/local_config.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ minimum_chats_token_size_for_event_summary: 256
6262
- `use_timezone`: string, default to `null`. Options include `"UTC"`, `"America/New_York"`, `"Europe/London"`, `"Asia/Tokyo"`, and `"Asia/Shanghai"`. If not set, the system's local timezone is used.
6363

6464
### LLM Configuration
65-
- `language`: string, default to `"en"`, available options `{"en", "zh"}`. The prompt language of Memobase.
65+
- `language`: string, default to `"en"`, available options `{"en", "zh", "ja"}`. The prompt language of Memobase.
6666
- `llm_style`: string, default to `"openai"`, available options `{"openai", "doubao_cache"}`. The LLM provider style.
6767
- `llm_base_url`: string, default to `null`. The base URL of any OpenAI-Compatible API.
6868
- `llm_api_key`: string, required. Your LLM API key.

src/server/api/memobase_server/controllers/modal/chat/types.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
zh_merge_profile,
1212
zh_summary_entry_chats,
1313
zh_merge_profile_yolo,
14+
ja_user_profile_topics,
15+
ja_extract_profile,
16+
ja_merge_profile,
17+
ja_summary_entry_chats,
18+
ja_merge_profile_yolo,
1419
)
1520
from ....models.response import ProfileData
1621

@@ -52,4 +57,12 @@
5257
"merge_yolo": zh_merge_profile_yolo,
5358
"organize": organize_profile,
5459
},
60+
"ja": {
61+
"entry_summary": ja_summary_entry_chats,
62+
"profile": ja_user_profile_topics,
63+
"extract": ja_extract_profile,
64+
"merge": ja_merge_profile,
65+
"merge_yolo": ja_merge_profile_yolo,
66+
"organize": organize_profile,
67+
},
5568
}

src/server/api/memobase_server/controllers/modal/roleplay/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
"detect_interest": zh_detect_interest,
1414
"infer_plot": zh_infer_plot,
1515
},
16+
"ja": {},
1617
}

src/server/api/memobase_server/env.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class Config:
9191
cache_user_profiles_ttl: int = 60 * 20 # 20 minutes
9292

9393
# LLM
94-
language: Literal["en", "zh"] = "en"
94+
language: Literal["en", "zh", "ja"] = "en"
9595
llm_style: Literal["openai", "doubao_cache"] = "openai"
9696
llm_base_url: str = None
9797
llm_api_key: str = None
@@ -227,7 +227,7 @@ def timezone(self) -> timezone:
227227

228228
@dataclass
229229
class ProfileConfig:
230-
language: Literal["en", "zh"] = None
230+
language: Literal["en", "zh", "ja"] = None
231231
profile_strict_mode: bool | None = None
232232
profile_validate_mode: bool | None = None
233233
additional_user_profiles: list[dict] = field(default_factory=list)
@@ -237,7 +237,7 @@ class ProfileConfig:
237237
event_tags: list[dict] = None
238238

239239
def __post_init__(self):
240-
if self.language not in ["en", "zh"]:
240+
if self.language not in ["en", "zh", "ja"]:
241241
self.language = None
242242
if self.additional_user_profiles:
243243
[UserProfileTopic(**up) for up in self.additional_user_profiles]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from . import (
22
extract_profile,
33
zh_extract_profile,
4+
ja_extract_profile,
45
merge_profile,
56
zh_merge_profile,
7+
ja_merge_profile,
68
organize_profile,
79
summary_profile,
810
)

src/server/api/memobase_server/prompts/chat_context_pack.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,21 @@ def zh_context_prompt(profile_section: str, event_section: str) -> str:
2929
"""
3030

3131

32+
def ja_context_prompt(profile_section: str, event_section: str) -> str:
33+
return f"""---
34+
# メモリ
35+
ユーザーから関連する質問がない限り、これらのメモリについて会話の中で積極的に言及しないでください。
36+
## ユーザーの現在のプロフィール:
37+
{profile_section}
38+
39+
## 過去のイベント:
40+
{event_section}
41+
---
42+
"""
43+
44+
3245
CONTEXT_PROMPT_PACK: dict[str, ContextPromptFunc] = {
3346
"en": en_context_prompt,
3447
"zh": zh_context_prompt,
48+
"ja": ja_context_prompt,
3549
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
from . import ja_user_profile_topics
2+
from ..models.response import AIUserProfiles
3+
from ..env import CONFIG, LOG
4+
from .utils import pack_profiles_into_string
5+
6+
ADD_KWARGS = {
7+
"prompt_id": "ja_extract_profile",
8+
}
9+
10+
EXAMPLES = [
11+
(
12+
"""- ユーザーがアシスタントに挨拶した。
13+
""",
14+
AIUserProfiles(**{"facts": []}),
15+
),
16+
(
17+
"""
18+
- ユーザーの好きな映画は『インセプション』と『インターステラー』 [2025/01/01に言及]
19+
- ユーザーの一番好きな映画は『TENET テネット』 [2025/01/02に言及]
20+
""",
21+
AIUserProfiles(
22+
**{
23+
"facts": [
24+
{
25+
"topic": "興味",
26+
"sub_topic": "映画",
27+
"memo": "『インセプション』、『インターステラー』[2025/01/01に言及];一番好きな映画は『TENET テネット』[2025/01/02に言及]",
28+
},
29+
{
30+
"topic": "興味",
31+
"sub_topic": "映画監督",
32+
"memo": "ユーザーはクリスチャン・ノーラン監督の大ファンだと思われる",
33+
},
34+
]
35+
}
36+
),
37+
),
38+
]
39+
40+
DEFAULT_JOB = """あなたはプロの心理学者です。
41+
あなたの仕事は、ユーザーのメモを詳細に読み、構造化された形式でユーザーの重要なプロフィールを抽出することです。
42+
次に、関連する重要な事実、ユーザーの好みを抽出します。これらの情報は、ユーザーの状態を評価するのに役立ちます。
43+
あなたは、明示された情報を抽出するだけでなく、会話中に暗示されている情報も推測する必要があります。
44+
これらの情報を記録する際は、ユーザーが入力した言語と同じ言語を使用してください。
45+
"""
46+
47+
FACT_RETRIEVAL_PROMPT = """{system_prompt}
48+
49+
## フォーマット
50+
### 入力
51+
#### トピックガイドライン
52+
あなたには、収集・抽出に集中すべき、ユーザーに関連するトピックとサブトピックの一覧が与えられます。
53+
ユーザーに関連しないトピックについては、情報の混乱を招く可能性があるため、収集しないでください。
54+
例えば、メモに他人の職位が言及されている場合、"仕事{tab}職位"というトピックを生成しないでください。
55+
必要なら、新しいトピック/サブトピックを作成しても構いません。ただしユーザーが禁止していない場合に限ります。
56+
57+
#### 既存のトピック
58+
あなたには、ユーザーとアシスタント間ですでに共有されている、トピックとサブトピックの一覧が与えられます。
59+
会話の中でそれらが再度言及された場合は、同じものを使うことを検討してください。
60+
61+
#### メモ
62+
あなたには、ユーザーに関する情報・出来事・好みなどを含む、Markdown形式のメモが与えられます。
63+
このメモは、ユーザーとアシスタントの会話から要約されたものです。
64+
65+
### 出力
66+
#### 思考
67+
あなたは、メモにはどのようなトピックやサブトピックが言及されているか?また、そのメモからどのような示唆を推測できるか?を考える必要があります。
68+
#### プロフィール
69+
70+
あなたの思考プロセスの後、あなたは、メモから事実と好みを抽出し、順序付きリストに整理する必要があります:
71+
- TOPIC{tab}SUB_TOPIC{tab}MEMO
72+
例:
73+
- 基本情報{tab}氏名{tab}メリンダ
74+
- 仕事{tab}役職{tab}ソフトウェアエンジニア
75+
76+
各行は1つの事実または好みを表し、以下を含みます:
77+
1. TOPIC: 大分類(例: 基本情報、仕事、興味 など)
78+
2. SUB_TOPIC: 詳細分類(例: 氏名、役職、映画 など)
79+
3. MEMO: 「ユーザー」に関する抽出結果。メモに時間情報が含まれる場合は[...]で表記。
80+
これらは `{tab}` で区切り、各行は "- " で始めて`\n`で改行区切りにしてください。
81+
82+
最終出力テンプレート:
83+
```
84+
POSSIBLE TOPICS THINKING
85+
---
86+
- TOPIC{tab}SUB_TOPIC{tab}MEMO
87+
- ...
88+
```
89+
90+
## 抽出例
91+
いくつかの例を示します:
92+
{examples}
93+
上記のMarkdown形式のリストフォーマットで事実と好みを返してください。
94+
実際の値を持つ属性のみを抽出してください。ユーザーが値を提供しない場合は抽出しないでください。
95+
あなたは、まず最初に思考して、そして、メモから事実と好みを抽出する必要があります。
96+
97+
#### トピック指針
98+
以下はあなたが収集・抽出に集中すべきトピックとサブトピックの一覧です:
99+
{topic_examples}
100+
101+
以下を念頭に置いてください:
102+
- もしユーザが日時に関連する情報を発言している場合は、データから具体的な日付を推定してください。
103+
- 日付は可能な限り具体的な日付を使用してください。「今日」「昨日」のような相対表現は使用しないでください。
104+
- 以下の会話に関連する情報が見つからなければ、空のリストを返しても構いません。
105+
- フォーマットと抽出例セクションに記載されている形式でレスポンスを返すことを厳守してください。
106+
- 明示的に発言された内容だけでなく、会話から暗示されることを推測してください。
107+
- 同一トピック/サブトピックに属する内容は1要素にまとめ、重複を避けてください。
108+
- メモに含まれる日時は2つの種類があります。1つはメモが「言及された日時」、もう1つはメモ内の「イベントが発生した日時」です。どちらも重要です。混同しないようにしてください。日時情報を正確に抽出し、関連するメモの後に時間表記を[...]を使用して記述する必要があります。
109+
- 実際の値を持つ属性のみを抽出してください。ユーザーが値を提供していない場合は、抽出しないでください。
110+
111+
では、あなたのタスクを遂行してください。
112+
以下はユーザーとアシスタントの会話です。会話から関連する事実と好みを抽出・推測して、上記のリスト形式で返してください。
113+
ユーザーが入力した言語を検出し、同じ言語で記録してください。
114+
"""
115+
116+
117+
def pack_input(already_input, chat_strs, strict_mode: bool = False):
118+
header = ""
119+
if strict_mode:
120+
header = "#### トピックガイドラインに記載されていないトピック/サブトピックを抽出しないでください。そうしないと、あなたの回答は無効になります!"
121+
return f"""{header}
122+
#### 既存のトピック
123+
関連するトピック/サブトピックを抽出する場合は、以下のトピック/サブトピックの命名規則を検討してください:
124+
{already_input}
125+
126+
#### メモ
127+
メモに記載されていないトピック/サブトピックに関する情報は一切出力しないでください。
128+
{chat_strs}
129+
"""
130+
131+
132+
def get_default_profiles() -> str:
133+
return ja_user_profile_topics.get_prompt()
134+
135+
136+
def get_prompt(topic_examples: str) -> str:
137+
sys_prompt = CONFIG.system_prompt or DEFAULT_JOB
138+
examples = "\n\n".join(
139+
[
140+
f"""<example>
141+
<input>{p[0]}</input>
142+
<output>
143+
{pack_profiles_into_string(p[1])}
144+
</output>
145+
</example>
146+
"""
147+
for p in EXAMPLES
148+
]
149+
)
150+
return FACT_RETRIEVAL_PROMPT.format(
151+
system_prompt=sys_prompt,
152+
examples=examples,
153+
tab=CONFIG.llm_tab_separator,
154+
topic_examples=topic_examples,
155+
)
156+
157+
158+
def get_kwargs() -> dict:
159+
return ADD_KWARGS
160+
161+
162+
if __name__ == "__main__":
163+
print(get_prompt(get_default_profiles()))

0 commit comments

Comments
 (0)