Act as an expert Software Engineer. Do a code review of this multirun.sh script: #!/usr/bin/env bash # # Ollama Multirun # # Bash shell script to run a prompt against all models in Ollama, and save the output as web pages # # Usage: # - Enter prompt manually: ./multirun.sh # - Enter prompt as argument: ./multirun.sh "your prompt" # - Enter prompt from file: ./multirun.sh < prompt.txt # - Enter prompt from pipe: echo "your prompt" | ./multirun.sh # echo "summarize this file: $(cat filename)" | ./multirun.sh # # - By default, will use all available models # To set a list of models to use, set as a comma-seperated list with -m # example: ./multirun.sh -m deepseek-r1:1.5b,deepseek-r1:8b # # - By default, will use "./results" as the results output directory # To set a results output directory: # ./multirun.sh -r ./path/to/directory # # - By default, will wait 5 minutes for models to respond. # To set new timeout (in seconds): # ./multirun.sh -t 30 if [ -z "$BASH_VERSION" ] || ! (echo "$BASH_VERSION" | awk -F. '{exit !($1 > 3 || ($1 == 3 && $2 >= 2))}') ; then echo "Error: This script requires Bash version 3.2 or higher." >&2 exit 1 fi OLLAMA_MULTIRUN_NAME="ollama-multirun" OLLAMA_MULTIRUN_VERSION="5.21.4" OLLAMA_MULTIRUN_URL="https://github.com/attogram/ollama-multirun" OLLAMA_MULTIRUN_DISCORD="https://discord.gg/BGQJCbYVBa" OLLAMA_MULTIRUN_LICENSE="MIT" OLLAMA_MULTIRUN_COPYRIGHT="Copyright (c) 2025 Ollama Bash Lib, Attogram Project " TIMEOUT="300" # number of seconds to allow model to respond addedImages=() usage() { local me me=$(basename "$0") echo "$OLLAMA_MULTIRUN_NAME"; echo echo "Usage:" echo " ./$me [flags]" echo " ./$me [flags] [prompt]" echo; echo "Flags:"; echo " -h -- Help for $OLLAMA_MULTIRUN_NAME" echo " -m model1,model2 -- Use specific models (comma separated list)" echo " -r -- Set results directory" echo " -t # -- Set timeout, in seconds" echo " -v -- Show version information" echo " [prompt] -- Set the prompt (\"Example prompt\")" } parseCommandLine() { modelsList="" resultsDirectory="results" prompt="" while (( "$#" )); do case "$1" in -h) usage exit 0 ;; -m) # specify models to run if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then modelsList=$2 shift 2 else echo "Error: Argument for $1 is missing" >&2 exit 1 fi ;; -r) # specify results outputDirectory if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then resultsDirectory=$2 shift 2 else echo "Error: Argument for $1 is missing" >&2 exit 1 fi ;; -t) # specify timeout in seconds if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then TIMEOUT=$2 shift 2 else echo "Error: Argument for $1 is missing" >&2 exit 1 fi ;; -v) echo "$OLLAMA_MULTIRUN_NAME v$OLLAMA_MULTIRUN_VERSION" exit 0 ;; -*) # unsupported flags echo "Error: unsupported argument: $1" >&2 exit 1 #shift 1 ;; *) # preserve positional arguments if [ -z "$prompt" ]; then prompt="$1" else prompt+=" $1" fi shift ;; esac done } getDateTime() { date '+%Y-%m-%d %H:%M:%S' } setModels() { models=($(ollama list | awk '{if (NR > 1) print $1}' | sort)) # Get list of models, sorted alphabetically if [ -z "${models[*]}" ]; then echo "No models found. Please install models with 'ollama pull '" >&2 exit 1 fi parsedModels=() if [ -n "$modelsList" ]; then IFS=',' read -ra modelsListArray <<< "$modelsList" # parse csv into modelsListArray for m in "${modelsListArray[@]}"; do local found=0 for existing_model in "${models[@]}"; do if [[ "$existing_model" == "$m" ]]; then found=1 break fi done if [[ $found -eq 1 ]]; then parsedModels+=("$m") else echo "Error: model not found: $m" >&2 exit 1 fi done fi if [ -n "${parsedModels[*]}" ]; then models=("${parsedModels[@]}") fi echo "models:"; echo "${models[@]}" echo } safeString() { local input="$1" # Get the input local length="${2:-40}" # Get length, default to 40 characters input=${input:0:length} # Truncate to first LENGTH characters input=$(echo "$input" | tr '[:upper:]' '[:lower:]') # Convert to lowercase input=${input// /_} # Replace spaces with underscores input=$(echo "$input" | sed 's/[^a-zA-Z0-9_]/_/g' | tr -cd 'a-zA-Z0-9_') # Replace non-allowed characters with underscores echo "$input" # Output the sanitized string } createOutputDirectory() { tag=$(safeString "$prompt") tagDatetime=$(date '+%Y%m%d-%H%M%S') #outputDirectory="$resultsDirectory/${tagDatetime}_${tag}" outputDirectory="$resultsDirectory/${tag}_${tagDatetime}" echo "$(getDateTime)" "Output Directory: $outputDirectory/" if [ ! -d "$outputDirectory" ]; then if ! mkdir -p "$outputDirectory"; then echo "Error: Failed to create Output Directory $outputDirectory" >&2 exit 1 fi fi } setPrompt() { if [ -n "$prompt" ]; then # if prompt is already set from command line return fi if [ -t 0 ]; then # Check if input is from a terminal (interactive) echo "Enter prompt:"; read -r prompt # Read prompt from user input return fi prompt=$(cat) # Read from standard input (pipe or file) } savePrompt() { echo "$(getDateTime)" "Prompt: $prompt" promptFile="$outputDirectory/prompt.txt" echo "$(getDateTime)" "Creating Prompt Text: $promptFile" echo "$prompt" > "$promptFile" promptWords=$(wc -w < "$promptFile" | awk '{print $1}') promptBytes=$(wc -c < "$promptFile" | awk '{print $1}') promptYamlFile="$outputDirectory/$tag.prompt.yaml" echo "$(getDateTime)" "Creating Prompt Yaml: $promptYamlFile" generatePromptYaml > "$promptYamlFile" } generatePromptYaml() { # Github Prompt YAML: https://docs.github.com/en/github-models/use-github-models/storing-prompts-in-github-repositories cat << EOF messages: - role: system content: '' - role: user content: | $(while IFS= read -r line; do echo " $line"; done <<< "$prompt") model: '' EOF } textarea() { local content="$1" # Get the input if [ -z "$content" ]; then content="" fi local padding="$2" if [ -z "$padding" ]; then padding=0 fi local max="$3" if [ -z "$max" ]; then max=25 fi local lines lines=$(printf '%s\n' "$content" | wc -l) # Get number of lines in content lines=$((lines + padding)) if [ "$lines" -gt "$max" ]; then lines=$max fi content=$(echo "$content" | sed 's/&/\&/g; s//\>/g; s/"/\"/g; s/'"'"'/\'/g') # Escape HTML special characters echo "" } showPrompt() { echo "

