feat: support translate message to current language (#340)

* 🚚 refactor: rename prompts to chains

* ♻️ refactor: refactor Message Actions

* ♻️ refactor: add translate action

*  feat: support translate

* ♻️ refactor: refactor part of common locale to chat

* 🌐 style: update i18n
This commit is contained in:
Arvin Xu
2023-10-18 14:58:02 +08:00
committed by GitHub
parent 33c0853466
commit cf15f1ebff
78 changed files with 1111 additions and 559 deletions
+55
View File
@@ -0,0 +1,55 @@
{
"agentDefaultMessage": "Hello, I'm **{{name}}**. You can start chatting with me right away or go to [Assistant Settings](/chat/settings#session={{id}}) to improve my information.",
"agentDefaultMessageWithSystemRole": "Hello, I'm **{{name}}**, {{systemRole}}. Let's start the conversation!",
"backToBottom": "Go to Latest Messages",
"clearCurrentMessages": "Clear Current Session Messages",
"confirmClearCurrentMessages": "You are about to clear the current session messages. Once cleared, they cannot be recovered. Please confirm your operation.",
"confirmRemoveSessionItemAlert": "You are about to delete this assistant. Once deleted, it cannot be recovered. Please confirm your operation.",
"defaultAgent": "Custom Assistant",
"defaultSession": "Custom Assistant",
"historyRange": "History Range",
"inbox": {
"defaultMessage": "Hello, I'm your intelligent assistant. You can ask me any questions, and I will do my best to answer you. If you need a more professional or customized assistant, you can click on `+` to create a custom assistant.",
"desc": "Activate brain clusters and spark thinking. Your intelligent assistant is here to communicate with you about everything.",
"title": "Chat Randomly"
},
"newAgent": "Create New Assistant",
"noDescription": "No description available",
"regenerate": "Regenerate",
"roleAndArchive": "Roles and Archives",
"searchAgentPlaceholder": "Search assistants and conversations...",
"send": "Send",
"sendPlaceholder": "Enter chat content...",
"shareModal": {
"download": "Download Screenshot",
"imageType": "Image Format",
"screenshot": "Screenshot",
"settings": "Export Settings",
"shareToShareGPT": "Generate ShareGPT Sharing Link",
"withBackground": "Include Background Image",
"withFooter": "Include Footer",
"withPluginInfo": "Include Plugin Information",
"withSystemRole": "Include Assistant Role Setting"
},
"stop": "Stop",
"temp": "Temporary",
"tokenDetail": "Role Setting: {{systemRoleToken}} · Chat History: {{chatsToken}}",
"tokenTag": {
"overload": "Exceeded Limit",
"remained": "Remaining",
"used": "Used"
},
"topic": {
"confirmRemoveTopic": "You are about to delete this topic. Once deleted, it cannot be recovered. Please proceed with caution.",
"defaultTitle": "Default Topic",
"saveCurrentMessages": "Save Current Session as Topic",
"searchPlaceholder": "Search topics...",
"title": "Topic"
},
"translate": {
"clear": "Clear Translation"
},
"translateTo": "Translate",
"updateAgent": "Update Assistant Information",
"warp": "Line Break"
}
+17 -51
View File
@@ -1,24 +1,19 @@
{
"about": "About",
"advanceSettings": "Advanced Settings",
"agentDefaultMessage": "Hello, I'm **{{name}}**. You can start chatting with me right away or go to [Agent Settings](/chat/settings#session={{id}}) to complete my information.",
"agentDefaultMessageWithSystemRole": "Hello, I'm **{{name}}**, {{systemRole}}. Let's start chatting!",
"agentMaxToken": "Max Session Length",
"agentModel": "Model",
"agentProfile": "Agent Information",
"agentProfile": "Agent Profile",
"appInitializing": "LobeChat is initializing, please wait...",
"archive": "Archive",
"autoGenerate": "Auto Generate",
"autoGenerateTooltip": "Auto generate agent description based on prompts",
"backToBottom": "Go to Latest Messages",
"cancel": "Cancel",
"changelog": "Changelog",
"clearCurrentMessages": "Clear Current Session Messages",
"close": "Close",
"confirmClearCurrentMessages": "You are about to clear the current session messages. Once cleared, they cannot be recovered. Please confirm your operation.",
"confirmRemoveSessionItemAlert": "You are about to delete this agent. Once deleted, it cannot be recovered. Please confirm your operation.",
"confirmRemoveSessionItemAlert": "You are about to delete this agent. Once deleted, it cannot be recovered. Please confirm your action.",
"copy": "Copy",
"copySuccess": "Copy Success",
"copySuccess": "Copy Successful",
"defaultAgent": "Custom Agent",
"defaultSession": "Custom Agent",
"delete": "Delete",
@@ -35,17 +30,18 @@
"feedback": "Feedback",
"historyRange": "History Range",
"import": "Import Configuration",
"inbox": {
"defaultMessage": "Hello, I'm your intelligent agent. You can ask me any questions and I will do my best to answer you. If you need a more professional or customized agent, you can click `+` to create a custom agent.",
"desc": "Activate the brain cluster and spark your thinking. Your intelligent agent is here to communicate with you about everything.",
"title": "Chat Freely"
"lang": {
"en": "English",
"en-US": "English",
"ja-JP": "Japanese",
"ko-KR": "Korean",
"ru-RU": "Russian",
"zh": "Simplified Chinese",
"zh-CN": "Simplified Chinese",
"zh-TW": "Traditional Chinese"
},
"message": {
"function_loading": "Plugin request in progress..."
},
"moreSetting": "More Settings...",
"newAgent": "New Agent",
"noDescription": "No Description",
"layoutInitializing": "Loading layout...",
"noDescription": "No description",
"ok": "OK",
"password": "Password",
"pin": "Pin",
@@ -54,51 +50,21 @@
"rename": "Rename",
"reset": "Reset",
"retry": "Retry",
"roleAndArchive": "Roles and Archives",
"searchAgentPlaceholder": "Search Agents and Conversations...",
"send": "Send",
"sendPlaceholder": "Enter chat content...",
"sessionList": "Agent List",
"setting": "Settings",
"share": "Share",
"shareModal": {
"download": "Download Screenshot",
"imageType": "Image Type",
"screenshot": "Screenshot",
"settings": "Export Settings",
"withBackground": "Include Background Image",
"withPluginInfo": "Include Plugin Information",
"withSystemRole": "Include Agent Role Setting",
"withFooter": "Including footer",
"shareToShareGPT": "Generate ShareGPT sharing link"
},
"stop": "Stop",
"switchMobileLayout": "Switching to mobile layout...",
"tab": {
"chat": "Chat",
"market": "Discover",
"setting": "Settings"
},
"temp": "Temporary",
"tokenDetail": "Role Setting: {{systemRoleToken}} · Message History: {{chatsToken}}",
"tokenTag": {
"overload": "Exceeded Limit",
"remained": "Remaining",
"used": "Used"
},
"topic": {
"confirmRemoveTopic": "You are about to delete this topic. Once deleted, it cannot be recovered. Please proceed with caution.",
"defaultTitle": "Default Topic",
"saveCurrentMessages": "Save the current session as a topic",
"searchPlaceholder": "Search Topics...",
"title": "Topic"
},
"updateAgent": "Update Agent Information",
"updatePrompt": "Update Prompts",
"updateAgent": "Update Agent Profile",
"upgradeVersion": {
"action": "Upgrade Now",
"hasNew": "New Update Available",
"hasNew": "Update available",
"newVersion": "New version available: {{version}}"
},
"warp": "Line break"
}
}
+55
View File
@@ -0,0 +1,55 @@
{
"agentDefaultMessage": "こんにちは、私は **{{name}}** です。すぐに会話を始めることができますし、[エージェント設定](/chat/settings#session={{id}}) に移動して私の情報を充実させることもできます。",
"agentDefaultMessageWithSystemRole": "こんにちは、私は **{{name}}** です、{{systemRole}}、さあ、会話を始めましょう!",
"backToBottom": "最新のメッセージを表示",
"clearCurrentMessages": "現在の会話メッセージをクリア",
"confirmClearCurrentMessages": "現在の会話メッセージをクリアします。クリア後は元に戻すことはできませんので、操作を確認してください",
"confirmRemoveSessionItemAlert": "このエージェントを削除します。削除後は元に戻すことはできませんので、操作を確認してください",
"defaultAgent": "デフォルトエージェント",
"defaultSession": "デフォルトエージェント",
"historyRange": "履歴範囲",
"inbox": {
"defaultMessage": "こんにちは、私はあなたのインテリジェントアシスタントです。何でも質問してください、できる限りお答えします。より専門的またはカスタマイズされたアシスタントが必要な場合は、`+` をクリックしてカスタムエージェントを作成できます",
"desc": "ブレインクラスタを起動し、思考の火花を引き起こします。あなたのインテリジェントアシスタントは、ここであなたとすべてを話します",
"title": "ちょっとおしゃべりしましょう"
},
"newAgent": "新しいエージェントを作成",
"noDescription": "説明はありません",
"regenerate": "再生成",
"roleAndArchive": "役割とアーカイブ",
"searchAgentPlaceholder": "エージェントと会話を検索...",
"send": "送信",
"sendPlaceholder": "チャット内容を入力...",
"shareModal": {
"download": "スクリーンショットをダウンロード",
"imageType": "画像形式",
"screenshot": "スクリーンショット",
"settings": "エクスポート設定",
"shareToShareGPT": "ShareGPT共有リンクを生成",
"withBackground": "背景画像を含む",
"withFooter": "フッターを含む",
"withPluginInfo": "プラグイン情報を含む",
"withSystemRole": "エージェントの役割設定を含む"
},
"stop": "停止",
"temp": "一時",
"tokenDetail": "役割設定: {{systemRoleToken}} · チャット履歴: {{chatsToken}}",
"tokenTag": {
"overload": "制限を超えています",
"remained": "残り",
"used": "使用済み"
},
"topic": {
"confirmRemoveTopic": "このトピックを削除します。削除後は元に戻すことはできませんので、注意して操作してください",
"defaultTitle": "デフォルトトピック",
"saveCurrentMessages": "現在の会話をトピックとして保存",
"searchPlaceholder": "トピックを検索...",
"title": "トピック"
},
"translate": {
"clear": "翻訳をクリア"
},
"translateTo": "翻訳",
"updateAgent": "エージェント情報を更新",
"warp": "改行"
}
+14 -48
View File
@@ -1,22 +1,17 @@
{
"about": "について",
"advanceSettings": "詳細設定",
"agentDefaultMessage": "こんにちは、私は **{{name}}** です。すぐにチャットを始めることができますし、[エージェント設定](/chat/settings#session={{id}}) に移動して私の情報を完全にすることもできます。",
"agentDefaultMessageWithSystemRole": "こんにちは、私は **{{name}}** です。{{systemRole}}、さあ、チャットを始めましょう!",
"agentMaxToken": "セッションの最大トークン数",
"agentModel": "モデル",
"agentProfile": "エージェント情報",
"appInitializing": "LobeChat を起動しています。お待ちください...",
"appInitializing": "LobeChatを起動中です。お待ちください...",
"archive": "アーカイブ",
"autoGenerate": "自動生成",
"autoGenerateTooltip": "ヒントワードに基づいてエージェントの説明を自動生成します",
"backToBottom": "最新メッセージを表示",
"cancel": "キャンセル",
"changelog": "更新履歴",
"clearCurrentMessages": "現在のセッションのメッセージをクリア",
"close": "閉じる",
"confirmClearCurrentMessages": "現在のセッションのメッセージをクリアします。クリア後は元に戻すことはできませんので、操作を確認してください",
"confirmRemoveSessionItemAlert": "このエージェントを削除します。削除後は元に戻すことはできませんので、操作を確認してください",
"confirmRemoveSessionItemAlert": "このエージェントを削除します。削除後は元に戻すことはできません操作を確認してください",
"copy": "コピー",
"copySuccess": "コピーが成功しました",
"defaultAgent": "デフォルトエージェント",
@@ -35,16 +30,17 @@
"feedback": "フィードバック",
"historyRange": "履歴範囲",
"import": "設定のインポート",
"inbox": {
"defaultMessage": "こんにちは、私はあなたのインテリジェントエージェントです。何でも質問してください、できる限りお答えします。より専門的でカスタマイズされたエージェントが必要な場合は、`+` をクリックしてカスタムエージェントを作成できます",
"desc": "ブレインクラスタを起動し、思考の火花を引き起こします。あなたのインテリジェントアシスタントとのすべてのコミュニケーションはここで行われます",
"title": "気軽にチャット"
"lang": {
"en": "英語",
"en-US": "英語",
"ja-JP": "日本語",
"ko-KR": "韓国語",
"ru-RU": "ロシア語",
"zh": "簡体中国語",
"zh-CN": "簡体中国語",
"zh-TW": "繁体中国語"
},
"message": {
"function_loading": "プラグインリクエスト中..."
},
"moreSetting": "その他の設定...",
"newAgent": "新しいエージェント",
"layoutInitializing": "レイアウトを読み込んでいます...",
"noDescription": "説明はありません",
"ok": "OK",
"password": "パスワード",
@@ -54,51 +50,21 @@
"rename": "名前の変更",
"reset": "リセット",
"retry": "再試行",
"roleAndArchive": "役割とアーカイブ",
"searchAgentPlaceholder": "エージェントとチャットを検索...",
"send": "送信",
"sendPlaceholder": "チャット内容を入力...",
"sessionList": "エージェントリスト",
"setting": "設定",
"share": "共有",
"shareModal": {
"download": "ダウンロード",
"imageType": "画像形式",
"screenshot": "スクリーンショット",
"settings": "設定をエクスポート",
"shareToShareGPT": "ShareGPT共有リンクを生成",
"withBackground": "背景画像を含む",
"withFooter": "フッターを含む",
"withPluginInfo": "プラグイン情報を含む",
"withSystemRole": "アシスタントの役割設定を含む"
},
"stop": "停止",
"switchMobileLayout": "モバイルレイアウトに切り替え中...",
"tab": {
"chat": "チャット",
"market": "発見",
"setting": "設定"
},
"temp": "一時的な",
"tokenDetail": "役割設定: {{systemRoleToken}} · チャット履歴: {{chatsToken}}",
"tokenTag": {
"overload": "制限を超える",
"remained": "残り",
"used": "使用済み"
},
"topic": {
"confirmRemoveTopic": "このトピックを削除しますか?削除後は元に戻せませんので、注意して操作してください。",
"defaultTitle": "デフォルトトピック",
"saveCurrentMessages": "現在のチャットをトピックとして保存",
"searchPlaceholder": "トピックを検索...",
"title": "トピック"
},
"updateAgent": "アシスタント情報を更新",
"updatePrompt": "プロンプトの更新",
"updateAgent": "エージェント情報の更新",
"upgradeVersion": {
"action": "今すぐアップグレード",
"hasNew": "利用可能な更新があります",
"newVersion": "新しいバージョンが利用可能です:{{version}}"
},
"warp": "改行"
}
}
+55
View File
@@ -0,0 +1,55 @@
{
"agentDefaultMessage": "안녕하세요, 저는 **{{name}}**입니다. 바로 대화를 시작하거나 [도우미 설정](/chat/settings#session={{id}})으로 이동하여 제 정보를 완성할 수 있습니다.",
"agentDefaultMessageWithSystemRole": "안녕하세요, 저는 **{{name}}**입니다. {{systemRole}}입니다. 대화를 시작해보세요!",
"backToBottom": "최신 메시지 보기",
"clearCurrentMessages": "현재 대화 지우기",
"confirmClearCurrentMessages": "현재 대화를 지우시겠습니까? 지우면 복구할 수 없습니다. 작업을 확인하세요.",
"confirmRemoveSessionItemAlert": "도우미를 삭제하시겠습니까? 삭제하면 복구할 수 없습니다. 작업을 확인하세요.",
"defaultAgent": "사용자 정의 도우미",
"defaultSession": "사용자 정의 도우미",
"historyRange": "기록 범위",
"inbox": {
"defaultMessage": "안녕하세요, 저는 여러분의 인공지능 도우미입니다. 궁금한 점이 있으면 물어보세요. 더 전문적이거나 맞춤화된 도우미가 필요하다면 `+`를 클릭하여 사용자 정의 도우미를 생성할 수 있습니다.",
"desc": "뇌 클러스터를 활성화하여 창의적인 생각을 이끌어내는 인공지능 도우미입니다. 모든 것에 대해 여기에서 대화하세요.",
"title": "잡담하기"
},
"newAgent": "새 도우미 만들기",
"noDescription": "설명 없음",
"regenerate": "재생성",
"roleAndArchive": "역할 및 아카이브",
"searchAgentPlaceholder": "도우미 및 대화 검색...",
"send": "보내기",
"sendPlaceholder": "대화 내용 입력...",
"shareModal": {
"download": "스크린샷 다운로드",
"imageType": "이미지 형식",
"screenshot": "스크린샷",
"settings": "내보내기 설정",
"shareToShareGPT": "ShareGPT 공유 링크 생성",
"withBackground": "배경 이미지 포함",
"withFooter": "푸터 포함",
"withPluginInfo": "플러그인 정보 포함",
"withSystemRole": "도우미 역할 포함"
},
"stop": "정지",
"temp": "임시",
"tokenDetail": "역할 설정: {{systemRoleToken}} · 대화 기록: {{chatsToken}}",
"tokenTag": {
"overload": "한도 초과",
"remained": "남음",
"used": "사용"
},
"topic": {
"confirmRemoveTopic": "해당 주제를 삭제하시겠습니까? 삭제하면 복구할 수 없습니다. 신중하게 작업하세요.",
"defaultTitle": "기본 주제",
"saveCurrentMessages": "현재 대화를 주제로 저장",
"searchPlaceholder": "주제 검색...",
"title": "주제"
},
"translate": {
"clear": "번역 지우기"
},
"translateTo": "번역",
"updateAgent": "도우미 정보 업데이트",
"warp": "줄바꿈"
}
+25 -59
View File
@@ -1,50 +1,46 @@
{
"about": "소개",
"advanceSettings": "고급 설정",
"agentDefaultMessage": "안녕하세요, 저는 **{{name}}**입니다. 바로 대화를 시작하거나 [도우미 설정](/chat/settings#session={{id}})으로 이동하여 제 정보를 완성할 수 있습니다.",
"agentDefaultMessageWithSystemRole": "안녕하세요, 저는 **{{name}}**입니다. {{systemRole}}입니다. 대화를 시작해봅시다!",
"agentMaxToken": "세션 최대 길이",
"agentModel": "모델",
"agentProfile": "도우미 정보",
"appInitializing": "LobeChat 시작하는 중입니다. 잠시 기다려주세요...",
"archive": "보관",
"agentProfile": "에이전트 정보",
"appInitializing": "LobeChat 시작 중입니다. 잠시 기다려주세요...",
"archive": "보관",
"autoGenerate": "자동 생성",
"autoGenerateTooltip": "도우미 설명을 자동으로 성합니다.",
"backToBottom": "최신 메시지 보기",
"autoGenerateTooltip": "힌트 단어를 기반으로 에이전트 설명을 자동으로 성합니다.",
"cancel": "취소",
"changelog": "변경 내역",
"clearCurrentMessages": "현재 대화 메시지 지우기",
"close": "닫기",
"confirmClearCurrentMessages": "현재 대화 메시지를 지우시겠습니까? 지운 후에는 복구할 수 없습니다. 작업을 확인하세요.",
"confirmRemoveSessionItemAlert": "도우미를 삭제하시겠습니까? 삭제한 후에는 복구할 수 없습니다. 작업을 확인하세요.",
"confirmRemoveSessionItemAlert": "에이전트를 삭제하려고 합니다. 삭제 후에는 복구할 수 없습니다. 작업을 확인하세요.",
"copy": "복사",
"copySuccess": "복사 완료",
"defaultAgent": "기본 도우미",
"defaultSession": "기본 도우미",
"defaultAgent": "기본 에이전트",
"defaultSession": "기본 세션",
"delete": "삭제",
"edit": "편집",
"export": "설정 내보내기",
"exportType": {
"agent": "도우미 설정 내보내기",
"agentWithMessage": "도우미와 메시지 내보내기",
"all": "전역 설정 모든 도우미 데이터 내보내기",
"allAgent": "모든 도우미 설정 내보내기",
"allAgentWithMessage": "모든 도우미와 메시지 내보내기",
"agent": "에이전트 설정 내보내기",
"agentWithMessage": "에이전트 및 메시지 내보내기",
"all": "전역 설정 모든 에이전트 데이터 내보내기",
"allAgent": "모든 에이전트 설정 내보내기",
"allAgentWithMessage": "모든 에이전트 및 메시지 내보내기",
"globalSetting": "전역 설정 내보내기"
},
"feedback": "피드백",
"historyRange": "기록 범위",
"import": "설정 가져오기",
"inbox": {
"defaultMessage": "안녕하세요, 저는 인공지능 도우미입니다. 궁금한 점이 있으면 물어보세요. 가능한 한 답변해드리겠습니다. 더 전문적이거나 맞춤화된 도우미가 필요하다면 `+`를 클릭하여 사용자 정의 도우미를 만들 수 있습니다.",
"desc": "뇌 클러스터를 활성화하여 창의적인 아이디어를 끄집어내세요. 여기에서 모든 것을 대화하는 인공지능 도우미와 소통하세요.",
"title": "무작위 대화"
"lang": {
"en": "영어",
"en-US": "영어",
"ja-JP": "일본어",
"ko-KR": "한국어",
"ru-RU": "러시아어",
"zh": "중국어 간체",
"zh-CN": "중국어 간체",
"zh-TW": "중국어 번체"
},
"message": {
"function_loading": "플러그인 요청 중..."
},
"moreSetting": "추가 설정...",
"newAgent": "새 도우미",
"layoutInitializing": "레이아웃을 로드 중입니다...",
"noDescription": "설명 없음",
"ok": "확인",
"password": "비밀번호",
@@ -54,51 +50,21 @@
"rename": "이름 변경",
"reset": "재설정",
"retry": "재시도",
"roleAndArchive": "역할 및 기록",
"searchAgentPlaceholder": "도우미와 대화 검색...",
"send": "보내기",
"sendPlaceholder": "대화 내용 입력...",
"sessionList": "도우미 목록",
"sessionList": "에이전트 목록",
"setting": "설정",
"share": "공유",
"shareModal": {
"download": "스크린샷 다운로드",
"imageType": "이미지 형식",
"screenshot": "스크린샷",
"settings": "내보내기 설정",
"shareToShareGPT": "ShareGPT 공유 링크 생성",
"withBackground": "배경 이미지 포함",
"withFooter": "푸터 포함",
"withPluginInfo": "플러그인 정보 포함",
"withSystemRole": "어시스턴트 역할 포함"
},
"stop": "중지",
"switchMobileLayout": "모바일 레이아웃으로 전환 중...",
"tab": {
"chat": "채팅",
"market": "탐색",
"setting": "설정"
},
"temp": "임시",
"tokenDetail": "역할 설정: {{systemRoleToken}} · 이전 메시지: {{chatsToken}}",
"tokenTag": {
"overload": "제한 초과",
"remained": "남음",
"used": "사용됨"
},
"topic": {
"confirmRemoveTopic": "이 주제를 삭제하려고 합니다. 삭제 후에는 복구할 수 없으니 주의하세요.",
"defaultTitle": "기본 주제",
"saveCurrentMessages": "현재 대화를 주제로 저장",
"searchPlaceholder": "주제 검색...",
"title": "주제"
},
"updateAgent": "어시스턴트 정보 업데이트",
"updatePrompt": "프롬프트 문구 업데이트",
"updateAgent": "에이전트 정보 업데이트",
"upgradeVersion": {
"action": "지금 업그레이드",
"hasNew": "사용 가능한 업데이트가 있습니다",
"newVersion": "새 버전 사용 가능: {{version}}"
},
"warp": "줄바꿈"
}
}
+55
View File
@@ -0,0 +1,55 @@
{
"agentDefaultMessage": "Привет, я **{{name}}**, ты можешь начать разговор со мной прямо сейчас или перейти к [настройкам помощника](/chat/settings#session={{id}}), чтобы улучшить мою информацию.",
"agentDefaultMessageWithSystemRole": "Привет, я **{{name}}**, {{systemRole}}, давай начнем разговор!",
"backToBottom": "К последнему сообщению",
"clearCurrentMessages": "Очистить текущий разговор",
"confirmClearCurrentMessages": "Вы собираетесь очистить текущий разговор, после этого его нельзя будет восстановить. Подтвердите свое действие.",
"confirmRemoveSessionItemAlert": "Вы собираетесь удалить этого помощника, после этого его нельзя будет восстановить. Подтвердите свое действие.",
"defaultAgent": "Пользовательский помощник",
"defaultSession": "Пользовательский помощник",
"historyRange": "История сообщений",
"inbox": {
"defaultMessage": "Привет, я твой интеллектуальный помощник. Ты можешь задать мне любой вопрос, и я постараюсь ответить на него. Если тебе нужен более профессиональный или настроенный помощник, нажми на `+`, чтобы создать пользовательского помощника.",
"desc": "Включи кластер мозгов и разгори искру мысли. Твой интеллектуальный помощник, готовый общаться о всем здесь",
"title": "Просто поболтаем"
},
"newAgent": "Создать помощника",
"noDescription": "Нет описания",
"regenerate": "Сгенерировать заново",
"roleAndArchive": "Роль и архив",
"searchAgentPlaceholder": "Поиск помощников и разговоров...",
"send": "Отправить",
"sendPlaceholder": "Введите текст сообщения...",
"shareModal": {
"download": "Скачать скриншот",
"imageType": "Тип изображения",
"screenshot": "Скриншот",
"settings": "Настройки экспорта",
"shareToShareGPT": "Создать ссылку ShareGPT для обмена",
"withBackground": "С фоновым изображением",
"withFooter": "С нижним колонтитулом",
"withPluginInfo": "С информацией о плагине",
"withSystemRole": "С указанием роли помощника"
},
"stop": "Остановить",
"temp": "Временный",
"tokenDetail": "Роль помощника: {{systemRoleToken}} · История сообщений: {{chatsToken}}",
"tokenTag": {
"overload": "Превышение лимита",
"remained": "Осталось",
"used": "Использовано"
},
"topic": {
"confirmRemoveTopic": "Вы собираетесь удалить эту тему, после этого ее нельзя будет восстановить. Подтвердите свое действие.",
"defaultTitle": "Стандартная тема",
"saveCurrentMessages": "Сохранить текущий разговор как тему",
"searchPlaceholder": "Поиск темы...",
"title": "Тема"
},
"translate": {
"clear": "Очистить перевод"
},
"translateTo": "Перевести на",
"updateAgent": "Обновить информацию о помощнике",
"warp": "Перенос строки"
}
+11 -45
View File
@@ -2,20 +2,15 @@
"about": "Наш Github",
"advanceSettings": "Дополнительные настройки",
"agentDefaultMessage": "Здравствуйте, я **{{name}}**. Вы можете начать общаться со мной прямо сейчас или перейти на [Assistant Settings](/chat/settings#session={{id}}) для моей настройки.",
"agentDefaultMessageWithSystemRole": "Здравствуйте, Я **{{name}}**, {{systemRole}}. Давайте начнем общаться!",
"agentMaxToken": "Максимальная длина запроса",
"agentModel": "Модель",
"agentProfile": "Информация о помощнике",
"appInitializing": "LobeChat запускается, пожалуйста, подождите...",
"archive": "Архив",
"autoGenerate": "Автогенерация",
"autoGenerateTooltip": "Автогенерация описания помощника на основе подсказок",
"backToBottom": "Перейти к последним сообщениям",
"cancel": "Отмена",
"changelog": "Журнал изменений",
"clearCurrentMessages": "Очистить сообщения текущего сеанса",
"close": "Закрывать",
"confirmClearCurrentMessages": "Вы собираетесь удалить сообщения текущего сеанса? После очистки их невозможно восстановить. Пожалуйста, подтвердите вашу операцию.",
"confirmRemoveSessionItemAlert": "Вы собираетесь удалить этого помощника? После удаления его невозможно восстановить. Пожалуйста, подтвердите вашу операцию.",
"copy": "Копировать",
"copySuccess": "Скопировано",
@@ -35,16 +30,17 @@
"feedback": "Обратная связь",
"historyRange": "Исторический диапазон",
"import": "Импорт конфига",
"inbox": {
"defaultMessage": "Hello, I'm your intelligent assistant. You can ask me any questions and I will do my best to answer you. If you need a more professional or customized assistant, you can click `+` to create a custom assistant.",
"desc": "Activate the brain cluster and spark your thinking. Your intelligent assistant is here to communicate with you about everything.",
"title": "Chat Freely"
"lang": {
"en": "Английский",
"en-US": "Английский",
"ja-JP": "Японский",
"ko-KR": "Корейский",
"ru-RU": "Русский",
"zh": "Китайский (упрощенный)",
"zh-CN": "Китайский (упрощенный)",
"zh-TW": "Китайский (традиционный)"
},
"message": {
"function_loading": "Запрос плагина в процессе..."
},
"moreSetting": "Больше настроек...",
"newAgent": "Новый ассистент",
"layoutInitializing": "Идет загрузка макета...",
"noDescription": "Нет описания",
"ok": "ОК",
"password": "пароль",
@@ -54,51 +50,21 @@
"rename": "Переименовать",
"reset": "Сброс",
"retry": "Повторить",
"roleAndArchive": "Роли и архивы",
"searchAgentPlaceholder": "Поисковые помощники и беседы...",
"send": "Отправить",
"sendPlaceholder": "Введите ваше сообщение...",
"sessionList": "Список помощников",
"setting": "Настройки",
"share": "Поделиться",
"shareModal": {
"download": "Скачать скриншот",
"imageType": "Тип изображения",
"screenshot": "Скриншот",
"settings": "Настройки экспорта",
"withBackground": "С фоновым изображением",
"withPluginInfo": "С информацией о плагине",
"withSystemRole": "С настройками роли помощника",
"withFooter": "с подвалом",
"shareToShareGPT": "Создать ссылку для обмена ShareGPT"
},
"stop": "Остановить",
"switchMobileLayout": "Переключение на мобильный макет...",
"tab": {
"chat": "Чат",
"market": "Магазин ассистентов",
"setting": "Настройки"
},
"temp": "Временный",
"tokenDetail": "Установление ролей: {{systemRoleToken}} · История сообщений: {{chatsToken}}",
"tokenTag": {
"overload": "Превышение лимита",
"remained": "Осталось",
"used": "Использовано"
},
"topic": {
"confirmRemoveTopic": "Вы собираетесь удалить эту тему? После удаления он не может быть восстановлен. Пожалуйста, действуйте с осторожностью.",
"defaultTitle": "Default",
"saveCurrentMessages": "Сохранить текущую сессию в качестве темы",
"searchPlaceholder": "Поиск тем...",
"title": "Тема"
},
"updateAgent": "Обновление информации о помощнике",
"updatePrompt": "Обновление подсказок",
"upgradeVersion": {
"action": "Обновить сейчас",
"hasNew": "Доступно обновление",
"newVersion": "Доступна новая версия: {{version}}"
},
"warp": "Разрыв строки"
}
}
+55
View File
@@ -0,0 +1,55 @@
{
"agentDefaultMessage": "你好,我是 **{{name}}**,你可以立即与我开始对话,也可以前往 [助手设置](/chat/settings#session={{id}}) 完善我的信息。",
"agentDefaultMessageWithSystemRole": "你好,我是 **{{name}}**{{systemRole}},让我们开始对话吧!",
"backToBottom": "查看最新消息",
"clearCurrentMessages": "清空当前会话消息",
"confirmClearCurrentMessages": "即将清空当前会话消息,清空后将无法找回,请确认你的操作",
"confirmRemoveSessionItemAlert": "即将删除该助手,删除后该将无法找回,请确认你的操作",
"defaultAgent": "自定义助手",
"defaultSession": "自定义助手",
"historyRange": "历史范围",
"inbox": {
"defaultMessage": "你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击`+`创建自定义助手",
"desc": "开启大脑集群,激发思维火花。你的智能助理,在这里与你交流一切",
"title": "随便聊聊"
},
"newAgent": "新建助手",
"noDescription": "暂无描述",
"regenerate": "重新生成",
"roleAndArchive": "角色与记录",
"searchAgentPlaceholder": "搜索助手和对话...",
"send": "发送",
"sendPlaceholder": "输入聊天内容...",
"shareModal": {
"download": "下载截图",
"imageType": "图片格式",
"screenshot": "截图",
"settings": "导出设置",
"shareToShareGPT": "生成 ShareGPT 分享链接",
"withBackground": "包含背景图片",
"withFooter": "包含页脚",
"withPluginInfo": "包含插件信息",
"withSystemRole": "包含助手角色设定"
},
"stop": "停止",
"temp": "临时",
"tokenDetail": "角色设定: {{systemRoleToken}} · 历史消息: {{chatsToken}}",
"tokenTag": {
"overload": "超过限制",
"remained": "剩余",
"used": "使用"
},
"topic": {
"confirmRemoveTopic": "即将删除该话题,删除后将不可恢复,请谨慎操作。",
"defaultTitle": "默认话题",
"saveCurrentMessages": "将当前会话保存为话题",
"searchPlaceholder": "搜索话题...",
"title": "话题"
},
"translate": {
"clear": "删除翻译"
},
"translateTo": "翻译",
"updateAgent": "更新助理信息",
"warp": "换行"
}
+11 -45
View File
@@ -1,8 +1,6 @@
{
"about": "关于",
"advanceSettings": "高级设置",
"agentDefaultMessage": "你好,我是 **{{name}}**,你可以立即与我开始对话,也可以前往 [助手设置](/chat/settings#session={{id}}) 完善我的信息。",
"agentDefaultMessageWithSystemRole": "你好,我是 **{{name}}**{{systemRole}},让我们开始对话吧!",
"agentMaxToken": "会话最大长度",
"agentModel": "模型",
"agentProfile": "助手信息",
@@ -10,12 +8,9 @@
"archive": "归档",
"autoGenerate": "自动补全",
"autoGenerateTooltip": "基于提示词自动补全助手描述",
"backToBottom": "查看最新消息",
"cancel": "取消",
"changelog": "更新日志",
"clearCurrentMessages": "清空当前会话消息",
"close": "关闭",
"confirmClearCurrentMessages": "即将清空当前会话消息,清空后将无法找回,请确认你的操作",
"confirmRemoveSessionItemAlert": "即将删除该助手,删除后该将无法找回,请确认你的操作",
"copy": "复制",
"copySuccess": "复制成功",
@@ -35,16 +30,17 @@
"feedback": "反馈与建议",
"historyRange": "历史范围",
"import": "导入配置",
"inbox": {
"defaultMessage": "你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击`+`创建自定义助手",
"desc": "开启大脑集群,激发思维火花。你的智能助理,在这里与你交流一切",
"title": "随便聊聊"
"lang": {
"en": "英语",
"en-US": "英语",
"ja-JP": "日语",
"ko-KR": "韩语",
"ru-RU": "俄语",
"zh": "简体中文",
"zh-CN": "简体中文",
"zh-TW": "繁体中文"
},
"message": {
"function_loading": "插件请求中..."
},
"moreSetting": "更多设置...",
"newAgent": "新建助手",
"layoutInitializing": "正在加载布局...",
"noDescription": "暂无描述",
"ok": "确定",
"password": "密码",
@@ -54,51 +50,21 @@
"rename": "重命名",
"reset": "重置",
"retry": "重试",
"roleAndArchive": "角色与记录",
"searchAgentPlaceholder": "搜索助手和对话...",
"send": "发送",
"sendPlaceholder": "输入聊天内容...",
"sessionList": "助手列表",
"setting": "设置",
"share": "分享",
"shareModal": {
"download": "下载截图",
"imageType": "图片格式",
"screenshot": "截图",
"settings": "导出设置",
"shareToShareGPT": "生成 ShareGPT 分享链接",
"withBackground": "包含背景图片",
"withFooter": "包含页脚",
"withPluginInfo": "包含插件信息",
"withSystemRole": "包含助手角色设定"
},
"stop": "停止",
"switchMobileLayout": "正在切换到移动端布局...",
"tab": {
"chat": "会话",
"market": "发现",
"setting": "设置"
},
"temp": "临时",
"tokenDetail": "角色设定: {{systemRoleToken}} · 历史消息: {{chatsToken}}",
"tokenTag": {
"overload": "超过限制",
"remained": "剩余",
"used": "使用"
},
"topic": {
"confirmRemoveTopic": "即将删除该话题,删除后将不可恢复,请谨慎操作。",
"defaultTitle": "默认话题",
"saveCurrentMessages": "将当前会话保存为话题",
"searchPlaceholder": "搜索话题...",
"title": "话题"
},
"updateAgent": "更新助理信息",
"updatePrompt": "更新提示词",
"upgradeVersion": {
"action": "立即升级",
"hasNew": "有可用更新",
"newVersion": "有新版本可用:{{version}}"
},
"warp": "换行"
}
}
+55
View File
@@ -0,0 +1,55 @@
{
"agentDefaultMessage": "妳好,我是 **{{name}}**,妳可以立即與我開始對話,也可以前往 [助手設定](/chat/settings#session={{id}}) 完善我的資訊。",
"agentDefaultMessageWithSystemRole": "妳好,我是 **{{name}}**{{systemRole}},讓我們開始對話吧!",
"backToBottom": "查看最新訊息",
"clearCurrentMessages": "清空當前會話訊息",
"confirmClearCurrentMessages": "即將清空當前會話訊息,清空後將無法找回,請確認妳的操作",
"confirmRemoveSessionItemAlert": "即將刪除該助手,刪除後該將無法找回,請確認妳的操作",
"defaultAgent": "自定義助手",
"defaultSession": "自定義助手",
"historyRange": "歷史範圍",
"inbox": {
"defaultMessage": "妳好,我是妳的智能助手,妳可以問我任何問題,我會盡力回答妳。如果需要獲得更加專業或定制的助手,可以點擊`+`創建自定義助手",
"desc": "開啟大腦集群,激發思維火花。妳的智能助理,在這裡與妳交流一切",
"title": "隨便聊聊"
},
"newAgent": "新建助手",
"noDescription": "暫無描述",
"regenerate": "重新生成",
"roleAndArchive": "角色與記錄",
"searchAgentPlaceholder": "搜索助手和對話...",
"send": "發送",
"sendPlaceholder": "輸入聊天內容...",
"shareModal": {
"download": "下載截圖",
"imageType": "圖片格式",
"screenshot": "截圖",
"settings": "導出設定",
"shareToShareGPT": "生成 ShareGPT 分享鏈接",
"withBackground": "包含背景圖片",
"withFooter": "包含頁腳",
"withPluginInfo": "包含插件信息",
"withSystemRole": "包含助手角色設定"
},
"stop": "停止",
"temp": "臨時",
"tokenDetail": "角色設定: {{systemRoleToken}} · 歷史訊息: {{chatsToken}}",
"tokenTag": {
"overload": "超過限制",
"remained": "剩餘",
"used": "使用"
},
"topic": {
"confirmRemoveTopic": "即將刪除該話題,刪除後將不可恢復,請謹慎操作。",
"defaultTitle": "默認話題",
"saveCurrentMessages": "將當前會話保存為話題",
"searchPlaceholder": "搜索話題...",
"title": "話題"
},
"translate": {
"clear": "刪除翻譯"
},
"translateTo": "翻譯",
"updateAgent": "更新助理資訊",
"warp": "換行"
}
+30 -64
View File
@@ -1,104 +1,70 @@
{
"about": "關於",
"advanceSettings": "進階設定",
"agentDefaultMessage": "嗨,我是 **{{name}}**。您可以立即與我開始對話,或是前往 [助理設定](/chat/settings#session={{id}}) 完善我的資訊。",
"agentDefaultMessageWithSystemRole": "嗨,我是 **{{name}}**{{systemRole}}。讓我們開始對話吧!",
"agentMaxToken": "最大對話長度",
"agentModel": "模型",
"agentProfile": "助資訊",
"appInitializing": "LobeChat 正在初始化,請稍候...",
"agentProfile": "助資訊",
"appInitializing": "LobeChat 正在啟動,請稍候...",
"archive": "歸檔",
"autoGenerate": "自動生",
"autoGenerateTooltip": "根據提示自動產生助理描述",
"backToBottom": "回到最新訊息",
"autoGenerate": "自動生",
"autoGenerateTooltip": "基於提示自動生成助手描述",
"cancel": "取消",
"changelog": "更新日誌",
"clearCurrentMessages": "清除目前的對話訊息",
"close": "關閉",
"confirmClearCurrentMessages": "您將清除目前的對話訊息。一旦清除,將無法恢復。請確認您的操作",
"confirmRemoveSessionItemAlert": "您將刪除此助理。一旦刪除,將無法恢復。請確認您的操作。",
"confirmRemoveSessionItemAlert": "即將刪除該助手,刪除後將無法找回,請確認您的操作",
"copy": "複製",
"copySuccess": "複製成功",
"defaultAgent": "自訂助理",
"defaultSession": "自訂助理",
"defaultAgent": "自定義助手",
"defaultSession": "自定義助手",
"delete": "刪除",
"edit": "編輯",
"export": "匯出設定",
"exportType": {
"agent": "匯出助設定",
"agentWithMessage": "匯出助理與訊息",
"all": "匯出全域設定所有助資料",
"allAgent": "匯出所有助設定",
"allAgentWithMessage": "匯出所有助理與訊息",
"agent": "匯出助設定",
"agentWithMessage": "匯出助手和訊息",
"all": "匯出全域設定所有助資料",
"allAgent": "匯出所有助設定",
"allAgentWithMessage": "匯出所有助手和訊息",
"globalSetting": "匯出全域設定"
},
"feedback": "意見回饋",
"feedback": "回饋與建議",
"historyRange": "歷史範圍",
"import": "匯入設定",
"inbox": {
"defaultMessage": "您好,我是您的智慧助理。您可以問我任何問題,我會盡力回答您。如果您需要更專業或自訂的助理,您可以點選 `+` 來建立一個自訂助理。",
"desc": "啟動思維並激發你的創意。你的智慧助理已經準備好與你討論所有事情。",
"title": "隨便聊聊"
"lang": {
"en": "英語",
"en-US": "英語",
"ja-JP": "日語",
"ko-KR": "韓語",
"ru-RU": "俄語",
"zh": "簡體中文",
"zh-CN": "簡體中文",
"zh-TW": "繁體中文"
},
"message": {
"function_loading": "外掛請求進行中..."
},
"moreSetting": "更多設定...",
"newAgent": "新助理",
"noDescription": "無描述",
"layoutInitializing": "正在載入佈局...",
"noDescription": "暫無描述",
"ok": "確定",
"password": "密碼",
"pin": "置頂",
"pinOff": "取消置頂",
"regenerate": "重新生",
"rename": "重命名",
"reset": "重",
"regenerate": "重新生",
"rename": "重命名",
"reset": "重",
"retry": "重試",
"roleAndArchive": "角色與歸檔",
"searchAgentPlaceholder": "搜尋助理與對話...",
"send": "傳送",
"sendPlaceholder": "輸入聊天內容...",
"sessionList": "助理列表",
"send": "發送",
"sessionList": "助手列表",
"setting": "設定",
"share": "分享",
"shareModal": {
"download": "下載截圖",
"imageType": "圖片格式",
"screenshot": "截圖",
"settings": "匯出設定",
"withBackground": "包含背景圖片",
"withPluginInfo": "包含插件資訊",
"withSystemRole": "包含助手角色設定",
"withFooter": "包含頁腳",
"shareToShareGPT": "生成 ShareGPT 分享連結"
},
"stop": "停止",
"switchMobileLayout": "正在切換到行動端佈局...",
"tab": {
"chat": "聊天",
"market": "探索",
"setting": "設定"
},
"temp": "臨時",
"tokenDetail": "角色設定:{{systemRoleToken}} · 訊息歷史:{{chatsToken}}",
"tokenTag": {
"overload": "超過限制",
"remained": "剩餘",
"used": "已使用"
},
"topic": {
"confirmRemoveTopic": "您將刪除此主題。一旦刪除,將無法恢復。請小心操作。",
"defaultTitle": "預設主題",
"saveCurrentMessages": "將目前的對話儲存為主題",
"searchPlaceholder": "搜尋主題...",
"title": "主題"
},
"updateAgent": "更新助理資訊",
"updatePrompt": "更新提示",
"upgradeVersion": {
"action": "立即升級",
"hasNew": "有可用更新",
"newVersion": "有新版本可用:{{version}}"
},
"warp": "換行"
}
}
+1
View File
@@ -79,6 +79,7 @@
"antd-style": "^3.5",
"brotli-wasm": "^1",
"chroma-js": "^2",
"copy-to-clipboard": "^3.3.3",
"dayjs": "^1",
"emoji-mart": "^5",
"fast-deep-equal": "^3",
@@ -19,7 +19,7 @@ const Header = memo(() => {
const init = useSessionChatInit();
const router = useRouter();
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const [isInbox, title, description, avatar, backgroundColor, model, plugins] = useSessionStore(
(s) => [
@@ -21,7 +21,7 @@ export const useStyles = createStyles(({ css, token }) => ({
const Header = memo(() => {
const { styles } = useStyles();
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const [createSession] = useSessionStore((s) => [s.createSession]);
return (
@@ -13,7 +13,7 @@ import { pathString } from '@/utils/url';
import ShareButton from '../../features/ChatHeader/ShareButton';
const MobileHeader = memo(() => {
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const router = useRouter();
const [isInbox, title] = useSessionStore((s) => [
+1 -1
View File
@@ -12,7 +12,7 @@ const Topics = memo(() => {
s.toggleMobileTopic,
]);
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
return (
<Modal onCancel={() => toggleConfig(false)} open={showAgentSettings} title={t('topic.title')}>
@@ -24,7 +24,7 @@ const Inner = memo(() => {
const [withFooter, setWithFooter] = useState(false);
const [imageType, setImageType] = useState<ImageType>(ImageType.JPG);
const [tab, setTab] = useState<Tab>(Tab.Screenshot);
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const avatar = useGlobalStore((s) => s.settings.avatar);
const [shareLoading, shareToShareGPT] = useSessionStore((s) => [
@@ -62,7 +62,7 @@ const Preview = memo<PreviewProps>(({ withSystemRole, imageType, withBackground,
agentSelectors.currentAgentPlugins(s),
agentSelectors.currentAgentSystemRole(s),
]);
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const { styles } = useStyles(withBackground);
const displayTitle = isInbox ? t('inbox.title') : title;
@@ -29,15 +29,15 @@ const ActionsRight = memo(() => {
cancelText={t('cancel', { ns: 'common' })}
okButtonProps={{ danger: true }}
okText={t('ok', { ns: 'common' })}
onConfirm={clearMessage}
onConfirm={() => clearMessage()}
placement={'topRight'}
title={t('confirmClearCurrentMessages', { ns: 'common' })}
title={t('confirmClearCurrentMessages', { ns: 'chat' })}
>
<ActionIcon
icon={Eraser}
placement={'bottom'}
title={
(<HotKeys desc={t('clearCurrentMessages', { ns: 'common' })} keys={hotkeys} />) as any
(<HotKeys desc={t('clearCurrentMessages', { ns: 'chat' })} keys={hotkeys} />) as any
}
/>
</Popconfirm>
@@ -9,7 +9,7 @@ import { agentSelectors, chatSelectors } from '@/store/session/selectors';
import { LanguageModel } from '@/types/llm';
const Token = memo<{ input: string }>(({ input }) => {
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const inputTokenCount = useTokenCount(input);
@@ -11,7 +11,7 @@ import { PREFIX_KEY, SAVE_TOPIC_KEY } from '@/const/hotkeys';
import { useSessionStore } from '@/store/session';
const SaveTopic = memo(() => {
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const [hasTopic, saveToTopic] = useSessionStore((s) => [!!s.activeTopicId, s.saveToTopic]);
const { mobile } = useResponsive();
@@ -9,7 +9,7 @@ import SaveTopic from './SaveTopic';
const Footer = memo(() => {
const theme = useTheme();
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
return (
<>
@@ -57,7 +57,7 @@ const ChatInputContent = memo<ChatContentProps>(
onInputChange={setMessage}
onSend={sendMessage}
onStop={stopGenerateMessage}
placeholder={t('sendPlaceholder')}
placeholder={t('sendPlaceholder', { ns: 'chat' })}
text={{
send: t('send'),
stop: t('stop'),
@@ -0,0 +1,22 @@
import { ActionIconGroup, RenderAction, useChatListActionsBar } from '@lobehub/ui';
import { memo } from 'react';
import { ErrorActionsBar } from './Error';
import { useCustomActions } from './customAction';
export const AssistantActionsBar: RenderAction = memo(({ text, id, onActionClick, error }) => {
const { regenerate, edit, copy, divider, del } = useChatListActionsBar(text);
const { translate } = useCustomActions();
if (id === 'default') return;
if (error) return <ErrorActionsBar onActionClick={onActionClick} text={text} />;
return (
<ActionIconGroup
dropdownMenu={[edit, copy, regenerate, divider, translate, divider, del]}
items={[regenerate, copy]}
onActionClick={onActionClick}
type="ghost"
/>
);
});
@@ -0,0 +1,15 @@
import { ActionIconGroup, useChatListActionsBar } from '@lobehub/ui';
import { ActionsBarProps } from '@lobehub/ui/es/ChatList/ActionsBar';
import { memo } from 'react';
export const ErrorActionsBar = memo<ActionsBarProps>(({ text, onActionClick }) => {
const { regenerate, del } = useChatListActionsBar(text);
return (
<ActionIconGroup
items={[regenerate, del]}
onActionClick={onActionClick}
type="ghost"
/>
);
});
@@ -1,7 +1,7 @@
import { ActionIconGroup, RenderAction, useChatListActionsBar } from '@lobehub/ui';
import { memo } from 'react';
export const SystemActionsBar: RenderAction = memo(({ text, onActionClick }) => {
export const DefaultActionsBar: RenderAction = memo(({ text, onActionClick }) => {
const { del } = useChatListActionsBar(text);
return (
<ActionIconGroup dropdownMenu={[del]} items={[]} onActionClick={onActionClick} type="ghost" />
@@ -0,0 +1,14 @@
import { ActionIconGroup, RenderAction, useChatListActionsBar } from '@lobehub/ui';
import { memo } from 'react';
export const FunctionActionsBar: RenderAction = memo(({ text, onActionClick }) => {
const { regenerate, divider, del } = useChatListActionsBar(text);
return (
<ActionIconGroup
dropdownMenu={[regenerate, divider, del]}
items={[regenerate]}
onActionClick={onActionClick}
type="ghost"
/>
);
});
@@ -1,11 +1,16 @@
import { ActionIconGroup, RenderAction, useChatListActionsBar } from '@lobehub/ui';
import { memo } from 'react';
import { useCustomActions } from './customAction';
export const UserActionsBar: RenderAction = memo(({ text, onActionClick }) => {
const { regenerate, edit, copy, divider, del } = useChatListActionsBar(text);
const { translate } = useCustomActions();
return (
<ActionIconGroup
dropdownMenu={[edit, copy, regenerate, divider, del]}
dropdownMenu={[edit, copy, regenerate, divider, translate, divider, del]}
items={[regenerate, edit]}
onActionClick={onActionClick}
type="ghost"
@@ -0,0 +1,21 @@
import { ActionIconGroupItems } from '@lobehub/ui/es/ActionIconGroup';
import { LanguagesIcon } from 'lucide-react';
import { useTranslation } from 'react-i18next';
export const useCustomActions = () => {
const { t } = useTranslation('chat');
const translate = {
// children: localeOptions.map((i) => ({
// key: i.value,
// label: t(`lang.${i.value}`, { ns: 'common' }),
// })),
icon: LanguagesIcon,
key: 'translate',
label: t('translateTo'),
} as ActionIconGroupItems;
return {
translate,
};
};
@@ -0,0 +1,13 @@
import { ChatListProps } from '@lobehub/ui';
import { AssistantActionsBar } from './Assistant';
import { DefaultActionsBar } from './Fallback';
import { FunctionActionsBar } from './Function';
import { UserActionsBar } from './User';
export const renderActions: ChatListProps['renderActions'] = {
assistant: AssistantActionsBar,
function: FunctionActionsBar,
system: DefaultActionsBar,
user: UserActionsBar,
};
@@ -0,0 +1,39 @@
import { SiOpenai } from '@icons-pack/react-simple-icons';
import { RenderMessageExtra, Tag } from '@lobehub/ui';
import { Divider } from 'antd';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';
import Translate from './Translate';
export const AssistantMessageExtra: RenderMessageExtra = memo(({ extra, id }) => {
const model = useSessionStore(agentSelectors.currentAgentModel);
const showModelTag = extra?.fromModel && model !== extra?.fromModel;
const hasTranslate = !!extra?.translate;
const showExtra = showModelTag || hasTranslate;
const loading = useSessionStore((s) => s.chatLoadingId === id);
if (!showExtra) return;
return (
<Flexbox gap={8} style={{ marginTop: 8 }}>
{showModelTag && (
<div>
<Tag icon={<SiOpenai size={'1em'} />}>{extra?.fromModel as string}</Tag>
</div>
)}
{extra.translate && (
<div>
<Divider style={{ margin: '12px 0' }} />
<Translate id={id} loading={loading} {...extra.translate} />
</div>
)}
</Flexbox>
);
});
@@ -0,0 +1,75 @@
import { ActionIcon, Icon, Markdown, Tag } from '@lobehub/ui';
import { App } from 'antd';
import { createStyles } from 'antd-style';
import copy from 'copy-to-clipboard';
import { ChevronDown, ChevronUp, ChevronsRight, CopyIcon, TrashIcon } from 'lucide-react';
import { memo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import { useSessionStore } from '@/store/session';
import { ChatTranslate } from '@/types/chatMessage';
import BubblesLoading from '../Loading';
const useStyles = createStyles(({ css }) => ({
container: css`
margin-top: 8px;
`,
}));
interface TranslateProps extends ChatTranslate {
id: string;
loading?: boolean;
}
const Translate = memo<TranslateProps>(({ content = '', from, to, id, loading }) => {
const { theme } = useStyles();
const { t } = useTranslation('common');
const [show, setShow] = useState(true);
const clearTranslate = useSessionStore((s) => s.clearTranslate);
const { message } = App.useApp();
return (
<Flexbox gap={8}>
<Flexbox align={'center'} horizontal justify={'space-between'}>
<div>
<Flexbox gap={4} horizontal>
<Tag style={{ margin: 0 }}>{from ? t(`lang.${from}` as any) : '...'}</Tag>
<Icon color={theme.colorTextTertiary} icon={ChevronsRight} />
<Tag>{t(`lang.${to}` as any)}</Tag>
</Flexbox>
</div>
<Flexbox horizontal>
<ActionIcon
icon={CopyIcon}
onClick={() => {
copy(content);
message.success(t('copySuccess'));
}}
size={'small'}
title={t('copy')}
/>
<ActionIcon
icon={TrashIcon}
onClick={() => {
clearTranslate(id);
}}
size={'small'}
title={t('translate.clear', { ns: 'chat' })}
/>
<ActionIcon
icon={show ? ChevronDown : ChevronUp}
onClick={() => {
setShow(!show);
}}
size={'small'}
/>
</Flexbox>
</Flexbox>
{!show ? null : loading && !content ? <BubblesLoading /> : <Markdown>{content}</Markdown>}
</Flexbox>
);
});
export default Translate;
@@ -0,0 +1,24 @@
import { RenderMessageExtra } from '@lobehub/ui';
import { Divider } from 'antd';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
import { useSessionStore } from '@/store/session';
import Translate from './Translate';
export const UserMessageExtra: RenderMessageExtra = memo(({ extra, id }) => {
const hasTranslate = !!extra?.translate;
const loading = useSessionStore((s) => s.chatLoadingId === id);
return (
<Flexbox gap={8} style={{ marginTop: hasTranslate ? 8 : 0 }}>
{extra?.translate && (
<div>
<Divider style={{ margin: '12px 0' }} />
<Translate id={id} {...extra.translate} loading={loading} />
</div>
)}
</Flexbox>
);
});
@@ -0,0 +1,9 @@
import { ChatListProps } from '@lobehub/ui';
import { AssistantMessageExtra } from './Assistant';
import { UserMessageExtra } from './User';
export const renderMessagesExtra: ChatListProps['renderMessagesExtra'] = {
assistant: AssistantMessageExtra,
user: UserMessageExtra,
};
@@ -0,0 +1,53 @@
import { useTheme } from 'antd-style';
const Svg = () => (
<svg viewBox="0 0 32 24" xmlns="http://www.w3.org/2000/svg">
<circle cx="0" cy="12" r="0" transform="translate(8 0)">
<animate
attributeName="r"
begin="0"
calcMode="spline"
dur="1.2s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.6 0.4 0.8"
keyTimes="0;0.2;0.7;1"
repeatCount="indefinite"
values="0; 4; 0; 0"
/>
</circle>
<circle cx="0" cy="12" r="0" transform="translate(16 0)">
<animate
attributeName="r"
begin="0.3"
calcMode="spline"
dur="1.2s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.6 0.4 0.8"
keyTimes="0;0.2;0.7;1"
repeatCount="indefinite"
values="0; 4; 0; 0"
/>
</circle>
<circle cx="0" cy="12" r="0" transform="translate(24 0)">
<animate
attributeName="r"
begin="0.6"
calcMode="spline"
dur="1.2s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.6 0.4 0.8"
keyTimes="0;0.2;0.7;1"
repeatCount="indefinite"
values="0; 4; 0; 0"
/>
</circle>
</svg>
);
const BubblesLoading = () => {
const { colorTextTertiary } = useTheme();
return (
<div style={{ fill: colorTextTertiary, height: 24, width: 32 }}>
<Svg />
</div>
);
};
export default BubblesLoading;
@@ -1,41 +1,18 @@
import { SiOpenai } from '@icons-pack/react-simple-icons';
import {
ActionIconGroup,
RenderAction,
RenderMessage,
RenderMessageExtra,
Tag,
useChatListActionsBar,
} from '@lobehub/ui';
import { createStyles } from 'antd-style';
import { RenderMessage } from '@lobehub/ui';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/slices/agentConfig';
import { chatSelectors } from '@/store/session/slices/chat/selectors';
import { chatSelectors } from '@/store/session/selectors';
import { isFunctionMessage } from '@/utils/message';
import FunctionCall from '../Plugins/FunctionCall';
import { DefautMessage } from './Default';
const useStyles = createStyles(({ css }) => ({
container: css`
margin-top: 8px;
`,
plugin: css`
display: flex;
gap: 4px;
align-items: center;
width: fit-content;
`,
}));
import { DefaultMessage } from './Default';
export const AssistantMessage: RenderMessage = memo(
({ id, plugin, function_call, content, ...props }) => {
const genFunctionCallProps = useSessionStore(chatSelectors.currentFunctionCallProps);
const genFunctionCallProps = useSessionStore(chatSelectors.getFunctionMessageParams);
if (!isFunctionMessage(content)) return <DefautMessage content={content} id={id} {...props} />;
if (!isFunctionMessage(content)) return <DefaultMessage content={content} id={id} {...props} />;
const fcProps = genFunctionCallProps({ content, function_call, id, plugin });
@@ -46,33 +23,3 @@ export const AssistantMessage: RenderMessage = memo(
);
},
);
export const AssistantMessageExtra: RenderMessageExtra = memo(({ extra, function_call }) => {
const { styles } = useStyles();
const model = useSessionStore(agentSelectors.currentAgentModel);
const hasModelTag = extra?.fromModel && model !== extra?.fromModel;
const hasFuncTag = !!function_call;
if (!(hasModelTag || hasFuncTag)) return;
return (
<Flexbox className={styles.container} horizontal>
<div>
<Tag icon={<SiOpenai size={'1em'} />}>{extra?.fromModel as string}</Tag>
</div>
</Flexbox>
);
});
export const AssistantActionsBar: RenderAction = memo(({ text, error, id, onActionClick }) => {
const { regenerate, edit, copy, divider, del } = useChatListActionsBar(text);
if (id === 'default') return;
return (
<ActionIconGroup
dropdownMenu={error ? [regenerate, divider, del] : [edit, copy, regenerate, divider, del]}
items={[regenerate]}
onActionClick={onActionClick}
type="ghost"
/>
);
});
@@ -1,6 +1,12 @@
import { RenderMessage } from '@lobehub/ui';
import { memo } from 'react';
export const DefautMessage: RenderMessage = memo(({ id, editableContent }) => {
import { LOADING_FLAT } from '@/const/message';
import BubblesLoading from '../Loading';
export const DefaultMessage: RenderMessage = memo(({ id, editableContent, content }) => {
if (content === LOADING_FLAT) return <BubblesLoading />;
return <div id={id}>{editableContent}</div>;
});
@@ -1,4 +1,4 @@
import { ActionIconGroup, RenderAction, RenderMessage, useChatListActionsBar } from '@lobehub/ui';
import { RenderMessage } from '@lobehub/ui';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
@@ -9,34 +9,15 @@ import FunctionCall from '../Plugins/FunctionCall';
import PluginMessage from '../Plugins/PluginMessage';
export const FunctionMessage: RenderMessage = memo(
({ id, content, plugin, function_call, ...props }) => {
const genFunctionCallProps = useSessionStore(chatSelectors.currentFunctionCallProps);
({ id, content, plugin, function_call, name }) => {
const genFunctionCallProps = useSessionStore(chatSelectors.getFunctionMessageParams);
const fcProps = genFunctionCallProps({ content, function_call, id, plugin });
return (
<Flexbox gap={12} id={id}>
<FunctionCall {...fcProps} />
<PluginMessage
content={content}
function_call={function_call}
id={id}
loading={fcProps.loading}
plugin={plugin}
{...props}
/>
<PluginMessage content={content} loading={fcProps.loading} name={name} />
</Flexbox>
);
},
);
export const FunctionActionsBar: RenderAction = memo(({ text, onActionClick }) => {
const { regenerate, divider, del } = useChatListActionsBar(text);
return (
<ActionIconGroup
dropdownMenu={[regenerate, divider, del]}
items={[regenerate]}
onActionClick={onActionClick}
type="ghost"
/>
);
});
@@ -1,24 +1,11 @@
import { ChatListProps } from '@lobehub/ui';
import { AssistantActionsBar, AssistantMessage, AssistantMessageExtra } from './Assistant';
import { DefautMessage } from './Default';
import { FunctionActionsBar, FunctionMessage } from './Function';
import { SystemActionsBar } from './System';
import { UserActionsBar } from './User';
import { AssistantMessage } from './Assistant';
import { DefaultMessage } from './Default';
import { FunctionMessage } from './Function';
export const renderMessages: ChatListProps['renderMessages'] = {
assistant: AssistantMessage,
default: DefautMessage,
default: DefaultMessage,
function: FunctionMessage,
};
export const renderMessagesExtra: ChatListProps['renderMessagesExtra'] = {
assistant: AssistantMessageExtra,
};
export const renderActions: ChatListProps['renderActions'] = {
assistant: AssistantActionsBar,
function: FunctionActionsBar,
system: SystemActionsBar,
user: UserActionsBar,
};
@@ -30,8 +30,6 @@ const FunctionCall = memo<FunctionCallProps>(
const pluginAvatar = pluginHelpers.getPluginAvatar(item?.meta);
const pluginTitle = pluginHelpers.getPluginTitle(item?.meta);
console.log(item?.meta);
const avatar = pluginAvatar ? (
<Avatar avatar={pluginAvatar} size={32} />
) : (
@@ -6,14 +6,15 @@ import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import { usePluginStore } from '@/store/plugin';
import { ChatMessage } from '@/types/chatMessage';
import IFrameRender from './IFrameRender';
const SystemJsRender = dynamic(() => import('./SystemJsRender'), { ssr: false });
export interface FunctionMessageProps extends ChatMessage {
export interface FunctionMessageProps {
content: string;
loading?: boolean;
name?: string;
}
const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
@@ -29,8 +30,6 @@ const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
const contentObj = useMemo(() => (isJSON ? JSON.parse(content) : content), [content]);
// if (!loading)
if (!isJSON) {
return (
<Flexbox gap={8} horizontal>
@@ -5,11 +5,14 @@ import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import { PREFIX_KEY, REGENERATE_KEY } from '@/const/hotkeys';
import { settingsSelectors, useGlobalStore } from '@/store/global';
import { useSessionChatInit, useSessionStore } from '@/store/session';
import { agentSelectors, chatSelectors } from '@/store/session/selectors';
import { renderActions } from './Actions';
import { renderErrorMessages } from './Error';
import { renderActions, renderMessages, renderMessagesExtra } from './Messages';
import { renderMessagesExtra } from './Extras';
import { renderMessages } from './Messages';
import SkeletonList from './SkeletonList';
const List = memo(() => {
@@ -25,6 +28,7 @@ const List = memo(() => {
deleteMessage,
resendMessage,
dispatchMessage,
translateMessage,
] = useSessionStore((s) => {
const config = agentSelectors.currentAgentConfig(s);
return [
@@ -35,9 +39,12 @@ const List = memo(() => {
s.deleteMessage,
s.resendMessage,
s.dispatchMessage,
s.translateMessage,
];
});
const targetLang = useGlobalStore(settingsSelectors.currentLanguage);
const hotkeys = [PREFIX_KEY, REGENERATE_KEY].join('+');
useHotkeys(
@@ -63,7 +70,15 @@ const List = memo(() => {
loadingId={chatLoadingId}
onActionsClick={{
del: ({ id }) => deleteMessage(id),
regenerate: ({ id }) => resendMessage(id),
regenerate: ({ id, error }) => {
resendMessage(id);
// if this message is an error message, we need to delete it
if (error) deleteMessage(id);
},
translate: ({ id }) => {
translateMessage(id, targetLang);
},
}}
onMessageChange={(id, content) =>
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: content })
+2 -3
View File
@@ -12,8 +12,7 @@ import ChatScrollAnchor from './ScrollAnchor';
const useStyles = createStyles(
({ css, responsive, stylish }) => css`
overflow-x: hidden;
overflow-y: scroll;
overflow: hidden scroll;
height: 100%;
${responsive.mobile} {
${stylish.noScrollbar}
@@ -29,7 +28,7 @@ interface ConversationProps {
const Conversation = memo<ConversationProps>(({ mobile, chatInput }) => {
const ref = useRef(null);
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const { styles } = useStyles();
const useFetchPluginList = usePluginStore((s) => s.useFetchPluginList);
@@ -15,7 +15,7 @@ const { Item } = List;
const Inbox = memo(() => {
const ref = useRef(null);
const isHovering = useHover(ref);
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const { mobile } = useResponsive();
const [activeId, activeSession, switchSession] = useSessionStore((s) => [
s.activeId,
@@ -8,7 +8,7 @@ import { Flexbox } from 'react-layout-kit';
import { useSessionStore } from '@/store/session';
const AddButton = memo<ButtonProps>((props) => {
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const createSession = useSessionStore((s) => s.createSession);
return (
<Flexbox style={{ margin: '12px 16px' }}>
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
import { useSessionStore } from '@/store/session';
const SessionSearchBar = memo(() => {
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const [keywords] = useSessionStore((s) => [s.searchKeywords]);
const { mobile } = useResponsive();
return (
@@ -19,7 +19,7 @@ const DefaultContent = memo(() => {
<Icon color={theme.colorTextDescription} icon={MessageSquareDashed} />
</Flexbox>
<Paragraph ellipsis={{ rows: 1 }} style={{ margin: 0 }}>
{t('topic.defaultTitle')}
{t('topic.defaultTitle', { ns: 'chat' })}
</Paragraph>
<Tag>{t('temp')}</Tag>
</Flexbox>
@@ -74,7 +74,7 @@ const TopicContent = memo<TopicContentProps>(({ id, title, fav }) => {
onOk: () => {
removeTopic(id);
},
title: t('topic.confirmRemoveTopic'),
title: t('topic.confirmRemoveTopic', { ns: 'chat' }),
});
},
},
@@ -54,7 +54,7 @@ export const Topic = () => {
<TopicItem
active={!activeTopicId}
fav={false}
title={t('topic.defaultTitle', { ns: 'common' })}
title={t('topic.defaultTitle', { ns: 'chat' })}
/>
{topicsData.map(({ id, favorite, title }) => (
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
import { useSessionStore } from '@/store/session';
const TopicSearchBar = memo(() => {
const { t } = useTranslation('common');
const { t } = useTranslation('chat');
const [keywords] = useSessionStore((s) => [s.topicSearchKeywords]);
const { mobile } = useResponsive();
return (
+2 -2
View File
@@ -5,9 +5,9 @@ import { useTranslation } from 'react-i18next';
import FullscreenLoading from '@/components/FullscreenLoading';
const Loading = () => {
const { t } = useTranslation();
const { t } = useTranslation('common');
return <FullscreenLoading title={t('appInitializing', { ns: 'common' })} />;
return <FullscreenLoading title={t('appInitializing')} />;
};
export default Loading;
+77
View File
@@ -0,0 +1,77 @@
import { chatHelpers } from '@/store/session/helpers';
import { LanguageModel } from '@/types/llm';
import { OpenAIChatMessage, OpenAIChatStreamPayload } from '@/types/openai/chat';
export const chainSummaryTitle = async (
messages: OpenAIChatMessage[],
): Promise<Partial<OpenAIChatStreamPayload>> => {
const finalMessages: OpenAIChatMessage[] = [
{
content:
'你是一名擅长会话的助理,你需要将用户的会话总结为 10 个字以内的标题,不需要包含标点符号',
role: 'system',
},
{
content: `${messages.map((message) => `${message.role}: ${message.content}`).join('\n')}
请总结上述对话为10个字以内的标题,不需要包含标点符号`,
role: 'user',
},
];
// 如果超过 4k,则使用 GPT3.5 16K 模型
const tokens = await chatHelpers.getMessagesTokenCount(finalMessages);
let model: LanguageModel | undefined = undefined;
if (tokens > 4000) {
model = LanguageModel.GPT3_5_16K;
}
return {
messages: finalMessages,
model,
};
};
export const chainTranslate = (
content: string,
targetLang: string,
): Partial<OpenAIChatStreamPayload> => ({
messages: [
{
content: '你是一名擅长翻译的助理,你需要将输入的语言翻译为目标语言',
role: 'system',
},
{
content: `请将以下内容 ${content},翻译为 ${targetLang} `,
role: 'user',
},
],
});
export const chainLangDetect = (content: string): Partial<OpenAIChatStreamPayload> => ({
messages: [
{
content:
'你是一名精通全世界语言的语言专家,你需要识别用户输入的内容,以国际标准 locale 进行输出',
role: 'system',
},
{
content: '{你好}',
role: 'user',
},
{
content: 'zh-CN',
role: 'assistant',
},
{
content: '{hello}',
role: 'user',
},
{
content: 'en-US',
role: 'assistant',
},
{
content: `{${content}}`,
role: 'user',
},
],
});
@@ -42,9 +42,9 @@ const AgentPrompt = memo(() => {
maxValue={ModelTokens[model as LanguageModel]}
shape={'square'}
text={{
overload: t('tokenTag.overload', { ns: 'common' }),
remained: t('tokenTag.remained', { ns: 'common' }),
used: t('tokenTag.used', { ns: 'common' }),
overload: t('tokenTag.overload', { ns: 'chat' }),
remained: t('tokenTag.remained', { ns: 'chat' }),
used: t('tokenTag.used', { ns: 'chat' }),
}}
value={systemTokenCount}
/>
+1 -1
View File
@@ -1,6 +1,6 @@
import { StateCreator } from 'zustand/vanilla';
import { promptPickEmoji, promptSummaryAgentName, promptSummaryDescription } from '@/prompts/agent';
import { promptPickEmoji, promptSummaryAgentName, promptSummaryDescription } from '@/chains/agent';
import { MetaData } from '@/types/meta';
import { LobeAgentConfig } from '@/types/session';
import { fetchPresetTaskResult } from '@/utils/fetch';
+4 -2
View File
@@ -15,10 +15,12 @@ const ResponsiveLayout = ({ children, Desktop, Mobile }: ServerResponsiveLayoutP
const { t } = useTranslation();
const mobile = useIsMobile();
return (
return mobile ? (
<Suspense fallback={<FullscreenLoading title={t('layoutInitializing', { ns: 'common' })} />}>
{mobile ? <Mobile>{children}</Mobile> : <Desktop>{children}</Desktop>}
<Mobile>{children}</Mobile>
</Suspense>
) : (
<Desktop>{children}</Desktop>
);
};
+2 -1
View File
@@ -4,10 +4,11 @@ import { initReactI18next } from 'react-i18next';
import { getClientConfig } from '@/config/client';
import { DEFAULT_LANG, LOBE_LOCALE_COOKIE } from '@/const/locale';
import resources from '@/locales/resources';
import type { Namespaces } from '@/types/locale';
import { isOnServerSide } from '@/utils/env';
import { resources } from './options';
const { I18N_DEBUG, I18N_DEBUG_BROWSER, I18N_DEBUG_SERVER } = getClientConfig();
const debugMode = I18N_DEBUG ?? isOnServerSide ? I18N_DEBUG_SERVER : I18N_DEBUG_BROWSER;
+60
View File
@@ -0,0 +1,60 @@
export default {
agentDefaultMessage:
'你好,我是 **{{name}}**,你可以立即与我开始对话,也可以前往 [助手设置](/chat/settings#session={{id}}) 完善我的信息。',
agentDefaultMessageWithSystemRole: '你好,我是 **{{name}}**{{systemRole}},让我们开始对话吧!',
backToBottom: '查看最新消息',
clearCurrentMessages: '清空当前会话消息',
confirmClearCurrentMessages: '即将清空当前会话消息,清空后将无法找回,请确认你的操作',
confirmRemoveSessionItemAlert: '即将删除该助手,删除后该将无法找回,请确认你的操作',
defaultAgent: '自定义助手',
defaultSession: '自定义助手',
historyRange: '历史范围',
inbox: {
defaultMessage:
'你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击`+`创建自定义助手',
desc: '开启大脑集群,激发思维火花。你的智能助理,在这里与你交流一切',
title: '随便聊聊',
},
newAgent: '新建助手',
noDescription: '暂无描述',
regenerate: '重新生成',
roleAndArchive: '角色与记录',
searchAgentPlaceholder: '搜索助手和对话...',
send: '发送',
sendPlaceholder: '输入聊天内容...',
shareModal: {
download: '下载截图',
imageType: '图片格式',
screenshot: '截图',
settings: '导出设置',
shareToShareGPT: '生成 ShareGPT 分享链接',
withBackground: '包含背景图片',
withFooter: '包含页脚',
withPluginInfo: '包含插件信息',
withSystemRole: '包含助手角色设定',
},
stop: '停止',
temp: '临时',
tokenDetail: '角色设定: {{systemRoleToken}} · 历史消息: {{chatsToken}}',
tokenTag: {
overload: '超过限制',
remained: '剩余',
used: '使用',
},
topic: {
confirmRemoveTopic: '即将删除该话题,删除后将不可恢复,请谨慎操作。',
defaultTitle: '默认话题',
saveCurrentMessages: '将当前会话保存为话题',
searchPlaceholder: '搜索话题...',
title: '话题',
},
translate: {
clear: '删除翻译',
},
translateTo: '翻译',
updateAgent: '更新助理信息',
warp: '换行',
};
+10 -45
View File
@@ -1,9 +1,6 @@
export default {
about: '关于',
advanceSettings: '高级设置',
agentDefaultMessage:
'你好,我是 **{{name}}**,你可以立即与我开始对话,也可以前往 [助手设置](/chat/settings#session={{id}}) 完善我的信息。',
agentDefaultMessageWithSystemRole: '你好,我是 **{{name}}**{{systemRole}},让我们开始对话吧!',
agentMaxToken: '会话最大长度',
agentModel: '模型',
agentProfile: '助手信息',
@@ -11,12 +8,9 @@ export default {
archive: '归档',
autoGenerate: '自动补全',
autoGenerateTooltip: '基于提示词自动补全助手描述',
backToBottom: '查看最新消息',
cancel: '取消',
changelog: '更新日志',
clearCurrentMessages: '清空当前会话消息',
close: '关闭',
confirmClearCurrentMessages: '即将清空当前会话消息,清空后将无法找回,请确认你的操作',
confirmRemoveSessionItemAlert: '即将删除该助手,删除后该将无法找回,请确认你的操作',
copy: '复制',
copySuccess: '复制成功',
@@ -37,18 +31,17 @@ export default {
historyRange: '历史范围',
import: '导入配置',
inbox: {
defaultMessage:
'你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击`+`创建自定义助手',
desc: '开启大脑集群,激发思维火花。你的智能助理,在这里与你交流一切',
title: '随便聊聊',
lang: {
'en': '英语',
'en-US': '英语',
'ja-JP': '日语',
'ko-KR': '韩语',
'ru-RU': '俄语',
'zh': '简体中文',
'zh-CN': '简体中文',
'zh-TW': '繁体中文',
},
layoutInitializing: '正在加载布局...',
message: {
function_loading: '插件请求中...',
},
moreSetting: '更多设置...',
newAgent: '新建助手',
noDescription: '暂无描述',
ok: '确定',
password: '密码',
@@ -58,24 +51,10 @@ export default {
rename: '重命名',
reset: '重置',
retry: '重试',
roleAndArchive: '角色与记录',
searchAgentPlaceholder: '搜索助手和对话...',
send: '发送',
sendPlaceholder: '输入聊天内容...',
sessionList: '助手列表',
setting: '设置',
share: '分享',
shareModal: {
download: '下载截图',
imageType: '图片格式',
screenshot: '截图',
settings: '导出设置',
shareToShareGPT: '生成 ShareGPT 分享链接',
withBackground: '包含背景图片',
withFooter: '包含页脚',
withPluginInfo: '包含插件信息',
withSystemRole: '包含助手角色设定',
},
stop: '停止',
tab: {
chat: '会话',
@@ -83,25 +62,11 @@ export default {
setting: '设置',
},
temp: '临时',
tokenDetail: '角色设定: {{systemRoleToken}} · 历史消息: {{chatsToken}}',
tokenTag: {
overload: '超过限制',
remained: '剩余',
used: '使用',
},
topic: {
confirmRemoveTopic: '即将删除该话题,删除后将不可恢复,请谨慎操作。',
defaultTitle: '默认话题',
saveCurrentMessages: '将当前会话保存为话题',
searchPlaceholder: '搜索话题...',
title: '话题',
},
updateAgent: '更新助理信息',
updatePrompt: '更新提示词',
upgradeVersion: {
action: '立即升级',
hasNew: '有可用更新',
newVersion: '有新版本可用:{{version}}',
},
warp: '换行',
};
+10
View File
@@ -1,5 +1,7 @@
import type { Locales } from '@/types/locale';
import _resources from './resources';
type LocaleOptions = {
label: string;
value: Locales;
@@ -33,3 +35,11 @@ export const localeOptions: LocaleOptions = [
] as LocaleOptions;
export const supportLangs: string[] = localeOptions.map((i) => i.value);
export const resources = {
..._resources,
en: _resources['en-US'],
zh: _resources['zh-CN'],
};
export const supportLocales = Object.keys(resources);
+2
View File
@@ -1,3 +1,4 @@
import chat from '../../../locales/en_US/chat.json';
import common from '../../../locales/en_US/common.json';
import empty from '../../../locales/en_US/empty.json';
import error from '../../../locales/en_US/error.json';
@@ -7,6 +8,7 @@ import setting from '../../../locales/en_US/setting.json';
import welcome from '../../../locales/en_US/welcome.json';
const resources = {
chat,
common,
empty,
error,
+1 -1
View File
@@ -10,10 +10,10 @@ const resources = {
'ja-JP': ja_JP,
'ko-KR': ko_KR,
'ru-RU': ru_RU,
'zh': zh_CN,
'zh-CN': zh_CN,
'zh-TW': zh_TW,
} as const;
export default resources;
export const defaultResources = zh_CN;
export type Resources = typeof resources;
+2
View File
@@ -1,3 +1,4 @@
import chat from '../../../locales/ja_JP/chat.json';
import common from '../../../locales/ja_JP/common.json';
import empty from '../../../locales/ja_JP/empty.json';
import error from '../../../locales/ja_JP/error.json';
@@ -7,6 +8,7 @@ import setting from '../../../locales/ja_JP/setting.json';
import welcome from '../../../locales/ja_JP/welcome.json';
const resources = {
chat,
common,
empty,
error,
+2
View File
@@ -1,3 +1,4 @@
import chat from '../../../locales/ko_KR/chat.json';
import common from '../../../locales/ko_KR/common.json';
import empty from '../../../locales/ko_KR/empty.json';
import error from '../../../locales/ko_KR/error.json';
@@ -7,6 +8,7 @@ import setting from '../../../locales/ko_KR/setting.json';
import welcome from '../../../locales/ko_KR/welcome.json';
const resources = {
chat,
common,
empty,
error,
+2
View File
@@ -1,3 +1,4 @@
import chat from '../../../locales/ru_RU/chat.json';
import common from '../../../locales/ru_RU/common.json';
import empty from '../../../locales/ru_RU/empty.json';
import error from '../../../locales/ru_RU/error.json';
@@ -7,6 +8,7 @@ import setting from '../../../locales/ru_RU/setting.json';
import welcome from '../../../locales/ru_RU/welcome.json';
const resources = {
chat,
common,
empty,
error,
+2
View File
@@ -1,3 +1,4 @@
import chat from '../default/chat';
import common from '../default/common';
import empty from '../default/empty';
import error from '../default/error';
@@ -7,6 +8,7 @@ import setting from '../default/setting';
import welcome from '../default/welcome';
const resources = {
chat,
common,
empty,
error,
+2
View File
@@ -1,3 +1,4 @@
import chat from '../../../locales/zh_TW/chat.json';
import common from '../../../locales/zh_TW/common.json';
import empty from '../../../locales/zh_TW/empty.json';
import error from '../../../locales/zh_TW/error.json';
@@ -7,6 +8,7 @@ import setting from '../../../locales/zh_TW/setting.json';
import welcome from '../../../locales/zh_TW/welcome.json';
const resources = {
chat,
common,
empty,
error,
-32
View File
@@ -1,32 +0,0 @@
import { chatHelpers } from '@/store/session/helpers';
import { LanguageModel } from '@/types/llm';
import { OpenAIChatMessage, OpenAIChatStreamPayload } from '@/types/openai/chat';
export const promptSummaryTitle = async (
messages: OpenAIChatMessage[],
): Promise<Partial<OpenAIChatStreamPayload>> => {
const finalMessages: OpenAIChatMessage[] = [
{
content:
'你是一名擅长会话的助理,你需要将用户的会话总结为 10 个字以内的标题,不需要包含标点符号',
role: 'system',
},
{
content: `${messages.map((message) => `${message.role}: ${message.content}`).join('\n')}
请总结上述对话为10个字以内的标题,不需要包含标点符号`,
role: 'user',
},
];
// 如果超过 4k,则使用 GPT3.5 16K 模型
const tokens = await chatHelpers.getMessagesTokenCount(finalMessages);
let model: LanguageModel | undefined = undefined;
if (tokens > 4000) {
model = LanguageModel.GPT3_5_16K;
}
return {
messages: finalMessages,
model,
};
};
+4
View File
@@ -1,8 +1,10 @@
import { DEFAULT_OPENAI_MODEL_LIST } from '@/const/llm';
import { DEFAULT_LANG } from '@/const/locale';
import { DEFAULT_AGENT_META } from '@/const/meta';
import { DEFAULT_AGENT, DEFAULT_AGENT_CONFIG, DEFAULT_SETTINGS } from '@/const/settings';
import { Locales } from '@/locales/resources';
import { GlobalSettings } from '@/types/settings';
import { isOnServerSide } from '@/utils/env';
import { merge } from '@/utils/merge';
import { GlobalStore } from '../store';
@@ -35,6 +37,8 @@ export const exportSettings = (s: GlobalStore) => {
const currentLanguage = (s: GlobalStore) => {
const locale = s.settings.language;
if (locale === 'auto') {
if (isOnServerSide) return DEFAULT_LANG;
return navigator.language as Locales;
}
@@ -5,11 +5,16 @@ import { SessionStore } from '@/store/session';
import { ChatMessageAction, chatMessage } from './message';
import { ShareAction, chatShare } from './share';
import { ChatTopicAction, chatTopic } from './topic';
import { ChatTranslateAction, chatTranslate } from './translate';
/**
* 聊天操作
*/
export interface ChatAction extends ChatTopicAction, ChatMessageAction, ShareAction {}
export interface ChatAction
extends ChatTopicAction,
ChatMessageAction,
ShareAction,
ChatTranslateAction {}
export const createChatSlice: StateCreator<
SessionStore,
@@ -20,4 +25,5 @@ export const createChatSlice: StateCreator<
...chatTopic(...params),
...chatMessage(...params),
...chatShare(...params),
...chatTranslate(...params),
});
@@ -66,13 +66,14 @@ export interface ChatMessageAction {
* @param text - 消息文本
*/
sendMessage: (text: string) => Promise<void>;
stopGenerateMessage: () => void;
toggleChatLoading: (
loading: boolean,
id?: string,
action?: string,
) => AbortController | undefined;
triggerFunctionCall: (id: string) => Promise<void>;
}
@@ -298,7 +299,6 @@ export const chatMessage: StateCreator<
toggleChatLoading(false);
},
toggleChatLoading: (loading, id, action) => {
if (loading) {
const abortController = new AbortController();
@@ -1,7 +1,7 @@
import { StateCreator } from 'zustand/vanilla';
import { chainSummaryTitle } from '@/chains/chat';
import { LOADING_FLAT } from '@/const/message';
import { promptSummaryTitle } from '@/prompts/chat';
import { SessionStore } from '@/store/session';
import { fetchPresetTaskResult } from '@/utils/fetch';
import { setNamespace } from '@/utils/storeDebug';
@@ -116,7 +116,7 @@ export const chatTopic: StateCreator<
output += x;
dispatchTopic({ id: topicId, key: 'title', type: 'updateChatTopic', value: output });
},
params: await promptSummaryTitle(messages),
params: await chainSummaryTitle(messages),
});
return topicId;
@@ -0,0 +1,87 @@
import { produce } from 'immer';
import { StateCreator } from 'zustand/vanilla';
import { chainLangDetect, chainTranslate } from '@/chains/chat';
import { supportLocales } from '@/locales/options';
import { SessionStore } from '@/store/session';
import { fetchPresetTaskResult } from '@/utils/fetch';
import { setNamespace } from '@/utils/storeDebug';
import { sessionSelectors } from '../../session/selectors';
const t = setNamespace('chat/translate');
/**
* 翻译事件
*/
export interface ChatTranslateAction {
clearTranslate: (id: string) => void;
/**
* 翻译消息
* @param id
*/
translateMessage: (id: string, targetLang: string) => Promise<void>;
}
export const chatTranslate: StateCreator<
SessionStore,
[['zustand/devtools', never]],
[],
ChatTranslateAction
> = (set, get) => ({
clearTranslate: (id) => {
get().dispatchMessage({
id,
key: 'translate',
type: 'updateMessageExtra',
value: null,
});
},
translateMessage: async (id, targetLang) => {
const { toggleChatLoading, dispatchMessage } = get();
const session = sessionSelectors.currentSession(get());
if (!session || !id) return;
const message = session.chats[id];
if (!message) return;
let content = '';
let from = '';
dispatchMessage({
id,
key: 'translate',
type: 'updateMessageExtra',
value: { content: '', to: targetLang },
});
toggleChatLoading(true, id, t('translateMessage(start)', { id }) as string);
// detect from language
fetchPresetTaskResult({
params: chainLangDetect(message.content),
}).then((data) => {
if (data && supportLocales.includes(data)) from = data;
});
// translate to target language
await fetchPresetTaskResult({
onMessageHandle: (text) => {
dispatchMessage({
id,
key: 'translate',
type: 'updateMessageExtra',
value: produce({ content: '', from, to: targetLang }, (draft) => {
content += text;
draft.content += content;
}),
});
},
params: chainTranslate(message.content, targetLang),
});
toggleChatLoading(false);
},
});
+23 -17
View File
@@ -52,15 +52,21 @@ export const currentChatsWithGuideMessage = (s: SessionStore): ChatMessage[] =>
const [activeId, isInbox] = [s.activeId, s.activeId === INBOX_SESSION_ID];
const meta = agentSelectors.currentAgentMeta(s);
const inboxMsg = t('inbox.defaultMessage', { ns: 'chat' });
const agentSystemRoleMsg = t('agentDefaultMessageWithSystemRole', {
name: meta.title || t('defaultAgent'),
ns: 'chat',
systemRole: meta.description,
});
const agentMsg = t('agentDefaultMessage', {
id: activeId,
name: meta.title || t('defaultAgent'),
ns: 'chat',
});
const emptyInboxGuideMessage = {
content: isInbox
? t('inbox.defaultMessage')
: !!meta.description
? t('agentDefaultMessageWithSystemRole', {
name: meta.title || t('defaultAgent'),
systemRole: meta.description,
})
: t('agentDefaultMessage', { id: activeId, name: meta.title || t('defaultAgent') }),
content: isInbox ? inboxMsg : !!meta.description ? agentSystemRoleMsg : agentMsg,
createAt: Date.now(),
extra: {},
id: 'default',
@@ -86,22 +92,22 @@ export const chatsMessageString = (s: SessionStore): string => {
return chats.map((m) => m.content).join('');
};
export const currentFunctionCallProps = (
s: SessionStore,
): ((
props: Pick<ChatMessage, 'plugin' | 'function_call' | 'content' | 'id'>,
) => FunctionCallProps) => {
const chatLoadingId = s.chatLoadingId;
return ({ plugin, function_call, content, id }) => {
export const getFunctionMessageParams =
(
s: SessionStore,
): ((
props: Pick<ChatMessage, 'plugin' | 'function_call' | 'content' | 'id'>,
) => FunctionCallProps) =>
({ plugin, function_call, content, id }) => {
const itemId = plugin?.identifier || function_call?.name;
const command = plugin ?? function_call;
const args = command?.arguments;
return {
arguments: args,
command,
content,
id: itemId,
loading: id === chatLoadingId,
loading: id === s.chatLoadingId,
};
};
};
@@ -3,8 +3,8 @@ import {
currentChats,
currentChatsWithGuideMessage,
currentChatsWithHistoryConfig,
currentFunctionCallProps,
getChatsById,
getFunctionMessageParams,
} from './chat';
import { currentTopics, getTopicMessages } from './topic';
@@ -13,8 +13,8 @@ export const chatSelectors = {
currentChats,
currentChatsWithGuideMessage,
currentChatsWithHistoryConfig,
currentFunctionCallProps,
getChatsById,
getFunctionMessageParams,
};
export const topicSelectors = {
+5 -4
View File
@@ -1,6 +1,7 @@
import { PluginRequestPayload } from '@lobehub/chat-plugin-sdk';
import { ErrorType } from '@/types/fetch';
import { Translate } from '@/types/translate';
import { LLMRoleType } from './llm';
import { BaseDataModel } from './meta';
@@ -18,6 +19,9 @@ export interface OpenAIFunctionCall {
name: string;
}
export interface ChatTranslate extends Translate {
content?: string;
}
export interface ChatMessage extends BaseDataModel {
/**
* @title 内容
@@ -29,10 +33,7 @@ export interface ChatMessage extends BaseDataModel {
extra?: {
fromModel?: string;
// 翻译
translate?: {
target: string;
to: string;
};
translate?: ChatTranslate;
} & Record<string, any>;
/**
+4
View File
@@ -0,0 +1,4 @@
export interface Translate {
from: string;
to: string;
}