Skip to content

Commit 9d4e1bf

Browse files
committed
Incorporar model_ai y configuración base para servicios de IA
1 parent 8050924 commit 9d4e1bf

13 files changed

Lines changed: 1116 additions & 4 deletions

File tree

config/settings/base.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
2525
# core/
2626
APPS_DIR = ROOT_DIR / "core"
27+
LLAMA_MODEL_DIR = ROOT_DIR / "model_ai/download"
2728

2829
env = environ.Env()
2930
READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False)
@@ -80,6 +81,7 @@
8081
"tracker",
8182
"reference",
8283
"xml_manager",
84+
"model_ai",
8385
]
8486

8587
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS + WAGTAIL
@@ -214,7 +216,7 @@
214216

215217
# Wagtail settings
216218

217-
WAGTAIL_SITE_NAME = "markapi"
219+
WAGTAIL_SITE_NAME = "SciELO XML Tools"
218220

219221
# Search
220222
# https://docs.wagtail.org/en/stable/topics/search/backends.html
@@ -295,6 +297,8 @@
295297
}
296298

297299
# LLAMA
298-
LLAMA_ENABLED = env.bool("LLAMA_ENABLED", default=False)
299-
LLAMA_MODEL_DIR = ROOT_DIR / "llama3/llama-3.2"
300-
MODEL_LLAMA = "llama-3.2-3b-instruct-q4_k_m.gguf"
300+
LLAMA_ENABLED = env.bool("LLAMA_ENABLED", default=True)
301+
MODEL_LLAMA = "llama-3.2-3b-instruct-q4_k_m.gguf"
302+
303+
#Aumento en el límite de campos
304+
DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000
File renamed without changes.

model_ai/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ModelIAConfig(AppConfig):
5+
default_auto_field = "django.db.models.BigAutoField"
6+
name = "model_ai"

model_ai/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class LlamaDisabledError(Exception):
2+
pass
3+
4+
class LlamaModelNotFoundError(FileNotFoundError):
5+
pass
6+
7+
class LlamaNotInstalledError(ImportError):
8+
pass

model_ai/llama.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Standard library imports
2+
import logging
3+
import os
4+
5+
from config.settings.base import (
6+
LLAMA_ENABLED,
7+
LLAMA_MODEL_DIR,
8+
)
9+
10+
# Third-party imports
11+
import google.generativeai as genai
12+
13+
# Local application imports
14+
from model_ai import messages
15+
from model_ai.exceptions import (
16+
LlamaDisabledError,
17+
LlamaModelNotFoundError,
18+
LlamaNotInstalledError,
19+
)
20+
from model_ai.models import LlamaModel
21+
22+
23+
class LlamaService:
24+
# Singleton pattern to cache the LLaMA model instance
25+
_cached_llm = None
26+
27+
def __init__(self, messages=None, response_format=None, max_tokens=4000, temperature=0.1, top_p=0.1, mode='chat', nthreads=2):
28+
self.messages = messages
29+
self.response_format = response_format
30+
self.max_tokens = max_tokens
31+
self.temperature = temperature
32+
self.top_p = top_p
33+
self.mode = mode
34+
35+
model_ai = LlamaModel.objects.first()
36+
37+
# Try to use Gemini if configured
38+
if not model_ai and model_ai.api_key_gemini:
39+
40+
if not LLAMA_ENABLED:
41+
raise LlamaDisabledError("LLaMA is disabled in settings.")
42+
43+
if LlamaService._cached_llm is None:
44+
try:
45+
from llama_cpp import Llama
46+
except ImportError as e:
47+
raise LlamaNotInstalledError("The 'llama-cpp-python' package is not installed. Please use the llama-activated Docker image (Dockerfile.llama).") from e
48+
49+
model_ai = LlamaModel.objects.first()
50+
if not model_ai:
51+
raise LlamaModelNotFoundError("No LLaMA model configured in the database. Please add a LLaMA model entry.")
52+
53+
model_path = os.path.join(LLAMA_MODEL_DIR, model_ai.name_file)
54+
if not os.path.isfile(model_path):
55+
raise LlamaModelNotFoundError(f"LLaMA model file not found at {model_path}. Please ensure the model is downloaded and the path is correct.")
56+
57+
try:
58+
LlamaService._cached_llm = Llama(model_path=model_path, n_ctx=max_tokens, n_threads=nthreads)
59+
except Exception as e:
60+
raise RuntimeError(f"Failed to initialize LLaMA model: {e}") from e
61+
62+
self.llm = LlamaService._cached_llm
63+
64+
def run(self, user_input):
65+
if self.mode == 'chat':
66+
return self._run_as_chat(user_input)
67+
elif self.mode == 'prompt':
68+
return self._run_as_content_generation(user_input)
69+
70+
def _run_as_chat(self, user_input):
71+
""" Run LLaMA in chat mode."""
72+
input = self.messages.copy()
73+
input.append({
74+
'role': 'user',
75+
'content': user_input
76+
})
77+
return self.llm.create_chat_completion(
78+
messages=input,
79+
response_format=self.response_format,
80+
max_tokens=self.max_tokens,
81+
temperature=self.temperature,
82+
top_p=self.top_p
83+
)
84+
85+
def _run_as_content_generation(self, user_input):
86+
""" Run LLaMA in completion mode."""
87+
model_ai = LlamaModel.objects.first()
88+
89+
# Try to use Gemini if configured
90+
if model_ai and model_ai.api_key_gemini:
91+
92+
# Setup Gemini API key
93+
genai.configure(api_key=model_ai.api_key_gemini)
94+
95+
# Fetch the Gemini model
96+
# FIXME: Hardcoded model name
97+
model = genai.GenerativeModel('models/gemini-3.1-flash-lite-preview')
98+
99+
# Generate content using Gemini
100+
return model.generate_content(user_input).text
101+
102+
# Gemini not configured, fallback to LLaMA
103+
else:
104+
return self.llm(
105+
user_input,
106+
max_tokens=self.max_tokens,
107+
temperature=self.temperature,
108+
stop=["\n\n"]
109+
)
110+
111+
class LlamaInputSettings:
112+
@staticmethod
113+
def get_first_metadata(text):
114+
logging.debug(messages.ALL_FIRST_BLOCK.format(text=text))
115+
return messages.ALL_FIRST_BLOCK.format(text=text)
116+
117+
@staticmethod
118+
def get_doi_and_section():
119+
return messages.DOI_AND_SECTION_MESSAGES, messages.DOI_AND_SECTION_FORMAT
120+
121+
@staticmethod
122+
def get_titles():
123+
return messages.TITLE_MESSAGES, messages.TITLE_RESPONSE_FORMAT
124+
125+
@staticmethod
126+
def get_author_config():
127+
return messages.AUTHOR_MESSAGES, messages.AUTHOR_RESPONSE_FORMAT
128+
129+
@staticmethod
130+
def get_affiliations():
131+
return messages.AFFILIATION_MESSAGES, messages.AFFILIATION_RESPONSE_FORMAT
132+
133+
@staticmethod
134+
def get_reference():
135+
return messages.REFERENCE_MESSAGES, messages.REFERENCE_RESPONSE_FORMAT
136+

0 commit comments

Comments
 (0)