Prompt: (raw) (yaml)" echo " words:$promptWords bytes:$promptBytes
" textarea "$prompt" 2 10 # 0 padding, max 10 lines echo "

" } showImages() { if [ ${#addedImages[@]} -gt 0 ]; then for image in "${addedImages[@]}"; do echo -n "
" echo -n "\"$image\"" echo -n "
" done echo -n "
" fi } clearModel() { if ! command -v expect >/dev/null 2>&1; then echo "Warning: 'expect' command not found, skipping model clearing." >&2 return fi echo "$(getDateTime)" "Clearing model session: $1" ( expect \ -c "spawn ollama run $1" \ -c "expect \">>> \"" \ -c 'send -- "/clear\n"' \ -c "expect \"Cleared session context\"" \ -c 'send -- "/bye\n"' \ -c "expect eof" \ ; ) > /dev/null 2>&1 # Suppress output if [ $? -ne 0 ]; then echo "ERROR: Failed to clear model session: $1" >&2 # exit 1 fi } stopModel() { echo "$(getDateTime)" "Stopping model: $1" if ! ollama stop "$1"; then echo "$(getDateTime)" "ERROR: Failed to stop model: $1" >&2 # exit 1 fi } showSortableTablesJavascript() { # From: https://github.com/tofsjonas/sortable/ # License: The Unlicense - https://github.com/tofsjonas/sortable/blob/main/LICENSE echo '' echo '' } showHeader() { title="$1" cat << "EOF" EOF echo "$title" } showFooter() { title="$1" echo "

