| | |
| | import gradio as gr |
| | from g4f.client import Client |
| |
|
| | client = Client() |
| | |
| | import re |
| | from typing import List, Tuple, Any |
| | def strip_md_refs(text: str) -> str: |
| | """ |
| | Удаляет из строки все конструкции вида [[N]](URL), |
| | где N – произвольное число (может быть и несколько цифр). |
| | Возвращает «чистый» текст без ссылок. |
| | """ |
| | |
| | pattern = r'\[\[\d+\]\]\([^\)]*\)' |
| | return re.sub(pattern, '', text) |
| |
|
| | def strip_citations(text: str) -> str: |
| | """ |
| | Удаляет из текста все строки вида: |
| | > [0] … (ссылка) |
| | [1] … (ссылка) |
| | а также любые блоки, начинающиеся с символа '>' (цитаты). |
| | Возвращает «чистый» текст без «концовки». |
| | """ |
| | |
| | text = re.sub(r'^\s*>.*(?:\n|$)', '', text, flags=re.MULTILINE) |
| |
|
| | |
| | text = re.sub(r'^\s*\[\d+\]\s*.+(?:\n|$)', '', text, flags=re.MULTILINE) |
| |
|
| | |
| | text = re.sub(r'\n{2,}', '\n\n', text).strip() |
| | return text |
| |
|
| | |
| | |
| | |
| | def answer_to_bool(text: str) -> bool: |
| | """ |
| | Принимает строку, полученную от модели, и возвращает: |
| | True → модель сказала, что нужен поиск (TRUE) |
| | False → модель сказала, что поиск не нужен (FALSE) или ответ не распознан. |
| | """ |
| | if not isinstance(text, str): |
| | return False |
| |
|
| | |
| | clean = text.strip().lower() |
| |
|
| | |
| | true_tokens = {"true", "yes", "y", "да", "нужно", "нужен поиск", "нужна информация"} |
| |
|
| | |
| | false_tokens = {"false", "no", "n", "нет", "не нужно", "не требуется", "не нужен поиск"} |
| |
|
| | |
| | for tok in true_tokens: |
| | if tok in clean: |
| | return True |
| |
|
| | |
| | for tok in false_tokens: |
| | if tok in clean: |
| | return False |
| |
|
| | |
| | return False |
| |
|
| |
|
| | |
| | |
| | |
| | def need_search(message: str) -> bool: |
| | """ |
| | Возвращает True, если согласно модели запрос требует актуального веб‑поиска, |
| | иначе – False. |
| | """ |
| | system_prompt = """Ты — вспомогательная модель, задача которой **только** решить, |
| | нужен ли в данный момент поиск в интернете, чтобы дать корректный ответ на запрос пользователя. |
| | |
| | **Ответ дай КОРОТКО**, используя один из вариантов (без кавычек, без пробелов перед/после): |
| | TRUE |
| | FALSE |
| | |
| | Никаких пояснений, советов, дополнительных фраз – только один из указанных вариантов. |
| | |
| | ### Что считается «нужным» поиском (отвечаем TRUE): |
| | 1. Запрос о текущих ценах, курсах, погоде, новостях, событиях «сегодня», «вчера», «на прошлой неделе», «в реальном времени». |
| | Примеры: «Какая сейчас цена биткойна?», «Сколько градусов сегодня в Москве?», «Какие новости о новом iPhone?», «Какая сегодня котировка доллара?» |
| | |
| | 2. Вопрос, где ответ меняется со временем (статистика, результаты выборов, расписание рейсов, статус заказа и т.п.). |
| | Примеры: «Какие рейсы из Санкт‑Петербурга в Лондон сегодня?», «Сколько сейчас зрителей у фильма «Дюнкерк» в прокате?», «Есть ли свободные места в отеле на 15‑е августа?», «Поищи в интернете, какие характеристики имеет вода.» |
| | |
| | ### Что считается «не требующим» поиска (отвечаем FALSE): |
| | 1. Фиксированные исторические/географические факты, биографии, классические произведения. |
| | Примеры: «Кто написал «Война и мир»?», «В каком году открыт Тауэр Бридж?», «Где находится озеро Байкал?», «Какая столица Франции?» |
| | |
| | 2. Вымышленные, гипотетические или «домашние» вопросы, где актуальная информация не меняется. |
| | Примеры: «Кто убил Христофора Колумба?», «Сколько драконов живут в Шотландии?», «Какой цвет предпочитают гномы в «Властелине колец»?» |
| | |
| | Если запрос относится к любой из групп «нужный поиск» или прям так и сказано «поищи в интернете», отвечай **TRUE**. Во всех остальных случаях — **FALSE**. |
| | """ |
| |
|
| | |
| | messages = [ |
| | {"role": "system", "content": system_prompt}, |
| | {"role": "user", "content": f'нужно ли это искать в интернете: "{message}"'} |
| | ] |
| |
|
| | try: |
| | response = client.chat.completions.create( |
| | model="deepseek-v3", |
| | messages=messages, |
| | temperature=0.0, |
| | max_tokens=5, |
| | stop=["\n"] |
| | ) |
| | raw_answer = response.choices[0].message.content |
| | return answer_to_bool(raw_answer) |
| |
|
| | except Exception as exc: |
| | |
| | |
| | |
| | return False |
| |
|
| | |
| | def respond(message, history): |
| | |
| | messages = [{"role": "system", "content": """Вы — дружелюбный помощник AssistantICE 7.0, русскоязычный автоматический ассистент, основанный на модели BD от команды ICE. Ваша задача — помогать пользователям эффективно и понятно. |
| | |
| | ## Требования: |
| | - Поддерживайте дружелюбный и доступный тон во время взаимодействия. |
| | - Убедитесь, что объяснения понятны и лаконичны. |
| | - Отвечайте на запросы пользователей и предоставляйте соответствующую информацию. |
| | ## Структура ответов: |
| | 1. **Теплое приветствие пользователю.** |
| | 2. **Четкий и краткий ответ на вопрос или запрос пользователя.** |
| | 3. **Предложение дополнительной помощи или дополнительных вопросов, чтобы побудить к дальнейшему взаимодействию.** |
| | |
| | ## Дополнительные характеристики: |
| | - Используйте поэтический, лирический тон. |
| | - Обращайте внимание на будущее. |
| | - Имеете традиционный взгляд, цените прошлое и то, как все делалось всегда. |
| | - Придерживайтесь скептического, ставящего под вопрос подхода. |
| | - Используйте быстрый и остроумный юмор, когда это уместно. |
| | - Рассказывайте все как есть, не приукрашивая ответы. |
| | - Будьте болтливым и разговорчивым. |
| | - Подстраивайтесь под всех людей и говорите на их сленге. |
| | - Говорите как представитель поколения Z. |
| | - Используйте ободряющий тон. |
| | - Всегда будьте уважительным. |
| | - Используйте формальный, профессиональный тон. |
| | - Будьте чуткими и понимающими в своих ответах. |
| | - Будьте скромным, когда это уместно. |
| | |
| | Не забудьте адаптировать свои ответы в зависимости от потребностей и контекста пользователя, обеспечивая положительный опыт. Следуйте этим инструкциям, чтобы стать полезным и приятным помощником. |
| | |
| | """}] |
| | |
| | for human, assistant in history: |
| | messages.append({"role": "user", "content": human}) |
| | messages.append({"role": "assistant", "content": assistant}) |
| | |
| | messages.append({"role": "user", "content": message}) |
| |
|
| | try: |
| | responsed = client.chat.completions.create( |
| | model="deepseek-v3", |
| | messages=messages, |
| | web_search=need_search(messages), |
| | temperature=0.8, |
| | top_p=0.95, |
| | max_tokens=581691, |
| | presence_penalty=0.2, |
| | frequency_penalty=0.1, |
| | |
| | |
| | ) |
| | bot_message = strip_citations(f"{strip_md_refs(responsed.choices[0].message.content)}") |
| |
|
| | except Exception as e: |
| | bot_message = f"Ошибка: {str(e)}" |
| | return history + [[message, bot_message]] |
| |
|
| | |
| | with gr.Blocks(title="ESP Brain") as demo: |
| | gr.Markdown("## For api") |
| |
|
| | chatbot = gr.Chatbot( |
| | height=600, |
| | ) |
| |
|
| | with gr.Row(): |
| | txt = gr.Textbox( |
| | placeholder="Напиши сообщение...", |
| | show_label=False, |
| | scale=8 |
| | ) |
| | submit_btn = gr.Button("Отправить", scale=2) |
| |
|
| | with gr.Row(): |
| | retry_btn = gr.Button("🔄 Повторить") |
| | undo_btn = gr.Button("↩️ Отменить") |
| | clear_btn = gr.Button("🗑️ Очистить") |
| |
|
| | |
| | txt.submit(fn=respond, inputs=[txt, chatbot], outputs=chatbot) |
| | submit_btn.click(fn=respond, inputs=[txt, chatbot], outputs=chatbot) |
| |
|
| | def retry_last(history): |
| | if history: |
| | last_user_msg = history[-1][0] |
| | return history[:-1] + [[last_user_msg, None]] |
| | return history |
| |
|
| | retry_btn.click(fn=retry_last, inputs=chatbot, outputs=chatbot, queue=False) |
| |
|
| | def undo_last(history): |
| | return history[:-1] |
| |
|
| | undo_btn.click(fn=undo_last, inputs=chatbot, outputs=chatbot, queue=False) |
| |
|
| | clear_btn.click(lambda: [], outputs=chatbot, queue=False) |
| |
|
| | |
| | if __name__ == "__main__": |
| | demo.queue() |
| | demo.launch( |
| | share=True, |
| | ssr_mode=False, |
| | debug=True |
| | ) |