SimpleHosting

SimpleHosting
Рейтинг
46
Регистрация
22.08.2017
Sly32 #:
Что за странный вопрос?
Планировал, что скажешь .csv. Захотелось поиздеваться, ну да ладно - в следующий раз. Думал, что ты оговорился, и имел в виду, локальные базы, ну скажем - SQLite.
Sly32 #:
У тебя цель - использовать больше контекста в вопросах.

Так я так и делаю, я разговариваю с другим ИИ, в подробностях говорю, что именно мне нужно, и прошу написать промпт. В самом коде у меня была оптимизация промпта. Но перед тем как выкладывать код на форум, я эту часть кода удалил, конфиденциальности ради.

Sly32 #:
Твое решение не оптимально, более такой поиск используют только в учебных целях, в рабочих проектах - нет.

Давай объясню, что я делаю. У меня есть две программы, мне нужно перенести их из пункта "А", в пункт "Б". Поэтому, я пишу маленькую программу которая делает авто замены. Чтобы я мог нажать одну кнопочку (т.е. запустить программу) и она поменяет все пути к базам, дискам, серверам... Есть еще много чего, о чем я спрашиваю AI, который видит весь код, но лучше промолчу.

Sly32 #:
И вообще мне лень

В том то и дело, мне тоже - лень, доводить до совершенства. Из пары мегабайт я трачу лишь килобайты - и так сойдёт.

Sly32 #:
NoSQL
Это ж какие?
Sly32 #:
заготовка у тебя уже есть, она норм, только допилить.

Я еще не решил, пилить или не пилить. И так экономия - за гранью. А дальше - что, (за следующей, гранью)? Мне AI платить будет что ли?

Sly32 #:
я могу подсказать как исправить, что добавить

Я у AI, дважды переспросил вчера, он сказал, что ты не сможешь докалибаться, мамой говорит клянусь. Скорей всего твои рекомендации на общую картину не повлияют.

Sly32 #:
решил тоже себе собрать свой МСР сервер
Дай.
Sly32 #:
Научить работать с любыми ЛЛМ не только гугловой.
Девиз программы - экономика должна быть экономной, а не - перфекционизм.
Sly32 #:
Ну чтож, ИИ норм написал, учись у него. Проверил, работает? Визуально - должно. С промптом бы я поработал, ну и контекстный поиск  можно было бы улучшить. 

Тут просто поиск по словам, я бы делал вектора.

Так надеялся, что не будет пожеланий по улучшению. Придется в понедельник - допилить.

Sly32 #:
Проверил, работает?

Работает, экономия - нереальная.

Sly32 #:
Ты сейчас пытаешься  сам написать систему, но  у тебя нет для этого компетенций, только потратишь время.
import os
import sys
# --- Подавляем "шумные" предупреждения gRPC/ALTS ---
# Эти строки должны стоять до импорта genai, чтобы быть эффективными.
os.environ["GRPC_VERBOSITY"] = "ERROR"
os.environ["GLOG_minloglevel"] = "3"
# ----------------------------------------------------
import google.generativeai as genai
import re
import time
from datetime import datetime # Добавлен для отметки времени

# --- НАСТРОЙКА ---
# API-ключ, предоставленный пользователем.
GOOGLE_API_KEY = 'ВАШ_API_КЛЮЧ_GEMINI' 
PROJECT_PATH = "D:/путь/путь/путь/путь/путь/путь/путь"
TARGET_EXTENSIONS = ['.tx1', '.tx2', '.tx3', '.tx4', '.tx5']

# Новые константы для файлового ввода/вывода
INPUT_QUERY_FILE = "input_query.txt"
OUTPUT_HISTORY_FILE = "chat_history.txt"

# Максимальный размер контекста, который мы отправляем в модель.
MAX_CONTEXT_SIZE = 100000 # 100К символов

# --- ФУНКЦИЯ: чтение содержимого файла (как в оригинале) ---
def get_file_paths(project_path):
    file_paths = []
    for root, _, files in os.walk(project_path):
        for file in files:
            if any(file.endswith(ext) for ext in TARGET_EXTENSIONS):
                full_path = os.path.join(root, file)
                rel_path = os.path.relpath(full_path, project_path)
                file_paths.append((full_path, rel_path))
    return sorted(file_paths, key=lambda x: x[1])

