Как известно, у больших языковых моделей (LLM) существуют ограничения по размеру контекстного окна. При постановке вопроса часто невозможно вставить весь исходный текст, что требует объединения кода из разных файлов в одном месте.
В связи с этим я разработал скрипт, который минимизирует исходный код проекта путем удаления пробелов, табуляций, комментариев и тестовых функций. Скрипт позволяет собрать все или выбранные файлы проекта в одном месте.
Для использования просто запустите скрипт в директории вашего проекта, чтобы сгенерировать минимизированный файл out.txt, содержащий оптимизированный код, готовый для использования с крупными языковыми моделями.
Перед запуском скрипта отредактируйте следующие массивы в соответствии с потребностями вашего проекта: folders_to_ignore, extensions_to_search, filenames_to_search, comment_chars и stop_words.
Пример конфигурации для проекта на Rust (включение всех файлов *.rs в out.txt):
folders_to_ignore=("target" ".git" ".github" ".gitignore" ".idea" ) # Folders to ignore extensions_to_search=( "rs" ) # File extensions to search for filenames_to_search=("Cargo.toml") # Filenames to search for comment_chars=("#" "//" "/*") # Characters that denote comments stop_words=("#[cfg(test)]") # Stop words after which to ignore the remaining lines in the file
Пример конфигурации для проекта на Rust (включение только определенных файлов в out.txt):
folders_to_ignore=("target" ".git" ".github" ".gitignore" ".idea" ) # Folders to ignore extensions_to_search=( ) # File extensions to search for filenames_to_search=("Cargo.toml" "lib.rs" "core.rs") # Filenames to search for comment_chars=("#" "//" "/*") # Characters that denote comments stop_words=("#[cfg(test)]") # Stop words after which to ignore the remaining lines in the file
Bash-версия скрипта:
#!/bin/bash # Remove existing out.txt if it exists rm -f out.txt # Arrays folders_to_ignore=("target" ".git" ".github" ".gitignore" ".idea" ) # Folders to ignore extensions_to_search=( "rs" ) # File extensions to search for filenames_to_search=("Cargo.toml" "core.rs" "text.rs" "json.rs") # Filenames to search for comment_chars=("#" "//" "/*") # Characters that denote comments stop_words=("#[cfg(test)]") # Stop words after which to ignore the remaining lines in the file # Build the 'find' command # Start with the basic 'find' command find_cmd="find ." # Add folders to ignore if [ ${#folders_to_ignore[@]} -gt 0 ]; then ignore_dir_expr="" for dir in "${folders_to_ignore[@]}"; do if [ -n "$ignore_dir_expr" ]; then ignore_dir_expr+=" -o " fi ignore_dir_expr+="-path './$dir' -prune" done find_cmd+=" \\( $ignore_dir_expr \\) -o" fi # Add conditions to search for files find_cmd+=" \\( " name_patterns=() # Add file extensions for ext in "${extensions_to_search[@]}"; do name_patterns+=("-name '*.$ext'") done # Add filenames for fname in "${filenames_to_search[@]}"; do name_patterns+=("-name '$fname'") done # Combine all patterns using -o for ((i=0; i<${#name_patterns[@]}; i++)); do find_cmd+=" ${name_patterns[$i]}" if [ $i -lt $((${#name_patterns[@]} - 1)) ]; then find_cmd+=" -o" fi done find_cmd+=" \\) -type f -print" # Print the final command for debugging (you can comment out this line) # echo "Running command: $find_cmd" # Build the regular expression for comments comment_pattern="" for ((i=0; i<${#comment_chars[@]}; i++)); do # Escape special characters in comment characters escaped_char=$(printf '%s\n' "${comment_chars[$i]}" | sed 's/[][(){}.*+?^$\\|/]/\\&/g') if [ $i -eq 0 ]; then comment_pattern="$escaped_char" else comment_pattern="$comment_pattern|$escaped_char" fi done # Execute the 'find' command and process the results while read filepath; do echo -e "\n#### $filepath ####" >> out.txt stop=false # Process the file line by line while IFS= read -r line; do if [ "$stop" = true ]; then break fi # Remove tabs line="${line//$'\t'/}" # Remove leading spaces line="${line#"${line%%[![:space:]]*}"}" # Remove trailing spaces line="${line%"${line##*[![:space:]]}"}" # Skip lines that are empty or contain only spaces if [[ -z "$line" ]]; then continue fi # Check for stop words for stop_word in "${stop_words[@]}"; do if [[ "$line" == "$stop_word" ]]; then stop=true break fi done if [ "$stop" = true ]; then break fi # Skip lines that are comments if [[ "$line" =~ ^($comment_pattern) ]]; then continue fi # Write the processed line to out.txt echo "$line" >> out.txt done < "$filepath" done < <(eval $find_cmd)
PowerShell-версия скрипта:
# Remove existing out.txt if it exists if (Test-Path -Path "out.txt") { Remove-Item -Path "out.txt" -Force } # Define arrays # Folders and files to ignore during the search $foldersToIgnore = @("target", ".git", ".github", ".gitignore", ".idea") # File extensions to search for $extensionsToSearch = @("rs") # Specific filenames to search for $filenamesToSearch = @("Cargo.toml", "core.rs", "text.rs", "json.rs") # Characters that denote comments in the files $commentChars = @("#", "//", "/*") # Words that, when encountered, will stop processing the current file $stopWords = @("#[cfg(test)]") # Function to build file filtering based on provided criteria function Get-FilteredFiles { param ( [string[]]$IgnoreFolders, [string[]]$Extensions, [string[]]$Filenames ) # Build a regex pattern for ignored folders if ($IgnoreFolders.Count -gt 0) { $ignorePattern = ($IgnoreFolders | ForEach-Object { [regex]::Escape($_) }) -join '|' } else { $ignorePattern = "" } # Build a list of filters for extensions and filenames $nameFilters = @() foreach ($ext in $Extensions) { $nameFilters += "*.$ext" } foreach ($fname in $Filenames) { $nameFilters += $fname } # Get all files with the specified extensions or filenames Get-ChildItem -Path . -Recurse -File -Include $nameFilters | Where-Object { if ($ignorePattern) { # Check if the full path contains any of the ignored folders -not ($_.FullName -match "\\($ignorePattern)\\") } else { $true } } } # Build a regex pattern for comments $escapedCommentChars = $commentChars | ForEach-Object { [regex]::Escape($_) } $commentPattern = $escapedCommentChars -join '|' # Get the list of files to process $files = Get-FilteredFiles -IgnoreFolders $foldersToIgnore -Extensions $extensionsToSearch -Filenames $filenamesToSearch # Process each file foreach ($file in $files) { # Add file header to out.txt "`n#### $($file.FullName) ####" | Out-File -FilePath "out.txt" -Append -Encoding utf8 $stop = $false # Read the file line by line Get-Content -Path $file.FullName | ForEach-Object { if ($stop) { return } $line = $_ # Remove tabs $line = $line -replace "`t", "" # Trim leading and trailing spaces $line = $line.Trim() # Skip empty lines if ([string]::IsNullOrWhiteSpace($line)) { return } # Check for stop words foreach ($stopWord in $stopWords) { if ($line -eq $stopWord) { $stop = $true break } } if ($stop) { return } # Skip lines that are comments if ($line -match "^($commentPattern)") { return } # Write the processed line to out.txt $line | Out-File -FilePath "out.txt" -Append -Encoding utf8 } }
P.S.
Содержимое файла out.txt необходимо скопировать в буфер обмена и вставить как текст в окно ввода LLM. Не прикрепляйте файл out.txt к вопросу. Обычно LLM из соображений оптимизации обрабатывает файлы, извлекая из них резюме, и на основе этого резюме отвечает на вопрос. Другими словами, если вы вставите содержимое файла out.txt в окно ввода LLM и затем зададите вопрос, модель будет отвечать на основе всего содержимого файла out.txt.
Исходный код скриптов находится на GitHub, если у вас есть улучшения, то делайте pull request.
ссылка на оригинал статьи https://habr.com/ru/articles/843274/
Добавить комментарий