Так я так и делаю, я разговариваю с другим ИИ, в подробностях говорю, что именно мне нужно, и прошу написать промпт. В самом коде у меня была оптимизация промпта. Но перед тем как выкладывать код на форум, я эту часть кода удалил, конфиденциальности ради.
Давай объясню, что я делаю. У меня есть две программы, мне нужно перенести их из пункта "А", в пункт "Б". Поэтому, я пишу маленькую программу которая делает авто замены. Чтобы я мог нажать одну кнопочку (т.е. запустить программу) и она поменяет все пути к базам, дискам, серверам... Есть еще много чего, о чем я спрашиваю AI, который видит весь код, но лучше промолчу.
В том то и дело, мне тоже - лень, доводить до совершенства. Из пары мегабайт я трачу лишь килобайты - и так сойдёт.
Я еще не решил, пилить или не пилить. И так экономия - за гранью. А дальше - что, (за следующей, гранью)? Мне AI платить будет что ли?
Я у AI, дважды переспросил вчера, он сказал, что ты не сможешь докалибаться, мамой говорит клянусь. Скорей всего твои рекомендации на общую картину не повлияют.
Тут просто поиск по словам, я бы делал вектора.
Так надеялся, что не будет пожеланий по улучшению. Придется в понедельник - допилить.
Работает, экономия - нереальная.
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()
Это слово из плана на завтра - вычеркиваю.
Не пробовал, AI - же знает. Зачем?
Чистые руки это - хорошо.
Почему вы всегда, не отвечаете на самые важные, ключевые вопросы. Мне осталось только прикрутить MCP к своему скрипту, убрать анимацию, и загрузку всего в промпт?
Когда напишу новую программу с MCP, я захочу свернуть код, чтобы - без простыней. Как на этом форуме сворачивать текст?
У него есть MCP? Мне Notepad++ нравится, в него можно добавить? Что можно добавить в Notepad++?
Я уже говорил, кто на работе мешает работать. Подробности умолчу.
Хотел вначале завтра выучить несколько новых слов, а уж потом отвечать. Но мне же осталось всего лишь прикрутить MCP?
Да, в математике - знаю.
А так вот какой выход вы рекомендуете - локально. Для локального пользования нужен мощный компьютер. Если шеф денег на AI не даст, так обязательно денег даст на новый компьютер?
Опять что-то новое - завтра разберусь.
Завтра разберусь.
Еще план на завтра: "Gemini 2.5 Computer Use", "Browserbase", "Apps SDK", "Gemini CLI", "gemini extensions install <GitHub URL или локальный путь>".
Вначале я анимацию сделал, а потом как и говорил содержимое директории загнал в память.
Что такое ОМГ, я тоже не знаю.
Вы расскажите, что именно вы делаете? Или мне и дальше угадывать, какой самый бюджетный вариант?