Merge pull request #51 from n4ze3m/next

v1.1.5
This commit is contained in:
Muhammed Nazeem 2024-04-30 21:11:43 +05:30 committed by GitHub
commit 914e358ee8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 658 additions and 27 deletions

View File

@ -193,7 +193,9 @@
},
"confirm": {
"delete": "Are you sure you want to delete this share? This action cannot be undone."
}
},
"label": "Manage Page Share",
"description": "Enable or disable the page share feature. By default, the page share feature is enabled."
},
"notification": {
"pageShareSuccess": "Page Share URL updated successfully",

View File

@ -196,7 +196,9 @@
},
"confirm": {
"delete": "本当にこの共有を削除しますか?この操作は元に戻せません。"
}
},
"label": "ページ共有を管理する",
"description": "ページ共有機能を有効または無効にします。デフォルトでは、ページ共有機能は有効になっています。"
},
"notification": {
"pageShareSuccess": "ページ共有URLが正常に更新されました",

View File

@ -196,7 +196,9 @@
},
"confirm": {
"delete": "ഈ പങ്കിടല്‍ ഇല്ലാതാക്കണമെന്ന് തീർച്ചയാണോ? ഈ പ്രവർത്തനം പിന്നീട് പിൻവലിക്കാനാകില്ല."
}
},
"label": "പേജ് ഷെയർ നിയന്ത്രിക്കുക",
"description": "പേജ് ഷെയർ സവിശേഷത സജീവമാക്കുകയോ അക്ഷമമാക്കുകയോ ചെയ്യുക. സ്ഥിരംമായി, പേജ് ഷെയർ സവിശേഷത സജീവമാക്കപ്പെടുന്നു."
},
"notification": {
"pageShareSuccess": "പേജ് പങ്കിടാനുള്ള URL വിജയകരമായി അപ്ഡേറ്റ് ചെയ്തു",

View File

@ -0,0 +1,54 @@
{
"pageAssist": "Помощник страницы",
"selectAModel": "Выберите модель",
"save": "Сохранить",
"saved": "Сохранено",
"cancel": "Отмена",
"retry": "Повторить",
"share": {
"tooltip": {
"share": "Поделиться"
},
"modal": {
"title": "Поделиться ссылкой на чат"
},
"form": {
"defaultValue": {
"name": "Аноним",
"title": "Безымянный чат"
},
"title": {
"label": "Название чата",
"placeholder": "Введите название чата",
"required": "Название чата обязательно"
},
"name": {
"label": "Ваше имя",
"placeholder": "Введите ваше имя",
"required": "Ваше имя обязательно"
},
"btn": {
"save": "Создать ссылку",
"saving": "Создание ссылки..."
}
},
"notification": {
"successGenerate": "Ссылка скопирована в буфер обмена",
"failGenerate": "Не удалось создать ссылку"
}
},
"copyToClipboard": "Копировать в буфер обмена",
"webSearch": "Поиск в интернете",
"regenerate": "Пересоздать",
"edit": "Редактировать",
"saveAndSubmit": "Сохранить и отправить",
"editMessage": {
"placeholder": "Введите сообщение..."
},
"submit": "Отправить",
"noData": "Нет данных",
"noHistory": "Нет истории чата",
"chatWithCurrentPage": "Чат с текущей страницей",
"beta": "Бета",
"tts": "Прочитать вслух"
}

View File

@ -0,0 +1,42 @@
{
"addBtn": "Добавить новое знание",
"columns": {
"title": "Название",
"status": "Статус",
"embeddings": "Модель вложения",
"createdAt": "Создано",
"action": "Действия"
},
"expandedColumns": {
"name": "Имя"
},
"tooltip": {
"delete": "Удалить"
},
"confirm": {
"delete": "Вы уверены, что хотите удалить это знание?"
},
"deleteSuccess": "Знание успешно удалено",
"status": {
"pending": "Ожидание",
"finished": "Завершено",
"processing": "Обработка"
},
"addKnowledge": "Добавить знание",
"form": {
"title": {
"label": "Название знания",
"placeholder": "Введите название знания",
"required": "Название знания обязательно"
},
"uploadFile": {
"label": "Загрузить файл",
"uploadText": "Перетащите файл сюда или нажмите, чтобы загрузить",
"uploadHint": "Поддерживаемые типы файлов: .pdf, .csv, .txt, .md",
"required": "Файл обязателен"
},
"submit": "Отправить",
"success": "Знание успешно добавлено"
},
"noEmbeddingModel": "Пожалуйста, сначала добавьте модель вложения на странице настроек Ollama"
}

View File

@ -0,0 +1,12 @@
{
"newChat": "Новый чат",
"selectAPrompt": "Выберите подсказку",
"githubRepository": "Репозиторий GitHub",
"settings": "Настройки",
"sidebarTitle": "История чата",
"error": "Ошибка",
"somethingWentWrong": "Что-то пошло не так",
"validationSelectModel": "Пожалуйста, выберите модель, чтобы продолжить",
"deleteHistoryConfirmation": "Вы уверены, что хотите удалить эту историю?",
"editHistoryTitle": "Введите новое название"
}

View File

@ -0,0 +1,28 @@
{
"ollamaState": {
"searching": "Поиск вашего Ollama 🦙",
"running": "Ollama работает 🦙",
"notRunning": "Не удалось подключиться к Ollama 🦙"
},
"formError": {
"noModel": "Пожалуйста, выберите модель",
"noEmbeddingModel": "Пожалуйста, установите модель вложения на странице Настройки > Ollama"
},
"form": {
"textarea": {
"placeholder": "Введите сообщение..."
},
"webSearch": {
"on": "Вкл",
"off": "Выкл"
}
},
"tooltip": {
"searchInternet": "Поиск в Интернете",
"speechToText": "Речь в текст",
"uploadImage": "Загрузить изображение",
"stopStreaming": "Остановить поток",
"knowledge": "Знание"
},
"sendWhenEnter": "Отправить при нажатии клавиши Enter"
}

View File

@ -0,0 +1,269 @@
{
"generalSettings": {
"title": "Общие настройки",
"settings": {
"heading": "Настройки веб-интерфейса",
"speechRecognitionLang": {
"label": "Язык распознавания речи",
"placeholder": "Выберите язык"
},
"language": {
"label": "Язык",
"placeholder": "Выберите язык"
},
"darkMode": {
"label": "Сменить тему",
"options": {
"light": "Светлая",
"dark": "Темная"
}
}
},
"webSearch": {
"heading": "Управление веб-поиском",
"searchMode": {
"label": "Выполнить простой интернет-поиск"
},
"provider": {
"label": "Поисковый движок",
"placeholder": "Выберите поисковый движок"
},
"totalSearchResults": {
"label": "Общее количество результатов поиска",
"placeholder": "Введите общее количество результатов поиска"
}
},
"system": {
"heading": "Настройки системы",
"deleteChatHistory": {
"label": "Удалить историю чата",
"button": "Удалить",
"confirm": "Вы уверены, что хотите удалить историю чата? Это действие нельзя отменить."
},
"export": {
"label": "Экспорт истории чата, настроек и подсказок",
"button": "Экспорт данных",
"success": "Экспорт успешен"
},
"import": {
"label": "Импорт истории чата, настроек и подсказок",
"button": "Импорт данных",
"success": "Импорт успешен",
"error": "Ошибка импорта"
}
},
"tts": {
"heading": "Настройки текст в речь",
"ttsEnabled": {
"label": "Включить текст в речь"
},
"ttsProvider": {
"label": "Поставщик текста в речь",
"placeholder": "Выберите поставщика"
},
"ttsVoice": {
"label": "Голос текста в речь",
"placeholder": "Выберите голос"
},
"ssmlEnabled": {
"label": "Включить SSML (язык разметки синтеза речи)"
}
}
},
"manageModels": {
"title": "Управление моделями",
"addBtn": "Добавить новую модель",
"columns": {
"name": "Название",
"digest": "Дайджест",
"modifiedAt": "Изменено",
"size": "Размер",
"actions": "Действия"
},
"expandedColumns": {
"parentModel": "Родительская модель",
"format": "Формат",
"family": "Семейство",
"parameterSize": "Размер параметров",
"quantizationLevel": "Уровень квантования"
},
"tooltip": {
"delete": "Удалить модель",
"repull": "Переполучить модель"
},
"confirm": {
"delete": "Вы уверены, что хотите удалить эту модель?",
"repull": "Вы уверены, что хотите переполучить эту модель?"
},
"modal": {
"title": "Добавить новую модель",
"placeholder": "Введите название модели",
"pull": "Получить модель"
},
"notification": {
"pullModel": "Получение модели",
"pullModelDescription": "Получение модели {{modelName}}. Для получения дополнительной информации проверьте значок расширения.",
"success": "Успех",
"error": "Ошибка",
"successDescription": "Модель успешно получена",
"successDeleteDescription": "Модель успешно удалена",
"someError": "Что-то пошло не так. Пожалуйста, попробуйте позже"
}
},
"managePrompts": {
"title": "Управление подсказками",
"addBtn": "Добавить новую подсказку",
"option1": "Обычная",
"option2": "RAG",
"questionPrompt": "Вопросная подсказка",
"columns": {
"title": "Название",
"prompt": "Подсказка",
"type": "Тип подсказки",
"actions": "Действия"
},
"systemPrompt": "Системная подсказка",
"quickPrompt": "Быстрая подсказка",
"tooltip": {
"delete": "Удалить подсказку",
"edit": "Редактировать подсказку"
},
"confirm": {
"delete": "Вы уверены, что хотите удалить эту подсказку? Это действие нельзя отменить."
},
"modal": {
"addTitle": "Добавить новую подсказку",
"editTitle": "Редактировать подсказку"
},
"form": {
"title": {
"label": "Название",
"placeholder": "Моя замечательная подсказка",
"required": "Пожалуйста, введите название"
},
"prompt": {
"label": "Подсказка",
"placeholder": "Введите подсказку",
"required": "Пожалуйста, введите подсказку",
"help": "Вы можете использовать {key} в качестве переменной в своей подсказке."
},
"isSystem": {
"label": "Это системная подсказка"
},
"btnSave": {
"saving": "Добавление подсказки...",
"save": "Добавить подсказку"
},
"btnEdit": {
"saving": "Обновление подсказки...",
"save": "Обновить подсказку"
}
},
"notification": {
"addSuccess": "Подсказка добавлена",
"addSuccessDesc": "Подсказка успешно добавлена",
"error": "Ошибка",
"someError": "Что-то пошло не так. Пожалуйста, попробуйте позже",
"updatedSuccess": "Подсказка обновлена",
"updatedSuccessDesc": "Подсказка успешно обновлена",
"deletedSuccess": "Подсказка удалена",
"deletedSuccessDesc": "Подсказка успешно удалена"
}
},
"manageShare": {
"title": "Управление обменом",
"heading": "Настройка URL обмена страницей",
"form": {
"url": {
"label": "URL обмена страницей",
"placeholder": "Введите URL обмена страницей",
"required": "Пожалуйста, введите ваш URL обмена страницей!",
"help": "По соображениям конфиденциальности вы можете самостоятельно разместить страницу обмена и указать здесь URL. <anchor>Узнать больше</anchor>."
}
},
"webshare": {
"heading": "Веб-обмен",
"columns": {
"title": "Название",
"url": "URL",
"actions": "Действия"
},
"tooltip": {
"delete": "Удалить обмен"
},
"confirm": {
"delete": "Вы уверены, что хотите удалить этот обмен? Это действие нельзя отменить."
},
"label": "Управление общим доступом к странице",
"description": "Включите или отключите функцию общего доступа к странице. По умолчанию функция общего доступа к странице включена."
},
"notification": {
"pageShareSuccess": "URL обмена страницей успешно обновлен",
"someError": "Что-то пошло не так. Пожалуйста, попробуйте позже",
"webShareDeleteSuccess": "Веб-обмен успешно удален"
}
},
"ollamaSettings": {
"title": "Настройки Ollama",
"heading": "Настройка Ollama",
"settings": {
"ollamaUrl": {
"label": "URL Ollama",
"placeholder": "Введите URL Ollama"
},
"ragSettings": {
"label": "Настройки RAG",
"model": {
"label": "Модель вложения",
"required": "Пожалуйста, выберите модель",
"help": "Настоятельно рекомендуется использовать модели вложения, например, `nomic-embed-text`.",
"placeholder": "Выберите модель"
},
"chunkSize": {
"label": "Размер фрагмента",
"placeholder": "Введите размер фрагмента",
"required": "Пожалуйста, введите размер фрагмента"
},
"chunkOverlap": {
"label": "Перекрытие фрагментов",
"placeholder": "Введите перекрытие фрагментов",
"required": "Пожалуйста, введите перекрытие фрагментов"
}
},
"prompt": {
"label": "Настройка системной подсказки RAG",
"option1": "Обычная",
"option2": "Веб",
"alert": "Настройка системной подсказки здесь устарела. Используйте раздел Управление подсказками для добавления или редактирования подсказок. Этот раздел будет удален в будущем выпуске",
"systemPrompt": "Системная подсказка",
"systemPromptPlaceholder": "Введите системную подсказку",
"webSearchPrompt": "Подсказка для веб-поиска",
"webSearchPromptHelp": "Не удаляйте `{search_results}` из подсказки.",
"webSearchPromptError": "Пожалуйста, введите подсказку для веб-поиска",
"webSearchPromptPlaceholder": "Введите подсказку для веб-поиска",
"webSearchFollowUpPrompt": "Последующая подсказка для веб-поиска",
"webSearchFollowUpPromptHelp": "Не удаляйте `{chat_history}` и `{question}` из подсказки.",
"webSearchFollowUpPromptError": "Введите подсказку для последующего веб-поиска!",
"webSearchFollowUpPromptPlaceholder": "Ваша подсказка для последующего веб-поиска"
}
}
},
"manageSearch": {
"title": "Управление веб-поиском",
"heading": "Настройка веб-поиска"
},
"about": {
"title": "О программе",
"heading": "О программе",
"chromeVersion": "Версия Page Assist",
"ollamaVersion": "Версия Ollama",
"support": "Вы можете поддержать проект Page Assist, сделав пожертвование или спонсорирование через следующие платформы:",
"koFi": "Поддержать на Ko-fi",
"githubSponsor": "Стать спонсором на GitHub",
"githubRepo": "Репозиторий GitHub"
},
"manageKnowledge": {
"title": "Управление знаниями",
"heading": "Настройка базы знаний"
}
}

View File

@ -0,0 +1,7 @@
{
"tooltip": {
"embed": "Внедрение страницы может занять несколько минут. Пожалуйста, подождите...",
"clear": "Очистить историю чата",
"history": "История чата"
}
}

View File

@ -197,7 +197,9 @@
},
"confirm": {
"delete": "您确定要删除此对话共享吗?这个操作不能撤销。"
}
},
"label": "管理页面分享",
"description": "启用或禁用页面分享功能。默认情况下,页面分享功能已启用。"
},
"notification": {
"pageShareSuccess": "对话共享服务 URL 已成功更新",

BIN
src/assets/onest.ttf Normal file

Binary file not shown.

View File

@ -1,9 +1,19 @@
@font-face {
font-family: "font";
src: url("font.ttf") format("truetype");
font-family: "Inter";
src: url("inter.ttf") format("truetype");
}
* {
font-family: "font" !important;
@font-face {
font-family: "Onest";
src: url("onest.ttf") format("truetype");
}
.inter {
font-family: "Inter", sans-serif !important;
}
.onest {
font-family: "Onest", sans-serif !important;
}
@tailwind base;
@ -62,6 +72,6 @@
/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}

View File

@ -20,6 +20,7 @@ import { ShareBtn } from "~/components/Common/ShareBtn"
import { useTranslation } from "react-i18next"
import { OllamaIcon } from "../Icons/Ollama"
import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnwledge"
import { useStorage } from "@plasmohq/storage/hook"
export default function OptionLayout({
children
@ -28,6 +29,7 @@ export default function OptionLayout({
}) {
const [sidebarOpen, setSidebarOpen] = useState(false)
const { t } = useTranslation(["option", "common"])
const [shareModeEnabled] = useStorage("shareMode", true)
const {
selectedModel,
@ -107,7 +109,7 @@ export default function OptionLayout({
<div>
<Select
value={selectedModel}
onChange={(e) => {
onChange={(e) => {
setSelectedModel(e)
localStorage.setItem("selectedModel", e)
}}
@ -175,9 +177,10 @@ export default function OptionLayout({
<div className="flex flex-1 justify-end px-4">
<div className="ml-4 flex items-center md:ml-6">
<div className="flex gap-4 items-center">
{pathname === "/" && messages.length > 0 && !streaming && (
<ShareBtn messages={messages} />
)}
{pathname === "/" &&
messages.length > 0 &&
!streaming &&
shareModeEnabled && <ShareBtn messages={messages} />}
<Tooltip title={t("githubRepository")}>
<a
href="https://github.com/n4ze3m/page-assist"

View File

@ -1,15 +1,17 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { Form, Input, Skeleton, Table, Tooltip, message } from "antd"
import { Form, Input, Skeleton, Switch, Table, Tooltip, message } from "antd"
import { Trash2 } from "lucide-react"
import { Trans, useTranslation } from "react-i18next"
import { SaveButton } from "~/components/Common/SaveButton"
import { deleteWebshare, getAllWebshares, getUserId } from "@/db"
import { getPageShareUrl, setPageShareUrl } from "~/services/ollama"
import { verifyPageShareURL } from "~/utils/verify-page-share"
import { useStorage } from "@plasmohq/storage/hook"
export const OptionShareBody = () => {
const queryClient = useQueryClient()
const { t } = useTranslation(["settings"])
const [shareModeEnabled, setShareModelEnabled] = useStorage("shareMode", true)
const { status, data } = useQuery({
queryKey: ["fetchShareInfo"],
@ -132,6 +134,20 @@ export const OptionShareBody = () => {
</div>
</Form.Item>
</Form>
<div className="space-y-2 flex mb-4 flex-row items-center justify-between rounded-lg dark:border-gray-600 ">
<div className="space-y-0.5">
<label className="text-sm font-semibold leading-5 text-gray-900 dark:text-white">
{t("manageShare.webshare.label")}
</label>
<p className="text-sm font-normal leading-5 text-gray-500 dark:text-gray-400">
{t("manageShare.webshare.description")}
</p>
</div>
<Switch
checked={shareModeEnabled}
onChange={setShareModelEnabled}
/>
</div>
</div>
<div>
<div>

View File

@ -11,13 +11,16 @@ import { PageAssistProvider } from "@/components/Common/PageAssistProvider"
function IndexOption() {
const { mode } = useDarkMode()
const { t } = useTranslation()
const { t, i18n } = useTranslation()
return (
<MemoryRouter>
<ConfigProvider
theme={{
algorithm:
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
token: {
fontFamily: i18n.language === "ru" ? "Onest" : "Inter"
}
}}
renderEmpty={() => (
<Empty

View File

@ -11,14 +11,17 @@ import { PageAssistProvider } from "@/components/Common/PageAssistProvider"
function IndexSidepanel() {
const { mode } = useDarkMode()
const { t } = useTranslation()
const { t, i18n } = useTranslation()
return (
<MemoryRouter>
<ConfigProvider
theme={{
algorithm:
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
token: {
fontFamily: i18n.language === "ru" ? "Onest" : "Inter"
}
}}
renderEmpty={() => (
<Empty

View File

@ -1,6 +1,7 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import { en } from "./lang/en";
import { ru } from "./lang/ru";
import { ml } from "./lang/ml";
import { zh } from "./lang/zh";
import { ja } from "./lang/ja";
@ -14,6 +15,8 @@ i18n
en: en,
ml: ml,
"zh-CN": zh,
ru: ru,
"ru-RU": ru,
zh: zh,
ja: ja,
"ja-JP": ja

15
src/i18n/lang/ru.ts Normal file
View File

@ -0,0 +1,15 @@
import option from "@/assets/locale/ru/option.json";
import playground from "@/assets/locale/ru/playground.json";
import common from "@/assets/locale/ru/common.json";
import sidepanel from "@/assets/locale/ru/sidepanel.json";
import settings from "@/assets/locale/ru/settings.json";
import knowledge from "@/assets/locale/ru/knowledge.json";
export const ru = {
option,
playground,
common,
sidepanel,
settings,
knowledge
}

View File

@ -4,6 +4,10 @@ export const supportLanguage = [
label: "English",
value: "en"
},
{
label: "Russian",
value: "ru"
},
{
label: "മലയാളം",
value: "ml"

View File

@ -0,0 +1,11 @@
{
"extName": {
"message": "Page Assist - Веб-интерфейс для локальных моделей искусственного интеллекта"
},
"extDescription": {
"message": "Используйте запущенные локально модели искусственного интеллекта для помощи в веб-просмотре."
},
"openSidePanelToChat": {
"message": "Открыть Copilot для чата"
}
}

View File

@ -10,12 +10,17 @@ import { OptionSettings } from "./option-settings"
import { OptionShare } from "./option-settings-share"
import { OptionKnowledgeBase } from "./option-settings-knowledge"
import { OptionAbout } from "./option-settings-about"
import { useTranslation } from "react-i18next"
export const OptionRouting = () => {
const { mode } = useDarkMode()
const { i18n } = useTranslation()
return (
<div className={mode === "dark" ? "dark" : "light"}>
<div
className={`${mode === "dark" ? "dark" : "light"} ${
i18n.language === "ru" ? "onest" : "inter"
}`}>
<Routes>
<Route path="/" element={<OptionIndex />} />
<Route path="/settings" element={<OptionSettings />} />
@ -32,9 +37,13 @@ export const OptionRouting = () => {
export const SidepanelRouting = () => {
const { mode } = useDarkMode()
const { i18n } = useTranslation()
return (
<div className={mode === "dark" ? "dark" : "light"}>
<div
className={`${mode === "dark" ? "dark" : "light"} ${
i18n.language === "ru" ? "onest" : "inter"
}`}>
<Routes>
<Route path="/" element={<SidepanelChat />} />
<Route path="/settings" element={<SidepanelSettings />} />

View File

@ -6,5 +6,9 @@ export const SUPPORTED_SERACH_PROVIDERS = [
{
label: "DuckDuckGo",
value: "duckduckgo"
},
{
label: "Sogou",
value: "sogou"
}
]

View File

@ -0,0 +1,127 @@
import { cleanUrl } from "@/libs/clean-url"
import { chromeRunTime } from "@/libs/runtime"
import { PageAssistHtmlLoader } from "@/loader/html"
import {
defaultEmbeddingChunkOverlap,
defaultEmbeddingChunkSize,
defaultEmbeddingModelForRag,
getOllamaURL
} from "@/services/ollama"
import {
getIsSimpleInternetSearch,
totalSearchResults
} from "@/services/search"
import { OllamaEmbeddings } from "@langchain/community/embeddings/ollama"
import type { Document } from "@langchain/core/documents"
import * as cheerio from "cheerio"
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"
import { MemoryVectorStore } from "langchain/vectorstores/memory"
const getCorrectTargeUrl = async (url: string) => {
if (!url) return ""
const res = await fetch(url)
const $ = cheerio.load(await res.text())
const link = $("script").text()
const matches = link.match(/"(.*?)"/)
return matches?.[1] || ""
}
export const localSogouSearch = async (query: string) => {
await chromeRunTime(cleanUrl("https://www.sogou.com/web?query=" + query))
const abortController = new AbortController()
setTimeout(() => abortController.abort(), 10000)
const htmlString = await fetch("https://www.sogou.com/web?query=" + query, {
signal: abortController.signal
})
.then((response) => response.text())
.catch()
const $ = cheerio.load(htmlString)
const $result = $("#main .results")
const nodes = $result.children().map(async (i, el) => {
const $el = $(el)
const title = $el.find(".vr-title").text().replace(/\n/g, "").trim()
let link = $el.find(".vr-title > a").get(0)?.attribs.href
const content = [".star-wiki", ".fz-mid", ".attribute-centent"]
.map((selector) => {
;[".text-lightgray", ".zan-box", ".tag-website"].forEach((cls) => {
$el.find(cls).remove()
})
return $el.find(selector).text().trim() ?? ""
})
.join(" ")
if (link?.startsWith("/")) {
link = await getCorrectTargeUrl(`https://www.sogou.com${link}`)
}
return { title, link, content }
})
const searchResults = await Promise.all(nodes)
return searchResults.filter(
(result) => result.link && result.title && result.content
)
}
export const webSogouSearch = async (query: string) => {
const results = await localSogouSearch(query)
const TOTAL_SEARCH_RESULTS = await totalSearchResults()
const searchResults = results.slice(0, TOTAL_SEARCH_RESULTS)
const isSimpleMode = await getIsSimpleInternetSearch()
if (isSimpleMode) {
await getOllamaURL()
return searchResults.map((result) => {
return {
url: result.link,
content: result.content
}
})
}
const docs: Document<Record<string, any>>[] = []
for (const result of searchResults) {
const loader = new PageAssistHtmlLoader({
html: "",
url: result.link
})
const documents = await loader.loadByURL()
documents.forEach((doc) => {
docs.push(doc)
})
}
const ollamaUrl = await getOllamaURL()
const embeddingModle = await defaultEmbeddingModelForRag()
const ollamaEmbedding = new OllamaEmbeddings({
model: embeddingModle || "",
baseUrl: cleanUrl(ollamaUrl)
})
const chunkSize = await defaultEmbeddingChunkSize()
const chunkOverlap = await defaultEmbeddingChunkOverlap()
const textSplitter = new RecursiveCharacterTextSplitter({
chunkSize,
chunkOverlap
})
const chunks = await textSplitter.splitDocuments(docs)
const store = new MemoryVectorStore(ollamaEmbedding)
await store.addDocuments(chunks)
const resultsWithEmbeddings = await store.similaritySearch(query, 3)
const searchResult = resultsWithEmbeddings.map((result) => {
return {
url: result.metadata.url,
content: result.pageContent
}
})
return searchResult
}

View File

@ -1,7 +1,8 @@
import { getWebSearchPrompt } from "~/services/ollama"
import { webGoogleSearch } from "./local-google"
import { webDuckDuckGoSearch } from "./local-duckduckgo"
import { webGoogleSearch } from "./search-engines/google"
import { webDuckDuckGoSearch } from "./search-engines/duckduckgo"
import { getSearchProvider } from "@/services/search"
import { webSogouSearch } from "./search-engines/sogou"
const getHostName = (url: string) => {
try {
@ -16,6 +17,8 @@ const searchWeb = (provider: string, query: string) => {
switch (provider) {
case "duckduckgo":
return webDuckDuckGoSearch(query)
case "sogou":
return webSogouSearch(query)
default:
return webGoogleSearch(query)
}

View File

@ -24,7 +24,7 @@ export default defineConfig({
srcDir: "src",
outDir: "build",
manifest: {
version: "1.1.4",
version: "1.1.5",
name: '__MSG_extName__',
description: '__MSG_extDescription__',
default_locale: 'en',