Rocha commited on
Commit
3a1fcd3
·
1 Parent(s): 88ef15f

Initial commit

Browse files
Files changed (3) hide show
  1. Dockerfile +16 -0
  2. app.py +193 -0
  3. requirements.txt +4 -0
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
2
+ # you will also find guides on how best to write your Dockerfile
3
+
4
+ FROM python:3.11
5
+
6
+ RUN useradd -m -u 1000 user
7
+ USER user
8
+ ENV PATH="/home/user/.local/bin:$PATH"
9
+
10
+ WORKDIR /app
11
+
12
+ COPY --chown=user ./requirements.txt requirements.txt
13
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
14
+
15
+ COPY --chown=user . /app
16
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException, Request
2
+ from pydantic import BaseModel
3
+ import numpy as np
4
+ import nltk
5
+ from nltk.stem.lancaster import LancasterStemmer
6
+ import datetime
7
+ import time
8
+ import json
9
+
10
+ app = FastAPI()
11
+
12
+ # Inicializar el stemmer
13
+ stemmer = LancasterStemmer()
14
+
15
+ # Modelo de datos para la solicitud de entrenamiento
16
+ class TrainingData(BaseModel):
17
+ sentences: list # Lista de diccionarios con "sentence" y "class"
18
+
19
+ # Variables globales para almacenar el modelo entrenado
20
+ synapse_0 = None
21
+ synapse_1 = None
22
+ words = []
23
+ classes = []
24
+
25
+ # Preprocesamiento de datos
26
+ def preprocess_data(training_data):
27
+ global words, classes
28
+ words = []
29
+ classes = []
30
+ documents = []
31
+ ignore_words = ['?']
32
+
33
+ for pattern in training_data:
34
+ w = nltk.word_tokenize(pattern['sentence'])
35
+ words.extend(w)
36
+ documents.append((w, pattern['class']))
37
+ if pattern['class'] not in classes:
38
+ classes.append(pattern['class'])
39
+
40
+ words = [stemmer.stem(w.lower()) for w in words if w not in ignore_words]
41
+ words = list(set(words))
42
+ classes = list(set(classes))
43
+
44
+ # Crear datos de entrenamiento
45
+ training = []
46
+ output = []
47
+ output_empty = [0] * len(classes)
48
+
49
+ for doc in documents:
50
+ bag = []
51
+ pattern_words = doc[0]
52
+ pattern_words = [stemmer.stem(word.lower()) for word in pattern_words]
53
+ for w in words:
54
+ bag.append(1) if w in pattern_words else bag.append(0)
55
+ training.append(bag)
56
+ output_row = list(output_empty)
57
+ output_row[classes.index(doc[1])] = 1
58
+ output.append(output_row)
59
+
60
+ return np.array(training), np.array(output)
61
+
62
+ # Funciones de la red neuronal
63
+ def sigmoid(x):
64
+ return 1 / (1 + np.exp(-x))
65
+
66
+ def sigmoid_output_to_derivative(output):
67
+ return output * (1 - output)
68
+
69
+ def train(X, y, hidden_neurons=10, alpha=1, epochs=50000, dropout=False, dropout_percent=0.5):
70
+ global synapse_0, synapse_1
71
+ print("Training with %s neurons, alpha:%s, dropout:%s %s" % (hidden_neurons, str(alpha), dropout, dropout_percent if dropout else ''))
72
+ print("Input matrix: %sx%s Output matrix: %sx%s" % (len(X), len(X[0]), 1, len(classes)))
73
+ np.random.seed(1)
74
+
75
+ last_mean_error = 1
76
+ synapse_0 = 2 * np.random.random((len(X[0]), hidden_neurons)) - 1
77
+ synapse_1 = 2 * np.random.random((hidden_neurons, len(classes))) - 1
78
+
79
+ prev_synapse_0_weight_update = np.zeros_like(synapse_0)
80
+ prev_synapse_1_weight_update = np.zeros_like(synapse_1)
81
+
82
+ for j in range(epochs + 1):
83
+ layer_0 = X
84
+ layer_1 = sigmoid(np.dot(layer_0, synapse_0))
85
+ layer_2 = sigmoid(np.dot(layer_1, synapse_1))
86
+
87
+ layer_2_error = y - layer_2
88
+
89
+ if (j % 10000) == 0 and j > 5000:
90
+ if np.mean(np.abs(layer_2_error)) < last_mean_error:
91
+ print("delta after " + str(j) + " iterations:" + str(np.mean(np.abs(layer_2_error))))
92
+ last_mean_error = np.mean(np.abs(layer_2_error))
93
+ else:
94
+ print("break:", np.mean(np.abs(layer_2_error)), ">", last_mean_error)
95
+ break
96
+
97
+ layer_2_delta = layer_2_error * sigmoid_output_to_derivative(layer_2)
98
+ layer_1_error = layer_2_delta.dot(synapse_1.T)
99
+ layer_1_delta = layer_1_error * sigmoid_output_to_derivative(layer_1)
100
+
101
+ synapse_1_weight_update = (layer_1.T.dot(layer_2_delta))
102
+ synapse_0_weight_update = (layer_0.T.dot(layer_1_delta))
103
+
104
+ synapse_1 += alpha * synapse_1_weight_update
105
+ synapse_0 += alpha * synapse_0_weight_update
106
+
107
+ prev_synapse_0_weight_update = synapse_0_weight_update
108
+ prev_synapse_1_weight_update = synapse_1_weight_update
109
+
110
+ # Guardar el modelo entrenado
111
+ now = datetime.datetime.now()
112
+ synapse = {'synapse0': synapse_0.tolist(), 'synapse1': synapse_1.tolist(),
113
+ 'datetime': now.strftime("%Y-%m-%d %H:%M"),
114
+ 'words': words,
115
+ 'classes': classes}
116
+ with open("intent_class.json", "w") as outfile:
117
+ json.dump(synapse, outfile, indent=4, sort_keys=True)
118
+ print("Model saved to intent_class.json")
119
+
120
+ # Endpoint para entrenar el modelo
121
+ @app.post("/train")
122
+ async def train_model(data: TrainingData):
123
+ global synapse_0, synapse_1, words, classes
124
+ training_data = data.sentences
125
+
126
+ # Preprocesar los datos
127
+ X, y = preprocess_data(training_data)
128
+
129
+ # Entrenar el modelo
130
+ start_time = time.time()
131
+ train(X, y, hidden_neurons=20, alpha=0.1, epochs=100000, dropout=False, dropout_percent=0.2)
132
+ elapsed_time = time.time() - start_time
133
+ print("Training completed in:", elapsed_time, "seconds")
134
+
135
+ return {"message": "Model trained successfully", "elapsed_time": elapsed_time}
136
+
137
+ # Endpoint para clasificar una frase
138
+ @app.post("/classify")
139
+ async def classify_sentence(request: Request):
140
+ global synapse_0, synapse_1, words, classes
141
+ data = await request.json()
142
+ sentence = data.get("sentence")
143
+
144
+ if not sentence:
145
+ raise HTTPException(status_code=400, detail="No sentence provided")
146
+
147
+ # Clasificar la frase
148
+ ERROR_THRESHOLD = 0.2
149
+ x = bow(sentence.lower(), words)
150
+ l0 = x
151
+ l1 = sigmoid(np.dot(l0, synapse_0))
152
+ l2 = sigmoid(np.dot(l1, synapse_1))
153
+
154
+ results = [[i, r] for i, r in enumerate(l2) if r > ERROR_THRESHOLD]
155
+ results.sort(key=lambda x: x[1], reverse=True)
156
+ return_results = [[classes[r[0]], r[1]] for r in results]
157
+
158
+ return {"sentence": sentence, "classification": return_results}
159
+
160
+ # Función para crear el bag of words
161
+ def bow(sentence, words, show_details=False):
162
+ sentence_words = clean_up_sentence(sentence)
163
+ bag = [0] * len(words)
164
+ for s in sentence_words:
165
+ for i, w in enumerate(words):
166
+ if w == s:
167
+ bag[i] = 1
168
+ if show_details:
169
+ print("found in bag: %s" % w)
170
+ return np.array(bag)
171
+
172
+ # Función para limpiar y tokenizar una frase
173
+ def clean_up_sentence(sentence):
174
+ sentence_words = nltk.word_tokenize(sentence)
175
+ sentence_words = [stemmer.stem(word.lower()) for word in sentence_words]
176
+ return sentence_words
177
+
178
+ # Cargar el modelo si existe
179
+ try:
180
+ with open("intent_class.json", "r") as file:
181
+ synapse = json.load(file)
182
+ synapse_0 = np.asarray(synapse['synapse0'])
183
+ synapse_1 = np.asarray(synapse['synapse1'])
184
+ words = synapse['words']
185
+ classes = synapse['classes']
186
+ print("Model loaded from intent_class.json")
187
+ except FileNotFoundError:
188
+ print("No pre-trained model found. Please train the model first.")
189
+
190
+ if __name__ == "__main__":
191
+ import uvicorn
192
+
193
+ uvicorn.run(app, host="0.0.0.0", port=8500)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ pydantic
3
+ nltk
4
+ numpy