| | |
| |
|
| | import numpy as np |
| | import pandas as pd |
| | import matplotlib.pyplot as plt |
| | from PIL import Image |
| | import io |
| |
|
| | from bioprocess_model import BioprocessModel |
| | from decorators import gpu_decorator |
| |
|
| | |
| | import torch |
| | from transformers import AutoTokenizer, AutoModelForCausalLM |
| | import json |
| |
|
| | |
| | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| |
|
| | model_path = "Qwen/Qwen2.5-7B" |
| |
|
| | |
| | tokenizer = AutoTokenizer.from_pretrained(model_path) |
| | model = AutoModelForCausalLM.from_pretrained(model_path).to(device).eval() |
| |
|
| | def parse_bounds(bounds_str, num_params): |
| | try: |
| | |
| | bounds_str = bounds_str.replace('inf', 'np.inf') |
| | |
| | bounds = eval(f"[{bounds_str}]") |
| | if len(bounds) != num_params: |
| | raise ValueError("Número de límites no coincide con el número de parámetros.") |
| | lower_bounds = [b[0] for b in bounds] |
| | upper_bounds = [b[1] for b in bounds] |
| | return lower_bounds, upper_bounds |
| | except Exception as e: |
| | print(f"Error al parsear los límites: {e}. Usando límites por defecto.") |
| | lower_bounds = [-np.inf] * num_params |
| | upper_bounds = [np.inf] * num_params |
| | return lower_bounds, upper_bounds |
| |
|
| | def generate_analysis(prompt, max_length=100): |
| | """ |
| | Genera un análisis utilizando el modelo Yi-Coder-9B-Chat. |
| | """ |
| | try: |
| | |
| | inputs = tokenizer(prompt, return_tensors="pt").to(device) |
| | |
| | with torch.no_grad(): |
| | outputs = model.generate( |
| | **inputs, |
| | max_new_tokens=max_length, |
| | eos_token_id=tokenizer.eos_token_id, |
| | pad_token_id=tokenizer.eos_token_id |
| | ) |
| | |
| | analysis = tokenizer.decode(outputs[0], skip_special_tokens=True) |
| | return analysis |
| | except Exception as e: |
| | print(f"Error al generar el análisis con Yi-Coder: {e}. Usando análisis por defecto.") |
| | return "Análisis generado por el modelo de lenguaje." |
| |
|
| | @gpu_decorator(duration=100) |
| | def process_and_plot( |
| | file, |
| | biomass_eq1, biomass_eq2, biomass_eq3, |
| | biomass_param1, biomass_param2, biomass_param3, |
| | biomass_bound1, biomass_bound2, biomass_bound3, |
| | substrate_eq1, substrate_eq2, substrate_eq3, |
| | substrate_param1, substrate_param2, substrate_param3, |
| | substrate_bound1, substrate_bound2, substrate_bound3, |
| | product_eq1, product_eq2, product_eq3, |
| | product_param1, product_param2, product_param3, |
| | product_bound1, product_bound2, product_bound3, |
| | legend_position, |
| | show_legend, |
| | show_params, |
| | biomass_eq_count, |
| | substrate_eq_count, |
| | product_eq_count |
| | ): |
| | |
| | df = pd.read_excel(file.name) |
| | |
| | |
| | expected_columns = ['Tiempo', 'Biomasa', 'Sustrato', 'Producto'] |
| | for col in expected_columns: |
| | if col not in df.columns: |
| | raise KeyError(f"La columna esperada '{col}' no se encuentra en el archivo Excel.") |
| |
|
| | |
| | time = df['Tiempo'].values |
| | biomass_data = df['Biomasa'].values |
| | substrate_data = df['Sustrato'].values |
| | product_data = df['Producto'].values |
| |
|
| | |
| | biomass_eq_count = int(biomass_eq_count) |
| | substrate_eq_count = int(substrate_eq_count) |
| | product_eq_count = int(product_eq_count) |
| |
|
| | |
| | biomass_eqs = [biomass_eq1, biomass_eq2, biomass_eq3][:biomass_eq_count] |
| | biomass_params = [biomass_param1, biomass_param2, biomass_param3][:biomass_eq_count] |
| | biomass_bounds = [biomass_bound1, biomass_bound2, biomass_bound3][:biomass_eq_count] |
| |
|
| | substrate_eqs = [substrate_eq1, substrate_eq2, substrate_eq3][:substrate_eq_count] |
| | substrate_params = [substrate_param1, substrate_param2, substrate_param3][:substrate_eq_count] |
| | substrate_bounds = [substrate_bound1, substrate_bound2, substrate_bound3][:substrate_eq_count] |
| |
|
| | product_eqs = [product_eq1, product_eq2, product_eq3][:product_eq_count] |
| | product_params = [product_param1, product_param2, product_param3][:product_eq_count] |
| | product_bounds = [product_bound1, product_bound2, product_bound3][:product_eq_count] |
| |
|
| | biomass_results = [] |
| | substrate_results = [] |
| | product_results = [] |
| |
|
| | |
| | main_model = BioprocessModel() |
| |
|
| | |
| | for i in range(len(biomass_eqs)): |
| | equation = biomass_eqs[i] |
| | params_str = biomass_params[i] |
| | bounds_str = biomass_bounds[i] |
| |
|
| | try: |
| | main_model.set_model_biomass(equation, params_str) |
| | except ValueError as ve: |
| | raise ValueError(f"Error en la configuración del modelo de biomasa {i+1}: {ve}") |
| |
|
| | params = [param.strip() for param in params_str.split(',')] |
| | lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params)) |
| |
|
| | try: |
| | y_pred = main_model.fit_model( |
| | 'biomass', time, biomass_data, |
| | bounds=(lower_bounds, upper_bounds) |
| | ) |
| | biomass_results.append({ |
| | 'y_pred': y_pred.tolist(), |
| | 'equation': equation, |
| | 'params': main_model.params['biomass'] |
| | }) |
| | except Exception as e: |
| | raise RuntimeError(f"Error al ajustar el modelo de biomasa {i+1}: {e}") |
| |
|
| | |
| | for i in range(len(substrate_eqs)): |
| | equation = substrate_eqs[i] |
| | params_str = substrate_params[i] |
| | bounds_str = substrate_bounds[i] |
| |
|
| | try: |
| | main_model.set_model_substrate(equation, params_str) |
| | except ValueError as ve: |
| | raise ValueError(f"Error en la configuración del modelo de sustrato {i+1}: {ve}") |
| |
|
| | params = [param.strip() for param in params_str.split(',')] |
| | lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params)) |
| |
|
| | try: |
| | y_pred = main_model.fit_model( |
| | 'substrate', time, substrate_data, |
| | bounds=(lower_bounds, upper_bounds) |
| | ) |
| | substrate_results.append({ |
| | 'y_pred': y_pred.tolist(), |
| | 'equation': equation, |
| | 'params': main_model.params['substrate'] |
| | }) |
| | except Exception as e: |
| | raise RuntimeError(f"Error al ajustar el modelo de sustrato {i+1}: {e}") |
| |
|
| | |
| | for i in range(len(product_eqs)): |
| | equation = product_eqs[i] |
| | params_str = product_params[i] |
| | bounds_str = product_bounds[i] |
| |
|
| | try: |
| | main_model.set_model_product(equation, params_str) |
| | except ValueError as ve: |
| | raise ValueError(f"Error en la configuración del modelo de producto {i+1}: {ve}") |
| |
|
| | params = [param.strip() for param in params_str.split(',')] |
| | lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params)) |
| |
|
| | try: |
| | y_pred = main_model.fit_model( |
| | 'product', time, product_data, |
| | bounds=(lower_bounds, upper_bounds) |
| | ) |
| | product_results.append({ |
| | 'y_pred': y_pred.tolist(), |
| | 'equation': equation, |
| | 'params': main_model.params['product'] |
| | }) |
| | except Exception as e: |
| | raise RuntimeError(f"Error al ajustar el modelo de producto {i+1}: {e}") |
| |
|
| | |
| | fig, axs = plt.subplots(3, 1, figsize=(10, 15)) |
| |
|
| | |
| | axs[0].plot(time, biomass_data, 'o', label='Datos de Biomasa') |
| | for i, result in enumerate(biomass_results): |
| | axs[0].plot(time, result['y_pred'], '-', label=f'Modelo de Biomasa {i+1}') |
| | axs[0].set_xlabel('Tiempo') |
| | axs[0].set_ylabel('Biomasa') |
| | if show_legend: |
| | axs[0].legend(loc=legend_position) |
| |
|
| | |
| | axs[1].plot(time, substrate_data, 'o', label='Datos de Sustrato') |
| | for i, result in enumerate(substrate_results): |
| | axs[1].plot(time, result['y_pred'], '-', label=f'Modelo de Sustrato {i+1}') |
| | axs[1].set_xlabel('Tiempo') |
| | axs[1].set_ylabel('Sustrato') |
| | if show_legend: |
| | axs[1].legend(loc=legend_position) |
| |
|
| | |
| | axs[2].plot(time, product_data, 'o', label='Datos de Producto') |
| | for i, result in enumerate(product_results): |
| | axs[2].plot(time, result['y_pred'], '-', label=f'Modelo de Producto {i+1}') |
| | axs[2].set_xlabel('Tiempo') |
| | axs[2].set_ylabel('Producto') |
| | if show_legend: |
| | axs[2].legend(loc=legend_position) |
| |
|
| | plt.tight_layout() |
| | buf = io.BytesIO() |
| | plt.savefig(buf, format='png') |
| | buf.seek(0) |
| | image = Image.open(buf) |
| |
|
| | |
| | prompt = f""" |
| | Analiza estos resultados de cinética y parámetros de bioprocesos, como experto: |
| | |
| | Biomasa: |
| | {json.dumps(biomass_results, indent=2)} |
| | |
| | Sustrato: |
| | {json.dumps(substrate_results, indent=2)} |
| | |
| | Producto: |
| | {json.dumps(product_results, indent=2)} |
| | |
| | Para cada cinética (Biomasa, Sustrato, Producto): |
| | 1. Evalúa el modelo (ajuste, parámetros) |
| | 2. Identifica problemas específicos |
| | 3. Sugiere mejoras concretas |
| | |
| | Concluye con un veredicto general sobre la calidad del modelado. |
| | """ |
| |
|
| | |
| | analysis = generate_analysis(prompt, max_length=1500) |
| |
|
| | return image, analysis |
| |
|