| import numpy as np |
| import json |
| import gradio as gr |
|
|
| |
| with open("corpus.txt", "r", encoding="utf-8") as f: |
| corpus = f.read().splitlines() |
|
|
| with open("dataset.json", "r", encoding="utf-8") as f: |
| qa_data = json.load(f) |
|
|
| |
| all_texts = corpus + list(qa_data.keys()) + list(qa_data.values()) |
| vocab = list(set(" ".join(all_texts).split())) |
| word2id = {w: i for i, w in enumerate(vocab)} |
| id2word = {i: w for w, i in word2id.items()} |
| vocab_size = len(vocab) |
|
|
| def one_hot(word): |
| vec = np.zeros(vocab_size) |
| if word in word2id: |
| vec[word2id[word]] = 1 |
| return vec |
|
|
| |
| np.random.seed(42) |
| hidden_size = 512 |
| W1 = np.random.randn(vocab_size, hidden_size) * 0.01 |
| W2 = np.random.randn(hidden_size, vocab_size) * 0.01 |
| lr = 0.05 |
|
|
| def softmax(x): |
| e = np.exp(x - np.max(x)) |
| return e / e.sum() |
|
|
| def train_step(sentence): |
| global W1, W2 |
| words = sentence.split() |
| loss = 0 |
| for i in range(len(words)-1): |
| x = one_hot(words[i]) |
| y_true = one_hot(words[i+1]) |
| h = np.dot(x, W1) |
| o = np.dot(h, W2) |
| y_pred = softmax(o) |
| loss += np.mean((y_true - y_pred)**2) |
| grad_o = y_pred - y_true |
| dW2 = np.outer(h, grad_o) |
| dW1 = np.outer(x, np.dot(W2, grad_o)) |
| W1 -= lr * dW1 |
| W2 -= lr * dW2 |
| return loss |
|
|
| |
| for epoch in range(200): |
| total_loss = 0 |
| for line in corpus: |
| total_loss += train_step(line + " <END>") |
| if epoch % 50 == 0: |
| print(f"Pretrain Epoch {epoch}, Loss: {total_loss:.4f}") |
|
|
| |
| for epoch in range(200): |
| total_loss = 0 |
| for q, a in qa_data.items(): |
| total_loss += train_step(q + " " + a) |
| if epoch % 50 == 0: |
| print(f"Finetune Epoch {epoch}, Loss: {total_loss:.4f}") |
|
|
| |
| def generate_reply(question, max_len=30): |
| words = question.split() |
| if words[0] not in word2id: |
| return "Maaf, aku belum ngerti kata itu 🥺" |
| x = one_hot(words[0]) |
| reply = [] |
| for _ in range(max_len): |
| h = np.dot(x, W1) |
| o = np.dot(h, W2) |
| y_pred = softmax(o) |
| pred_id = np.argmax(y_pred) |
| pred_word = id2word[pred_id] |
| if pred_word == "<END>": |
| break |
| reply.append(pred_word) |
| x = one_hot(pred_word) |
| return " ".join(reply) |
|
|
| |
| def chatbot(input_text): |
| return generate_reply(input_text) |
|
|
| demo = gr.Interface(fn=chatbot, |
| inputs="text", |
| outputs="text", |
| title="Chatbot Numpy ala Cici 🤭", |
| description="Mini chatbot dengan training 2 tahap: corpus + Q&A") |
|
|
| if __name__ == "__main__": |
| demo.launch() |