Spaces:
Paused
Paused
| """ | |
| model.py - Inference & Model Orchestration Layer | |
| This module encapsulates the logic for loading and executing high-parameter LLMs. | |
| It manages the transition from raw user input to structured data by coordinating | |
| the chat model, embedding model, and Pydantic-based output validation. | |
| """ | |
| from langchain_huggingface import HuggingFaceEmbeddings | |
| from langchain_core.output_parsers import PydanticOutputParser | |
| from schema import PokemonEmeraldResponse | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| CHAT_MODEL_ID = "mistralai/Mistral-Small-Instruct-2409" | |
| EMBEDDING_MODEL_ID = "nomic-ai/nomic-embed-text-v1.5" | |
| def load_chat_model(): | |
| """ | |
| Bootstrap the tokenizer and chat model for the RAG pipeline. | |
| Returns: (model, tokenizer) tuple. | |
| """ | |
| print(f"Loading {CHAT_MODEL_ID} model...") | |
| tokenizer = AutoTokenizer.from_pretrained(CHAT_MODEL_ID) | |
| model = AutoModelForCausalLM.from_pretrained( | |
| CHAT_MODEL_ID, | |
| torch_dtype="auto", | |
| device_map="auto" | |
| ) | |
| print("Model loaded!") | |
| return model, tokenizer | |
| def load_embedding_model(): | |
| """ | |
| Bootstrap the HuggingFaceEmbeddings model for the RAG pipeline. | |
| Returns: An instance of HuggingFaceEmbeddings configured with EMBEDDING_MODEL_ID. | |
| """ | |
| print(f"Loading {EMBEDDING_MODEL_ID} model...") | |
| embedding_model = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL_ID) | |
| print("Model loaded!") | |
| return embedding_model | |
| def generate_answer(chat_model, tokenizer, prompt, max_retries=3): | |
| """ | |
| Executes the core RAG generation loop with automated schema validation. | |
| This function manages the transition from raw model output to structured JSON. | |
| It includes a retry mechanism to handle edge-case parsing failures, ensuring | |
| the final response adheres to the PokemonEmeraldResponse Pydantic schema. | |
| """ | |
| print("Generating chat response...") | |
| inputs = tokenizer(prompt, return_tensors="pt").to("cuda") | |
| inputs_size = len(inputs.input_ids[0]) | |
| parser = PydanticOutputParser(pydantic_object=PokemonEmeraldResponse) | |
| attempt = 0 | |
| while attempt < max_retries: | |
| try: | |
| response = chat_model.generate( | |
| **inputs, | |
| max_new_tokens=256, | |
| num_beams=3, | |
| early_stopping=True, | |
| repetition_penalty=1.2, | |
| length_penalty=1, | |
| ) | |
| output = tokenizer.decode(response[0][inputs_size:], skip_special_tokens=True) | |
| return parser.parse(output) | |
| except Exception as e: | |
| print(f"Chat model response generation failed, attempt {attempt}.") | |
| attempt += 1 | |
| print(f"Parsing failed. Output: {output}") |