ai_chatbot 0.1.6.4 → 0.1.6.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ai_chatbot/version.rb +1 -1
- data/lib/ml_model.py +99 -119
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fee6347bdac6070db1bfbc1711f039103c1237c149f42a7f0b848b85eba98314
|
4
|
+
data.tar.gz: c54c29b235f159921d4b33ac36bc56d505983eb03a25500829d72e9741628983
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f80cec458575b77b6be9879007e3f60830886b88bcfbde28974e9fe1e68b59d61424956a0aea0db62e69e5705e2c8d2b2b97d3e6700ee3b9cdd141530816325f
|
7
|
+
data.tar.gz: d2ac4f47ef9ce02255a60e84a6bff019c9036be5368f79e43748ca945a459c4459c5b53ee7a57a8345114018e03d0f5a1eeab70895ac78bafefed6980223dc59
|
data/lib/ai_chatbot/version.rb
CHANGED
data/lib/ml_model.py
CHANGED
@@ -1,162 +1,142 @@
|
|
1
1
|
import sys
|
2
|
+
import psycopg2
|
3
|
+
import os
|
4
|
+
from dotenv import load_dotenv
|
2
5
|
from sklearn.feature_extraction.text import TfidfVectorizer
|
3
6
|
from sklearn.naive_bayes import MultinomialNB
|
4
7
|
from sklearn.pipeline import make_pipeline
|
5
8
|
from sklearn.metrics.pairwise import cosine_similarity
|
6
|
-
import pickle
|
7
|
-
import os
|
8
9
|
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
# Load or initialize the dataset
|
13
|
-
if os.path.exists("qa_model.pkl"):
|
14
|
-
with open("qa_model.pkl", "rb") as f:
|
15
|
-
model_data = pickle.load(f)
|
16
|
-
questions = model_data.get("questions", [])
|
17
|
-
answers = model_data.get("answers", [])
|
18
|
-
else:
|
19
|
-
questions = [
|
20
|
-
"How to create a new model in Rails?",
|
21
|
-
"What is migration?",
|
22
|
-
"How to add a route?"
|
23
|
-
]
|
24
|
-
answers = [
|
25
|
-
"You can create a model using 'rails generate model'.",
|
26
|
-
"Migration is a database schema change.",
|
27
|
-
"You can add a route in the config/routes.rb file."
|
28
|
-
]
|
29
|
-
|
30
|
-
# Create a pipeline (TF-IDF + MultinomialNB)
|
31
|
-
model = make_pipeline(TfidfVectorizer(), MultinomialNB())
|
32
|
-
model.fit(questions, answers)
|
33
|
-
|
34
|
-
# Populate cache with known questions and answers
|
35
|
-
for q, a in zip(questions, answers):
|
36
|
-
cache[q.lower()] = a
|
37
|
-
|
38
|
-
# Function to predict or retrain the model
|
39
|
-
def main(action, query=None, new_answer=None):
|
40
|
-
if action == "predict":
|
41
|
-
return get_prediction(query)
|
42
|
-
elif action == "train_model":
|
43
|
-
return train_model(query, new_answer)
|
44
|
-
elif action == "update_answer":
|
45
|
-
return update_answer(query, new_answer)
|
46
|
-
elif action == "update_or_delete_question":
|
47
|
-
return update_or_delete_question(query, new_answer)
|
48
|
-
elif action == "list_questions":
|
49
|
-
return list_questions()
|
50
|
-
elif action == "list_answers":
|
51
|
-
return list_answers()
|
10
|
+
# Load environment variables
|
11
|
+
load_dotenv()
|
52
12
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
13
|
+
# Connect to PostgreSQL
|
14
|
+
conn = psycopg2.connect(
|
15
|
+
dbname=os.getenv("DB_NAME"),
|
16
|
+
user=os.getenv("DB_USERNAME"),
|
17
|
+
password=os.getenv("DB_PASSWORD"),
|
18
|
+
host=os.getenv("DB_HOST"),
|
19
|
+
port=os.getenv("DB_PORT"),
|
20
|
+
)
|
21
|
+
cursor = conn.cursor()
|
22
|
+
|
23
|
+
# Fetch data from DB
|
24
|
+
cursor.execute("SELECT question, answer FROM qa_data")
|
25
|
+
rows = cursor.fetchall()
|
26
|
+
questions = [row[0] for row in rows]
|
27
|
+
answers = [row[1] for row in rows]
|
56
28
|
|
57
|
-
|
58
|
-
|
59
|
-
|
29
|
+
# Define the vectorizer and Naive Bayes model
|
30
|
+
vectorizer = TfidfVectorizer()
|
31
|
+
model = MultinomialNB()
|
32
|
+
pipeline = make_pipeline(vectorizer, model)
|
60
33
|
|
61
|
-
|
62
|
-
|
34
|
+
# Train model if there is data
|
35
|
+
if questions:
|
36
|
+
pipeline.fit(questions, answers)
|
63
37
|
|
64
|
-
|
65
|
-
|
66
|
-
|
38
|
+
|
39
|
+
def get_prediction(query):
|
40
|
+
if not questions:
|
41
|
+
return "No questions available in the database."
|
42
|
+
|
43
|
+
query_vec = vectorizer.transform([query])
|
44
|
+
similarities = cosine_similarity(query_vec, vectorizer.transform(questions)).flatten()
|
45
|
+
|
46
|
+
max_sim_index = similarities.argmax()
|
47
|
+
max_similarity = similarities[max_sim_index]
|
67
48
|
|
68
49
|
threshold = 0.65
|
69
50
|
if max_similarity < threshold:
|
70
51
|
return "No good match found. Please provide the correct answer."
|
71
52
|
else:
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
return prediction
|
78
|
-
|
79
|
-
# Function to train the model with a new question and answer
|
53
|
+
return answers[max_sim_index]
|
54
|
+
|
55
|
+
|
56
|
+
# Function to train the model with new data
|
80
57
|
def train_model(new_question, new_answer):
|
81
58
|
global questions, answers
|
82
59
|
|
83
|
-
#
|
60
|
+
# Store in database
|
61
|
+
cursor.execute(
|
62
|
+
"INSERT INTO qa_data (question, answer, created_at, updated_at) VALUES (%s, %s, NOW(), NOW()) ON CONFLICT (question) DO NOTHING",
|
63
|
+
(new_question, new_answer),
|
64
|
+
)
|
65
|
+
conn.commit()
|
66
|
+
|
67
|
+
# Update lists and retrain model
|
84
68
|
questions.append(new_question)
|
85
69
|
answers.append(new_answer)
|
70
|
+
pipeline.fit(questions, answers) # Retrain model
|
86
71
|
|
87
|
-
|
88
|
-
model.fit(questions, answers)
|
89
|
-
|
90
|
-
# **Update cache**
|
91
|
-
cache[new_question.lower()] = new_answer
|
72
|
+
return f"Added: '{new_question}' -> '{new_answer}'"
|
92
73
|
|
93
|
-
# Save the updated model
|
94
|
-
with open("qa_model.pkl", "wb") as f:
|
95
|
-
pickle.dump({"questions": questions, "answers": answers}, f)
|
96
|
-
|
97
|
-
return f"Model retrained with: '{new_question}' -> '{new_answer}'"
|
98
74
|
|
99
75
|
# Function to update an answer
|
100
76
|
def update_answer(existing_question, new_answer):
|
101
|
-
|
102
|
-
|
103
|
-
if existing_question in questions:
|
104
|
-
index = questions.index(existing_question)
|
105
|
-
answers[index] = new_answer
|
106
|
-
|
107
|
-
# Retrain the model
|
108
|
-
model.fit(questions, answers)
|
77
|
+
if existing_question not in questions:
|
78
|
+
return f"Question '{existing_question}' not found."
|
109
79
|
|
110
|
-
|
111
|
-
|
80
|
+
cursor.execute(
|
81
|
+
"UPDATE qa_data SET answer = %s WHERE question = %s", (new_answer, existing_question)
|
82
|
+
)
|
83
|
+
conn.commit()
|
112
84
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
return f"Answer updated for: '{existing_question}'"
|
118
|
-
|
119
|
-
return "Question not found."
|
120
|
-
|
121
|
-
# Function to update or delete a question
|
122
|
-
def update_or_delete_question(existing_question, new_question):
|
123
|
-
global questions, answers
|
85
|
+
# Update lists and retrain model
|
86
|
+
index = questions.index(existing_question)
|
87
|
+
answers[index] = new_answer
|
88
|
+
pipeline.fit(questions, answers)
|
124
89
|
|
125
|
-
|
126
|
-
index = questions.index(existing_question)
|
90
|
+
return f"Updated: '{existing_question}' -> '{new_answer}'"
|
127
91
|
|
128
|
-
if new_question:
|
129
|
-
questions[index] = new_question
|
130
|
-
# **Update cache**
|
131
|
-
cache[new_question.lower()] = answers[index]
|
132
|
-
else:
|
133
|
-
# Delete the question
|
134
|
-
del questions[index]
|
135
|
-
del answers[index]
|
136
92
|
|
137
|
-
|
138
|
-
|
93
|
+
# Function to delete a question
|
94
|
+
def delete_question(existing_question):
|
95
|
+
if existing_question not in questions:
|
96
|
+
return f"Question '{existing_question}' not found."
|
139
97
|
|
140
|
-
|
141
|
-
|
142
|
-
cache.pop(existing_question.lower(), None)
|
98
|
+
cursor.execute("DELETE FROM qa_data WHERE question = %s", (existing_question,))
|
99
|
+
conn.commit()
|
143
100
|
|
144
|
-
|
145
|
-
|
146
|
-
|
101
|
+
index = questions.index(existing_question)
|
102
|
+
del questions[index]
|
103
|
+
del answers[index]
|
104
|
+
pipeline.fit(questions, answers)
|
147
105
|
|
148
|
-
|
106
|
+
return f"Deleted: '{existing_question}'"
|
149
107
|
|
150
|
-
return "Question not found."
|
151
108
|
|
109
|
+
# Function to list questions
|
152
110
|
def list_questions():
|
153
|
-
|
111
|
+
cursor.execute("SELECT question FROM qa_data")
|
112
|
+
return [row[0] for row in cursor.fetchall()]
|
113
|
+
|
154
114
|
|
115
|
+
# Function to list answers
|
155
116
|
def list_answers():
|
156
|
-
|
117
|
+
cursor.execute("SELECT answer FROM qa_data")
|
118
|
+
return [row[0] for row in cursor.fetchall()]
|
157
119
|
|
120
|
+
|
121
|
+
# Command-line execution
|
158
122
|
if __name__ == "__main__":
|
159
123
|
action = sys.argv[1]
|
160
124
|
question = sys.argv[2] if len(sys.argv) > 2 else None
|
161
125
|
answer = sys.argv[3] if len(sys.argv) > 3 else None
|
162
|
-
|
126
|
+
|
127
|
+
if action == "predict":
|
128
|
+
print(get_prediction(question))
|
129
|
+
elif action == "train_model":
|
130
|
+
print(train_model(question, answer))
|
131
|
+
elif action == "update_answer":
|
132
|
+
print(update_answer(question, answer))
|
133
|
+
elif action == "delete_question":
|
134
|
+
print(delete_question(question))
|
135
|
+
elif action == "list_questions":
|
136
|
+
print(list_questions())
|
137
|
+
elif action == "list_answers":
|
138
|
+
print(list_answers())
|
139
|
+
|
140
|
+
# Close DB connection
|
141
|
+
cursor.close()
|
142
|
+
conn.close()
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai_chatbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.6.
|
4
|
+
version: 0.1.6.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sanket
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: open3
|
@@ -24,8 +24,8 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
description:
|
28
|
-
|
27
|
+
description: Added PostgreSQL support, fixed model error. Version 0.1.6.5.1 Details
|
28
|
+
on Git.
|
29
29
|
email:
|
30
30
|
- sanket.tikhande@gmail.com
|
31
31
|
executables: []
|
@@ -58,5 +58,5 @@ requirements: []
|
|
58
58
|
rubygems_version: 3.3.7
|
59
59
|
signing_key:
|
60
60
|
specification_version: 4
|
61
|
-
summary: 'Fix:
|
61
|
+
summary: 'Fix: Added postgres integration'
|
62
62
|
test_files: []
|