" echo "" } createMenu() { local currentModel="$1" echo "" echo "models: " for modelName in "${models[@]}"; do if [ "$modelName" == "$currentModel" ]; then echo "$modelName " else echo "$modelName " fi done echo ''; } setStats() { statsTotalDuration=$(grep -oE "total duration:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $NF }') statsLoadDuration=$(grep -oE "load duration:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $NF }') statsPromptEvalCount=$(grep -oE "prompt eval count:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $4, $5 }') statsPromptEvalDuration=$(grep -oE "prompt eval duration:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $NF }') statsPromptEvalRate=$(grep -oE "prompt eval rate:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $4, $5 }') statsEvalCount=$(grep -oE "^eval count:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $3, $4 }') statsEvalDuration=$(grep -oE "^eval duration:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $NF }') statsEvalRate=$(grep -oE "^eval rate:[[:space:]]+(.*)" "$modelStatsTxt" | awk '{ print $3, $4 }') mapfile -t addedImages < <(grep -oE "Added image '(.*)'" "$modelStatsTxt" | awk '{ print $NF }' | sed "s/'//g") if [ ${#addedImages[@]} -gt 0 ]; then for image in "${addedImages[@]}"; do if ! [ -f "$outputDirectory/$(basename "$image")" ]; then echo "Copying image: $image" cp "$image" "$outputDirectory" fi done fi responseWords=$(wc -w < "$modelOutputTxt" | awk '{print $1}') responseBytes=$(wc -c < "$modelOutputTxt" | awk '{print $1}') } setOllamaStats() { ollamaVersion=$(ollama -v | awk '{print $4}') # ps columns: 1:NAME, 2:ID, 3:SIZE_NUM 4:SIZE_GB, 5:PROCESSOR_% 6:PROCESS_TYPE, 7:CONTEXT, 8:UNTIL ollamaPs=$(ollama ps | awk '{print $1, $2, $3, $4, $5, $6, $7}' | sed '1d') # Get columns from ollama ps output, skipping the header ollamaModel=$(echo "$ollamaPs" | awk '{print $1}') # Get the model name ollamaSize=$(echo "$ollamaPs" | awk '{print $3, $4}') # Get the model size ollamaProcessor=$(echo "$ollamaPs" | awk '{print $5, $6}') # Get the processor ollamaContext=$(echo "$ollamaPs" | awk '{print $7}') # Get the context size } setSystemStats() { systemArch=$(uname -m) # Get hardware platform systemProcessor=$(uname -p) # Get system processor systemOSName=$(uname -s) # Get system OS name systemOSVersion=$(uname -r) # Get system OS version setSystemMemoryStats } setSystemMemoryStats() { systemMemoryUsed="?" systemMemoryAvail="?" #echo "OS Type: $OSTYPE" case "$OSTYPE" in cygwin|msys) #echo "OS Type match: cygwin|msys" if command -v wmic >/dev/null 2>&1; then local totalMemKB totalMemKB=$(wmic OS get TotalVisibleMemorySize /value 2>/dev/null | grep -E "^TotalVisibleMemorySize=" | cut -d'=' -f2 | tr -d '\r') local availMemKB availMemKB=$(wmic OS get FreePhysicalMemory /value 2>/dev/null | grep -E "^FreePhysicalMemory=" | cut -d'=' -f2 | tr -d '\r') if [ -n "$totalMemKB" ] && [ -n "$availMemKB" ]; then local usedMemKB=$((totalMemKB - availMemKB)) # Convert KB to human readable format (approximate) if [ $usedMemKB -gt 1048576 ]; then systemMemoryUsed="$((usedMemKB / 1048576))G" elif [ $usedMemKB -gt 1024 ]; then systemMemoryUsed="$((usedMemKB / 1024))M" else systemMemoryUsed="${usedMemKB}K" fi if [ "$availMemKB" -gt 1048576 ]; then systemMemoryAvail="$((availMemKB / 1048576))G" elif [ "$availMemKB" -gt 1024 ]; then systemMemoryAvail="$((availMemKB / 1024))M" else systemMemoryAvail="${availMemKB}K" fi fi fi ;; darwin*) #echo "OS Type match: darwin" local top top=$(top -l 1 2>/dev/null || echo "") if [ -n "$top" ]; then systemMemoryUsed=$(echo "$top" | awk '/PhysMem/ {print $2}' || echo "N/A") systemMemoryAvail=$(echo "$top" | awk '/PhysMem/ {print $6}' || echo "N/A") fi ;; *) #echo "OS Type match: *" local top top=$(top -l 1 2>/dev/null || top -bn1 2>/dev/null || echo "") if [ -n "$top" ]; then systemMemoryUsed=$(echo "$top" | awk '/PhysMem/ {print $2}' || echo "N/A") systemMemoryAvail=$(echo "$top" | awk '/PhysMem/ {print $6}' || echo "N/A") fi ;; esac } showSystemStats() { echo "
" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "
System
Ollama proc$ollamaProcessor
Ollama context$ollamaContext
Ollama version$ollamaVersion
Multirun timeout$TIMEOUT seconds
Sys arch$systemArch
Sys processor$systemProcessor
sys memory$systemMemoryUsed + $systemMemoryAvail
Sys OS$systemOSName $systemOSVersion
" } createModelInfoTxt() { # Create model info files - for each model, do 'ollama show' and save the results to text file for model in "${models[@]}"; do modelInfoTxt="$outputDirectory/$(safeString "$model" 80).info.txt" echo "$(getDateTime)" "Creating Model Info Text: $modelInfoTxt" ollama show "$model" > "$modelInfoTxt" done } setModelInfo() { modelInfoTxt="$outputDirectory/$(safeString "$model" 80).info.txt" modelCapabilities=() modelSystemPrompt="" modelTemperature="" local section="" local line while IFS= read -r line; do # Read the content of the file line by line line="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" # Trim leading/trailing whitespace if [[ -z "$line" ]]; then section="" continue; # Skip empty lines fi if [[ $line == "Model"* ]]; then section="Model" continue elif [[ $line == "Capabilities"* ]]; then section="Capabilities" continue elif [[ $line == "System"* ]]; then section="System" continue elif [[ $line == "Parameters"* ]]; then section="Parameters" continue elif [[ $line == "License"* ]]; then section="License" continue elif [[ $line == "Projector"* ]]; then section="Projector" continue fi case $section in "Model") if [[ "$line" == "architecture"* ]]; then modelArchitecture=$(echo "$line" | awk '/architecture/ {print $2}') # Get model architecture fi if [[ "$line" == "parameters"* ]]; then modelParameters=$(echo "$line" | awk '/parameters/ {print $2}') # Get model parameters fi if [[ "$line" == "context length"* ]]; then modelContextLength=$(echo "$line" | awk '/context length/ {print $3}') # Get model context length fi if [[ "$line" == "embedding length"* ]]; then modelEmbeddingLength=$(echo "$line" | awk '/embedding length/ {print $3}') # Get model embedding length fi if [[ "$line" == "quantization"* ]]; then modelQuantization=$(echo "$line" | awk '/quantization/ {print $2}') # Get model quantization fi ;; "Capabilities") modelCapabilities+=("$line") ;; "System") modelSystemPrompt+="$line"$'\n' ;; "Parameters") if [[ "$line" == "temperature"* ]]; then modelTemperature=$(echo "$line" | awk '/temperature/ {print $2}') # Get model temperature fi ;; esac done < "$modelInfoTxt" } createModelsOverviewHtml() { # list of models used in current run modelsIndexHtml="$outputDirectory/models.html" echo "$(getDateTime)" "Creating Models Index Page: $modelsIndexHtml" { showHeader "$OLLAMA_MULTIRUN_NAME: models" titleLink="$OLLAMA_MULTIRUN_NAME: $tag: models: $tagDatetime" echo "
$titleLink
" cat <<- EOF
EOF } > "$modelsIndexHtml" for model in "${models[@]}"; do setModelInfo { echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" } >> "$modelsIndexHtml" done { echo "
Model Architecture Parameters Context
length
Embedding
length
Quantization Temperature Capabilities System prompt (raw) (index)
$model$modelArchitecture$modelParameters$modelContextLength$modelEmbeddingLength$modelQuantization$modelTemperature$(printf "%s
" "${modelCapabilities[@]}")
$modelSystemPromptrawindex
" showSortableTablesJavascript showFooter "$titleLink" } >> "$modelsIndexHtml" } createModelOutputHtml() { modelHtmlFile="$outputDirectory/$(safeString "$model" 80).html" echo "$(getDateTime)" "Creating Model Output Page: $modelHtmlFile" { showHeader "$OLLAMA_MULTIRUN_NAME: $model" titleLink="$OLLAMA_MULTIRUN_NAME: $tag: $model: $tagDatetime" echo "
$titleLink

" createMenu "$model" echo "
" showPrompt showImages modelThinkingTxt="$outputDirectory/$(safeString "$model" 80).thinking.txt" if [ -f "$modelThinkingTxt" ]; then echo "

Thinking: $model (raw)
" textarea "$(cat "$modelThinkingTxt")" 3 15 # 3 padding, max 15 lines echo "

" fi echo "

Output: $model (raw)
" textarea "$(cat "$modelOutputTxt")" 3 25 # 3 padding, max 25 lines echo "

" echo "
" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "
Stats (raw)
Words$responseWords
Bytes$responseBytes
Total duration$statsTotalDuration
Load duration$statsLoadDuration
Prompt eval count$statsPromptEvalCount
Prompt eval duration$statsPromptEvalDuration
Prompt eval rate$statsPromptEvalRate
Eval count$statsEvalCount
Eval duration$statsEvalDuration
Eval rate$statsEvalRate
" echo "
" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "
Model (raw)
Name$model
Architecture$modelArchitecture
Size$ollamaSize
Parameters$modelParameters
Context length$modelContextLength
Embedding length$modelEmbeddingLength
Quantization$modelQuantization
Capabilities$(printf "%s
" "${modelCapabilities[@]}")
" showSystemStats showFooter "$titleLink" } > "$modelHtmlFile" } createOutputIndexHtml() { outputIndexHtml="$outputDirectory/index.html" echo "$(getDateTime)" "Creating Output Index Page: $outputIndexHtml" { showHeader "$OLLAMA_MULTIRUN_NAME: $tag" titleLink="$OLLAMA_MULTIRUN_NAME: $tag: $tagDatetime" echo "
$titleLink

" createMenu "index" echo "
" showPrompt echo "" cat <<- "EOF" EOF } > "$outputIndexHtml" } addModelToOutputIndexHtml() { ( echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" echo "" ) >> "$outputIndexHtml" } finishOutputIndexHtml() { { echo "
Model Response
words
Response
bytes
Total
duration
Load
duration
Prompt eval
count
Prompt eval
duration
Prompt eval
rate
Eval
count
Eval
duration
Eval
rate
Model
params
Model
size
Model
context
Ollama
context
Ollama
proc
$model$responseWords$responseBytes$statsTotalDuration$statsLoadDuration$statsPromptEvalCount$statsPromptEvalDuration$statsPromptEvalRate$statsEvalCount$statsEvalDuration$statsEvalRate$modelParameters$ollamaSize$modelContextLength$ollamaContext$ollamaProcessor
" echo "

" showSystemStats showSortableTablesJavascript titleLink="$OLLAMA_MULTIRUN_NAME: $tag: $tagDatetime" showFooter "$titleLink" } >> "$outputIndexHtml" local imagesHtml imagesHtml=$(showImages) local tmpfile tmpfile=$(mktemp) sed "s##${imagesHtml}#" "$outputIndexHtml" > "$tmpfile" && mv "$tmpfile" "$outputIndexHtml" } getSortedResultsDirectories() { # Sort directories by datetime at end of directory name ls -d "$resultsDirectory"/* | awk 'match($0, /[0-9]{8}-[0-9]{6}$/) { print $0, substr($0, RSTART, RLENGTH) }' | sort -k2 -r | cut -d' ' -f1 } createMainIndexHtml() { resultsIndexFile="${resultsDirectory}/index.html" echo "$(getDateTime)" "Creating Main Index Page: $resultsIndexFile" { showHeader "$OLLAMA_MULTIRUN_NAME: results" titleLink="$OLLAMA_MULTIRUN_NAME" echo "
$titleLink
" echo "

Models Index

" echo "

Runs:

    " for dir in $(getSortedResultsDirectories); do if [ -d "$dir" ]; then echo "
  • ${dir##*/}
  • " fi done echo "

" showFooter "$titleLink" } > "$resultsIndexFile" } createMainModelIndexHtml() { # create table of contents: list all models used in all run results, and links to every individual model run local modelsFound=() local modelsIndex=() local mainModelIndexHtml for dir in $(getSortedResultsDirectories); do # for each item in main results directory if [ -d "$dir" ]; then # if is a directory for file in "$dir"/*.html; do # for each *.html file in the directory if [[ $file != *"/index.html" && $file != *"/models.html" ]]; then # skip index.html and models.html fileName="${file##*/}" modelName="${fileName%.html}" # remove .html to get model name local found=0 for f in "${modelsFound[@]}"; do if [[ "$f" == "$modelName" ]]; then found=1 break fi done if [[ $found -eq 0 ]]; then modelsFound+=("$modelName") fi modelsIndex+=("$modelName:$dir/$fileName") fi done fi done mainModelIndexHtml="$resultsDirectory/models.html" echo; echo "$(getDateTime)" "Creating Main Model Index Page: $mainModelIndexHtml" { showHeader "$OLLAMA_MULTIRUN_NAME: Model Run Index" titleLink="$OLLAMA_MULTIRUN_NAME: Model Run Index" echo "
$titleLink
" echo '

Models: ' for foundModel in "${modelsFound[@]}"; do echo "$foundModel " done echo '

' echo "
    " for foundModel in "${modelsFound[@]}"; do echo "
  • $foundModel
  • " echo "
      " for modelIndex in "${modelsIndex[@]}"; do modelName=${modelIndex%%:*} # get everything before the : if [ "$modelName" == "$foundModel" ]; then run=${modelIndex#*:} # get everything after the : runLink="${run#"$resultsDirectory"/}" # remove the results directory from beginning runName="${runLink%/*}" # remove everything after last slash including the slash echo "
    • $runName
    • " fi done echo '
    ' done echo "
" echo "

top

" showFooter "$titleLink" } > "$mainModelIndexHtml" } runModelWithTimeout() { echo "$prompt" | ollama run --verbose "${model}" > "${modelOutputTxt}" 2> "${modelStatsTxt}" & local pid=$! ( sleep "$TIMEOUT" if kill -0 $pid 2>/dev/null; then echo "[ERROR: Multirun Timeout after ${TIMEOUT} seconds]" > "${modelOutputTxt}" kill $pid 2>/dev/null fi ) & local timeout_pid=$! # Wait for the main process to complete if wait $pid 2>/dev/null; then # Main process completed successfully, kill the timeout process if kill -0 $timeout_pid 2>/dev/null; then kill $timeout_pid 2>/dev/null wait $timeout_pid 2>/dev/null # Clean up the timeout process fi else # Main process was killed (likely by timeout), wait for timeout process wait $timeout_pid 2>/dev/null fi } parseThinkingOutput() { local modelThinkingTxt modelThinkingTxt="$outputDirectory/$(safeString "$model" 80).thinking.txt" # Check for either tags or Thinking... patterns if grep -q -E "(|Thinking\.\.\.)" "$modelOutputTxt"; then #echo "Found thinking content in $modelOutputTxt, extracting..." # Read the entire file content local content content=$(cat "$modelOutputTxt") # Extract thinking content local thinkingContent="" thinkingContent+=$(echo "$content" | sed -n '//,/<\/think>/p' | sed '1d;$d') thinkingContent+=$(echo "$content" | sed -n '/Thinking\.\.\./,/\.\.\.done thinking\./p' | sed '1d;$d') # Remove thinking content from original content=$(echo "$content" | sed '//,/<\/think>/d') content=$(echo "$content" | sed '/Thinking\.\.\./,/\.\.\.done thinking\./d') echo "$(getDateTime)" "Creating Thinking Text: $modelThinkingTxt" echo "$thinkingContent" > "$modelThinkingTxt" echo "$(getDateTime)" "Updating Model Output Text: $modelOutputTxt" echo "$content" > "$modelOutputTxt" fi } export OLLAMA_MAX_LOADED_MODELS=1 parseCommandLine "$@" echo; echo "$OLLAMA_MULTIRUN_NAME v$OLLAMA_MULTIRUN_VERSION"; echo setModels setPrompt echo; echo "$(getDateTime)" "Response Timeout: $TIMEOUT" createOutputDirectory createMainIndexHtml savePrompt createModelInfoTxt createModelsOverviewHtml setSystemStats createOutputIndexHtml for model in "${models[@]}"; do # Loop through each model and run it with the given prompt echo; echo "$(getDateTime)" "Running model: $model" # clearModel "$model" - not needed? modelOutputTxt="$outputDirectory/$(safeString "$model" 80).output.txt" modelStatsTxt="$outputDirectory/$(safeString "$model" 80).stats.txt" echo "$(getDateTime)" "Creating Model Output Text: $modelOutputTxt" echo "$(getDateTime)" "Creating Model Stats Text: $modelStatsTxt" runModelWithTimeout setSystemMemoryStats setOllamaStats parseThinkingOutput setModelInfo setStats createModelOutputHtml addModelToOutputIndexHtml stopModel "$model" done finishOutputIndexHtml createMainModelIndexHtml echo; echo "$(getDateTime)" "Done: $outputDirectory/"