# --- НОВАЯ ФУНКЦИЯ: Извлечение релевантного контекста (Адаптивный MCP) ---
def extract_relevant_context(project_path, file_paths, user_query):
    """
    Извлекает только те части кода, которые релевантны ЗАПРОСУ ПОЛЬЗОВАТЕЛЯ.
    Этот механизм заменяет полную загрузку контекста (MCP-подобный подход).
    """
    relevant_context = ""
    # Извлекаем ключевые слова (фразы) из запроса пользователя
    query_keywords = user_query.upper().split()
    
    # Создаем набор поисковых терминов, исключая очень короткие слова.
    search_terms = set([k for k in query_keywords if len(k) > 2])
    
    if not search_terms:
        # Если запрос очень короткий или пустой, мы не можем провести адаптивный поиск.
        # В этом случае, мы полагаемся на Fallback-логику ниже.
        pass

    for full_path, rel_path in file_paths:
        try:
            # Читаем файл
            with open(full_path, 'r', encoding='windows-1251', errors='ignore') as f:
                content = f.read()
        except Exception:
            try:
                # Попытка с другой кодировкой
                with open(full_path, 'r', encoding='utf-8', errors='ignore') as f:
                    content = f.read()
            except Exception:
                continue

        relevant_lines = []
        lines = content.split('\n')
        
        # Переменная для контекстного захвата:
        # Включаем 1 строку до и 1 строку после релевантной строки.
        lines_to_include = set()
        
        # Проверяем, есть ли термины для поиска. Если нет, этот блок пропускается.
        if search_terms:
            for i, line in enumerate(lines):
                is_relevant = False
                for term in search_terms:
                    # Ищем целое слово или паттерн (например, "DB" или "LEVEL")
                    if re.search(r'\b' + re.escape(term) + r'\b', line, re.IGNORECASE):
                        is_relevant = True
                        break

                if is_relevant:
                    # Включаем релевантную строку и соседей для контекста
                    lines_to_include.add(i)
                    if i > 0:
                        lines_to_include.add(i - 1)
                    if i < len(lines) - 1:
                        lines_to_include.add(i + 1)
        
        # Собираем контекст для текущего файла
        if lines_to_include:
            relevant_context += f"--- Файл: {rel_path} ---\n"
            
            # Проходим по всем строкам и включаем те, которые были отмечены
            for i in sorted(list(lines_to_include)):
                relevant_context += lines[i] + "\n"
            
            relevant_context += "\n"
            
            # Проверка, не превысили ли мы лимит
            if len(relevant_context) > MAX_CONTEXT_SIZE:
                relevant_context = relevant_context[:MAX_CONTEXT_SIZE] + "\n... КОНТЕКСТ ОБОРВАН (достигнут лимит) ...\n"
                break
                
    if not relevant_context:
        # Fallback: Если ничего не найдено (либо не было ключевых слов, либо они не сработали), 
        # загружаем начало первого файла, как было запланировано в вашей логике.
        print("[ВНИМАНИЕ] Релевантный контекст по ключевым словам не найден. Загружаю первые 10000 символов первого файла.")
        
        if file_paths:
            try:
                with open(file_paths[0][0], 'r', encoding='windows-1251', errors='ignore') as f:
                    content = f.read()
                return "Не удалось найти релевантный код. Загружаю начало первого файла:\n" + content[:10000]
            except:
                return "Не удалось найти и загрузить код."
        
        return "Не удалось найти код."
        
    return relevant_context.strip()


# --- ОСНОВНАЯ ЛОГИКА ПРОГРАММЫ ---
def main():
    
    # 1. Считывание путей и имен файлов
    print(f"--- Сканирование проекта: {PROJECT_PATH} ---")
    file_paths = get_file_paths(PROJECT_PATH)
    
    if not file_paths:
        print(f"[ОШИБКА] Файлы не найдены в папке: {PROJECT_PATH}")
        sys.exit(1)

    # 2. Получение запроса от пользователя ИЗ ФАЙЛА
    
    # Читаем новый запрос
    if not os.path.exists(INPUT_QUERY_FILE):
        print(f"[ОШИБКА] Файл запроса '{INPUT_QUERY_FILE}' не найден.")
        print("Пожалуйста, создайте этот файл и поместите в него свой вопрос.")
        sys.exit(1)
        
    try:
        with open(INPUT_QUERY_FILE, 'r', encoding='utf-8') as f:
            user_input = f.read().strip()
    except Exception as e:
        print(f"[ОШИБКА] Не удалось прочитать файл запроса '{INPUT_QUERY_FILE}': {e}")
        sys.exit(1)

    if not user_input:
        print(f"Файл запроса '{INPUT_QUERY_FILE}' пуст. Запрос отменен.")
        return
        
    print(f"--- Запрос прочитан из {INPUT_QUERY_FILE}: {user_input[:50]}... ---")

    # 3. Извлечение релевантного контекста
    print("... Извлечение релевантного контекста (Адаптивный MCP) ...")
    start_time = time.time()
    # *** Используем user_input для адаптивного поиска! ***
    relevant_context = extract_relevant_context(PROJECT_PATH, file_paths, user_input)
    # ******************************************************
    end_time = time.time()
    print(f"--- Контекст извлечен ({len(relevant_context)} символов за {end_time - start_time:.2f} с) ---")

    # 4. Настройка API
    try:
        # Пытаемся настроить с предоставленным ключом. 
        api_key_to_use = GOOGLE_API_KEY or os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")

        if api_key_to_use:
            genai.configure(api_key=api_key_to_use)
        
        model = genai.GenerativeModel('gemini-2.5-flash')
    except Exception as e:
        print(f"[ОШИБКА НАСТРОЙКИ] Не удалось настроить модель: {e}")
        print("Подсказка: Убедитесь, что ваш API-ключ корректно задан.")
        return

    # 5. Подготовка промпта
    system_prompt = (
        "Ты — опытный программист, специализирующийся на ... и ... "
        "Твоя задача — помочь пользователю. Отвечай на его вопрос, используя только предоставленный РЕЛЕВАНТНЫЙ КОНТЕКСТ. "
        "Анализируй контекст как **полный и достаточный** источник для ответа. "
        "Отвечай точно, ссылаясь на имена файлов, которые ты видишь в контексте, при необходимости.\\n\\n"
        "РЕЛЕВАНТНЫЙ КОНТЕКСТ ПРОЕКТА ...:\\n\\n" + relevant_context
    )

    # 6. Отправка запроса
    print("AI: ...думаю...")
    ai_response_text = ""
    try:
        response = model.generate_content(
            contents=[
                {'role': 'user', 'parts': [{'text': system_prompt}]},
                {'role': 'user', 'parts': [{'text': user_input}]}
            ]
        )
        # 7. Обработка ответа
        if response.text:
            ai_response_text = response.text
        else:
            ai_response_text = f"[ОШИБКА] API вернул пустой ответ. Prompt Feedback: {response.prompt_feedback}"

    except Exception as e:
        ai_response_text = f"[ОШИБКА API] Произошла ошибка при вызове модели: {e}"


    # 8. Сохранение истории в файл
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    new_entry = f"==========================================================\n"
    new_entry += f"[{current_time}] ЗАПРОС (из {INPUT_QUERY_FILE}):\n"
    new_entry += f"{user_input}\n"
    new_entry += f"\n"
    new_entry += f"[{current_time}] ОТВЕТ AI ({len(relevant_context)} символов контекста):\n"
    new_entry += f"{ai_response_text}\n\n"
    
    # Добавляем новую запись в конец файла истории
    try:
        with open(OUTPUT_HISTORY_FILE, 'a', encoding='utf-8') as f: 
            f.write(new_entry)
        
        print(f"--- РЕЗУЛЬТАТ СОХРАНЕН в файл: {OUTPUT_HISTORY_FILE} ---")
        
        # Если была ошибка API, сообщаем об этом в консоли
        if "[ОШИБКА]" in ai_response_text:
            print(f"ВНИМАНИЕ: Произошла ошибка. Проверьте {OUTPUT_HISTORY_FILE} для деталей.")

    except Exception as e:
        print(f"[КРИТИЧЕСКАЯ ОШИБКА] Не удалось записать историю в файл {OUTPUT_HISTORY_FILE}: {e}")


if __name__ == '__main__':
    main()

Sly32 #:
OMG(Oh My God)

Это слово из плана на завтра - вычеркиваю.

Sly32 #:
Неужели за столько дней ты не попробовал погуглить что такое MCP?

Не пробовал, AI - же знает. Зачем?

Sly32 #:
Все, я умываю руки.

Чистые руки это - хорошо.

Почему вы всегда, не отвечаете на самые важные, ключевые вопросы. Мне осталось только прикрутить MCP к своему скрипту, убрать анимацию, и загрузку всего в промпт?

Когда напишу новую программу с MCP, я захочу свернуть код, чтобы - без простыней. Как на этом форуме сворачивать текст?

Sly32 #:
Вообще-то я уже советовал - Использовать Github Copilot.

У него есть MCP? Мне Notepad++ нравится, в него можно добавить? Что можно добавить в Notepad++?

Sly32 #:
но ничто не мешает оплатить подписку

Я уже говорил, кто на работе мешает работать. Подробности умолчу.

Sly32 #:
Ты сейчас пытаешься  сам написать систему, но  у тебя нет для этого компетенций, только потратишь время.

Хотел вначале завтра выучить несколько новых слов, а уж потом отвечать. Но мне же осталось всего лишь прикрутить MCP?

Sly32 #:
А ты математику в школе учил? не знаешь, что такое вектора?

Да, в математике - знаю.

Sly32 #:
И какую ты проблему этим решил?
Еще вчера я думал, что экономный, что я молодец.
Sly32 #:
Локально наверное удобнее всего работать с Ollama.

А так вот какой выход вы рекомендуете - локально. Для локального пользования нужен мощный компьютер. Если шеф денег на AI не даст, так обязательно денег даст на новый компьютер?

Sly32 #:
векторный индекс

Опять что-то новое - завтра разберусь.

Sly32 #:
FAISS

Завтра разберусь.

Еще план на завтра: "Gemini 2.5 Computer Use", "Browserbase", "Apps SDK", "Gemini CLI", "gemini extensions install <GitHub URL или локальный путь>".

Sly32 #:
Обьясни, для чего тебе там анимация
Было медленно, AI и говорит, а давай анимацию сделаем. Я и согласился.
Sly32 #:
Как, показывай.

Вначале я анимацию сделал, а потом как и говорил содержимое директории загнал в память.

Sly32 #:
ОМГ

Что такое ОМГ, я тоже не знаю.

Вы расскажите, что именно вы делаете? Или мне и дальше угадывать, какой самый бюджетный вариант?

Всего: 1300