pvanand commited on
Commit
4799f28
·
0 Parent(s):

Duplicate from pvanand/RASA_Omdena_demo_model_feature_followup_actions_server

Browse files
.dockerignore ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Include any files or directories that you don't want to be copied to your
2
+ # container here (e.g., local build artifacts, temporary files, etc.).
3
+ #
4
+ # For more help, visit the .dockerignore file reference guide at
5
+ # https://docs.docker.com/engine/reference/builder/#dockerignore-file
6
+
7
+ **/.DS_Store
8
+ **/__pycache__
9
+ **/.venv
10
+ **/.classpath
11
+ **/.dockerignore
12
+ **/.env
13
+ **/.git
14
+ **/.gitignore
15
+ **/.project
16
+ **/.settings
17
+ **/.toolstarget
18
+ **/.vs
19
+ **/.vscode
20
+ **/*.*proj.user
21
+ **/*.dbmdl
22
+ **/*.jfm
23
+ **/bin
24
+ **/charts
25
+ **/docker-compose*
26
+ **/compose*
27
+ **/Dockerfile*
28
+ **/node_modules
29
+ **/npm-debug.log
30
+ **/obj
31
+ **/secrets.dev.yaml
32
+ **/values.dev.yaml
33
+ LICENSE
34
+ README.md
35
+ **/tests
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .rasa
Dockerfile ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # Comments are provided throughout this file to help you get started.
4
+ # If you need more help, visit the Dockerfile reference guide at
5
+ # https://docs.docker.com/engine/reference/builder/
6
+
7
+ ARG PYTHON_VERSION=3.8
8
+ FROM python:${PYTHON_VERSION}-slim as base
9
+
10
+ # Copy the requirements file into the container.
11
+ COPY requirements.txt .
12
+
13
+ # Install the dependencies from the requirements file.
14
+ RUN python -m pip install --no-cache-dir -r requirements.txt
15
+
16
+
17
+ # Prevents Python from writing pyc files.
18
+ ENV PYTHONDONTWRITEBYTECODE=1
19
+
20
+ # Keeps Python from buffering stdout and stderr to avoid situations where
21
+ # the application crashes without emitting any logs due to buffering.
22
+ ENV PYTHONUNBUFFERED=1
23
+
24
+ WORKDIR /app
25
+ # Copy the source code into the container.
26
+ COPY . .
27
+
28
+ # Create a non-privileged user that the app will run under.
29
+ # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user
30
+ # Switch to the non-privileged user to run the application.
31
+
32
+ # Run the Python script to generate the FAISS index and save the model.
33
+ RUN python create_faiss_index.py
34
+
35
+ USER 1001
36
+
37
+ ENTRYPOINT [ "rasa" ]
38
+
39
+ # Expose the port that the application listens on.
40
+ EXPOSE 7860
41
+
42
+ # Get secret openai and mount it
43
+ RUN --mount=type=secret,id=openai,mode=0444,required=true
44
+
45
+ # To specify model path
46
+ CMD ["run","actions","--port","7860"]
47
+
48
+ #CMD ["python", "actions/actions_llm.py"]
49
+
README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: pvanand/RASA_Omdena_demo_model_feature_followup
3
+ emoji: 🏆
4
+ colorFrom: yellow
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ duplicated_from: pvanand/RASA_Omdena_demo_model_feature_followup_actions_server
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
actions/__init__.py ADDED
File without changes
actions/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (181 Bytes). View file
 
actions/__pycache__/actions.cpython-310.pyc ADDED
Binary file (180 Bytes). View file
 
actions/actions.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This files contains your custom actions which can be used to run
2
+ # custom Python code.
3
+ #
4
+ # See this guide on how to implement these action:
5
+ # https://rasa.com/docs/rasa/custom-actions
6
+
7
+ from typing import Any, Text, Dict, List
8
+ from rasa_sdk import Action, Tracker
9
+ from rasa_sdk.events import SlotSet, FollowupAction
10
+ from rasa_sdk.executor import CollectingDispatcher
11
+ import random
12
+ import os
13
+ import sys
14
+ import openai
15
+
16
+ # Add "/app/actions" to the sys.path
17
+ actions_path = os.path.abspath("/app/actions")
18
+ sys.path.insert(0, actions_path)
19
+
20
+ print("-#-System-path-#-")
21
+ for path in sys.path:
22
+ print(path)
23
+ print("-#-END-OF-System-path-#-")
24
+ # Import search_content.py from /actions folder
25
+ from search_content import main_search
26
+
27
+
28
+ # Import api key from secrets
29
+ secret_value_0 = os.environ.get("openai")
30
+
31
+ openai.api_key = secret_value_0
32
+ # Provide your OpenAI API key
33
+
34
+ def generate_openai_response(query, model_engine="text-davinci-002", max_tokens=124, temperature=0.8):
35
+ """Generate a response using the OpenAI API."""
36
+
37
+ # Run the main function from search_content.py and store the results in a variable
38
+ results = main_search(query)
39
+
40
+ # Create context from the results
41
+ context = "".join([f"#{str(i)}" for i in results])[:2014] # Trim the context to 2014 characters - Modify as necessory
42
+ prompt_template = f"Relevant context: {context}\n\n Answer the question in detail: {query}"
43
+
44
+ # Generate a response using the OpenAI API
45
+ response = openai.Completion.create(
46
+ engine=model_engine,
47
+ prompt=prompt_template,
48
+ max_tokens=max_tokens,
49
+ temperature=temperature,
50
+ n=1,
51
+ stop=None,
52
+ )
53
+
54
+ return response.choices[0].text.strip()
55
+
56
+ class GetOpenAIResponse(Action):
57
+
58
+ def name(self) -> Text:
59
+ return "action_get_response_openai"
60
+
61
+ def run(self,
62
+ dispatcher: CollectingDispatcher,
63
+ tracker: Tracker,
64
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
65
+
66
+ # Use OpenAI API to generate a response
67
+ query = tracker.latest_message.get('text')
68
+ response = generate_openai_response(query)
69
+
70
+ # Output the generated response to user
71
+ dispatcher.utter_message(text=response)
72
+
73
+ class GeneralHelp(Action):
74
+ def name(self) -> Text:
75
+ return "action_general_help"
76
+
77
+ def run(self, dispatcher: CollectingDispatcher,
78
+ tracker: Tracker,
79
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
80
+
81
+ user_role = tracker.slots.get("user_role", None)
82
+
83
+ if user_role is None:
84
+ dispatcher.utter_message(text="Sure! Are you a developer or a client representing an organization?")
85
+ else:
86
+ return [FollowupAction("action_help_with_role")]
87
+
88
+ # Modified from @Rohit Garg's code https://github.com/rohitkg83/Omdena/blob/master/actions/actions.py
89
+ class ActionHelpWithRole(Action):
90
+
91
+ def name(self) -> Text:
92
+ return "action_help_with_role"
93
+
94
+ def run(self,
95
+ dispatcher: CollectingDispatcher,
96
+ tracker: Tracker,
97
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
98
+
99
+ # Get the value of the first_occurrence_user_type slot
100
+ current_user_type = tracker.slots.get("user_role", None)
101
+
102
+ if current_user_type == 'developer':
103
+ msg = "Thanks a lot for providing the details. You can join one of our local chapter and collaborate on " \
104
+ "various projects and challenges to Develop Your Skills, Get Recognized, and Make an Impact. Please " \
105
+ "visit https://omdena.com/community for more details. Do you have any other questions? "
106
+
107
+ elif current_user_type == 'client':
108
+ msg = "Thanks a lot for providing the details. With us you can Innovate, Deploy and Scale " \
109
+ "AI Solutions in Record Time. For more details please visit https://omdena.com/offerings. Do you have any other questions? "
110
+ else:
111
+ msg = "Please enter either developer or client"
112
+
113
+ dispatcher.utter_message(text=msg)
114
+
115
+ class ResetSlotsAction(Action):
116
+ def name(self) -> Text:
117
+ return "action_reset_slots"
118
+
119
+ def run(self, dispatcher: CollectingDispatcher,
120
+ tracker: Tracker,
121
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
122
+ slots_to_reset = ["user_role"] # Add the names of the slots you want to reset
123
+ events = [SlotSet(slot, None) for slot in slots_to_reset]
124
+ return events
125
+
126
+ class ActionJoinClassify(Action):
127
+
128
+ def name(self) -> Text:
129
+ return "action_join_classify"
130
+
131
+ def run(self,
132
+ dispatcher: CollectingDispatcher,
133
+ tracker: Tracker,
134
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
135
+
136
+ # Get the value of the latest intent
137
+ last_intent = tracker.slots.get("local_chapter", None)
138
+
139
+ # Check if the last intent was 'local_chapter'
140
+ if last_intent == 'local chapter':
141
+ dispatcher.utter_message(template="utter_join_chapter")
142
+ else:
143
+ return [FollowupAction("action_get_response_openai")]
144
+
145
+
146
+
147
+ class ActionEligibilityClassify(Action):
148
+
149
+ def name(self) -> Text:
150
+ return "action_eligibility_classify"
151
+
152
+ def run(self,
153
+ dispatcher: CollectingDispatcher,
154
+ tracker: Tracker,
155
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
156
+
157
+ # Get the value of the latest intent
158
+ last_intent = tracker.slots.get("local_chapter", None)
159
+
160
+ # Check if the last intent was 'local_chapter'
161
+ if last_intent == 'local chapter':
162
+ dispatcher.utter_message(template="utter_local_chapter_participation_eligibility")
163
+ else:
164
+ return [FollowupAction("action_get_response_openai")]
165
+
166
+
167
+ class ActionCostClassify(Action):
168
+
169
+ def name(self) -> Text:
170
+ return "action_cost_classify"
171
+
172
+ def run(self,
173
+ dispatcher: CollectingDispatcher,
174
+ tracker: Tracker,
175
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
176
+
177
+ # Get the value of the latest intent
178
+ last_intent = tracker.slots.get("local_chapter", None)
179
+
180
+ # Check if the last intent was 'local_chapter'
181
+ if last_intent == 'local chapter':
182
+ dispatcher.utter_message(template="utter_local_chapter_cost")
183
+ else:
184
+ return [FollowupAction("action_get_response_openai")]
185
+
186
+ class SayHelloWorld(Action):
187
+
188
+ def name(self) -> Text:
189
+ return "action_hello_world"
190
+
191
+ def run(self,
192
+ dispatcher: CollectingDispatcher,
193
+ tracker: Tracker,
194
+ domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
195
+
196
+ # Use OpenAI API to generate a response
197
+ secret_value_0 = os.environ.get("openai")
198
+ openai.api_key = secret_value_0
199
+ model_engine = "text-davinci-002"
200
+ prompt_template = "Say hello world"
201
+
202
+ response = openai.Completion.create(
203
+ engine=model_engine,
204
+ prompt=prompt_template,
205
+ max_tokens=124,
206
+ temperature=0.8,
207
+ n=1,
208
+ stop=None,
209
+ )
210
+
211
+ # Output the generated response to user
212
+ generated_text = response.choices[0].text
213
+ dispatcher.utter_message(text=generated_text)
actions/actions_llm.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # run_search.py
2
+ import os
3
+ import sys
4
+ import openai
5
+
6
+ # Add "/actions" to the sys.path
7
+ actions_path = os.path.abspath("/actions")
8
+ sys.path.insert(0, actions_path)
9
+
10
+ # Import search_content.py from /actions folder
11
+ from search_content import main_search
12
+
13
+
14
+ # Import api key from secrets
15
+ secret_value_0 = os.environ.get("openai")
16
+
17
+ openai.api_key = secret_value_0
18
+ # Provide your OpenAI API key
19
+
20
+ def generate_openai_response(query, model_engine="text-davinci-002", max_tokens=124, temperature=0.8):
21
+ """Generate a response using the OpenAI API."""
22
+ # Run the main function from search_content.py and store the results in a variable
23
+ results = main_search(query)
24
+
25
+ # Create context from the results
26
+ context = "".join([f"#{str(i)}" for i in results])[:2014] # Trim the context to 2014 characters - Modify as necessory
27
+ prompt_template = f"Relevant context: {context}\n\n Answer the question in detail: {query}"
28
+
29
+ # Generate a response using the OpenAI API
30
+ response = openai.Completion.create(
31
+ engine=model_engine,
32
+ prompt=prompt_template,
33
+ max_tokens=max_tokens,
34
+ temperature=temperature,
35
+ n=1,
36
+ stop=None,
37
+ )
38
+
39
+ return response.choices[0].text.strip()
40
+
41
+ def main():
42
+ query = "What is omdena local chapters, how a developer can benifit from it"
43
+ response = generate_openai_response(query)
44
+ print(response)
45
+
46
+ if __name__ == "__main__":
47
+ main()
actions/search_content.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # search_content.py
2
+
3
+ import faiss
4
+ import pandas as pd
5
+ from sentence_transformers import SentenceTransformer
6
+
7
+ # Define paths for model, Faiss index, and data file
8
+ MODEL_SAVE_PATH = "all-distilroberta-v1-model.pkl"
9
+ FAISS_INDEX_FILE_PATH = "index.faiss"
10
+ DATA_FILE_PATH = "omdena_qna_dataset/omdena_faq_training_data.csv"
11
+
12
+ def load_transformer_model(model_file):
13
+ """Load a sentence transformer model from a file."""
14
+ return SentenceTransformer.load(model_file)
15
+
16
+ def load_faiss_index(filename):
17
+ """Load a Faiss index from a file."""
18
+ return faiss.read_index(filename)
19
+
20
+ def load_data(file_path):
21
+ """Load data from a CSV file and preprocess it."""
22
+ data_frame = pd.read_csv(file_path)
23
+ data_frame["id"] = data_frame.index
24
+
25
+ # Create a 'QNA' column that combines 'Questions' and 'Answers'
26
+ data_frame['QNA'] = data_frame.apply(lambda row: f"Question: {row['Questions']}, Answer: {row['Answers']}", axis=1)
27
+ return data_frame.set_index(["id"], drop=False)
28
+
29
+ def search_content(query, data_frame_indexed, transformer_model, faiss_index, k=5):
30
+ """Search the content using a query and return the top k results."""
31
+ # Encode the query using the model
32
+ query_vector = transformer_model.encode([query])
33
+
34
+ # Normalize the query vector
35
+ faiss.normalize_L2(query_vector)
36
+
37
+ # Search the Faiss index using the query vector
38
+ top_k = faiss_index.search(query_vector, k)
39
+
40
+ # Extract the IDs and similarities of the top k results
41
+ ids = top_k[1][0].tolist()
42
+ similarities = top_k[0][0].tolist()
43
+
44
+ # Get the corresponding results from the data frame
45
+ results = data_frame_indexed.loc[ids]
46
+
47
+ # Add a column for the similarities
48
+ results["similarities"] = similarities
49
+ return results
50
+
51
+ def main_search(query):
52
+ """Main function to execute the search."""
53
+ transformer_model = load_transformer_model(MODEL_SAVE_PATH)
54
+ faiss_index = load_faiss_index(FAISS_INDEX_FILE_PATH)
55
+ data_frame_indexed = load_data(DATA_FILE_PATH)
56
+ results = search_content(query, data_frame_indexed, transformer_model, faiss_index)
57
+ return results['Answers'] # return the 'Answers' column
58
+
59
+ if __name__ == "__main__":
60
+ query = "school courses"
61
+ print(main_search(query)) # print the results if this script is run directly
app.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import openai
3
+
4
+ secret_value_0 = os.environ.get("openai")
5
+
6
+ openai.api_key = secret_value_0
7
+
8
+ model_engine = "text-davinci-002"
9
+ prompt_template = "Say hello world" #prompt_template
10
+
11
+ response = openai.Completion.create(
12
+ engine=model_engine,
13
+ prompt=prompt_template,
14
+ max_tokens=124,
15
+ temperature=0.8,
16
+ n=1,
17
+ stop=None,
18
+ )
19
+
20
+ print(response.choices[0].text)
compose.yaml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Comments are provided throughout this file to help you get started.
2
+ # If you need more help, visit the Docker compose reference guide at
3
+ # https://docs.docker.com/compose/compose-file/
4
+
5
+ # Here the instructions define your application as a service called "server".
6
+ # This service is built from the Dockerfile in the current directory.
7
+ # You can add other services your application may depend on here, such as a
8
+ # database or a cache. For examples, see the Awesome Compose repository:
9
+ # https://github.com/docker/awesome-compose
10
+ services:
11
+ server:
12
+ build:
13
+ context: .
14
+ ports:
15
+ - 7860:7860
16
+
17
+ # The commented out section below is an example of how to define a PostgreSQL
18
+ # database that your application can use. `depends_on` tells Docker Compose to
19
+ # start the database before your application. The `db-data` volume persists the
20
+ # database data between container restarts. The `db-password` secret is used
21
+ # to set the database password. You must create `db/password.txt` and add
22
+ # a password of your choosing to it before running `docker compose up`.
23
+ # depends_on:
24
+ # db:
25
+ # condition: service_healthy
26
+ # db:
27
+ # image: postgres
28
+ # restart: always
29
+ # user: postgres
30
+ # secrets:
31
+ # - db-password
32
+ # volumes:
33
+ # - db-data:/var/lib/postgresql/data
34
+ # environment:
35
+ # - POSTGRES_DB=example
36
+ # - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
37
+ # expose:
38
+ # - 5432
39
+ # healthcheck:
40
+ # test: [ "CMD", "pg_isready" ]
41
+ # interval: 10s
42
+ # timeout: 5s
43
+ # retries: 5
44
+ # volumes:
45
+ # db-data:
46
+ # secrets:
47
+ # db-password:
48
+ # file: db/password.txt
49
+
config.yml ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # The config recipe.
2
+ # https://rasa.com/docs/rasa/model-configuration/
3
+ recipe: default.v1
4
+
5
+ # The assistant project unique identifier
6
+ # This default value must be replaced with a unique assistant name within your deployment
7
+ assistant_id: placeholder_default
8
+
9
+ # Configuration for Rasa NLU.
10
+ # https://rasa.com/docs/rasa/nlu/components/
11
+ language: en
12
+
13
+ pipeline:
14
+ # # No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model.
15
+ # # If you'd like to customize it, uncomment and adjust the pipeline.
16
+ # # See https://rasa.com/docs/rasa/tuning-your-model for more information.
17
+ # - name: WhitespaceTokenizer
18
+ # - name: RegexFeaturizer
19
+ # - name: LexicalSyntacticFeaturizer
20
+ # - name: CountVectorsFeaturizer
21
+ # - name: CountVectorsFeaturizer
22
+ # analyzer: char_wb
23
+ # min_ngram: 1
24
+ # max_ngram: 4
25
+ # - name: DIETClassifier
26
+ # epochs: 100
27
+ # constrain_similarities: true
28
+ # - name: EntitySynonymMapper
29
+ # - name: ResponseSelector
30
+ # epochs: 100
31
+ # constrain_similarities: true
32
+ # - name: FallbackClassifier
33
+ # threshold: 0.3
34
+ # ambiguity_threshold: 0.1
35
+
36
+ # Configuration for Rasa Core.
37
+ # https://rasa.com/docs/rasa/core/policies/
38
+ policies:
39
+ # # No configuration for policies was provided. The following default policies were used to train your model.
40
+ # # If you'd like to customize them, uncomment and adjust the policies.
41
+ # # See https://rasa.com/docs/rasa/policies for more information.
42
+ # - name: MemoizationPolicy
43
+ # - name: RulePolicy
44
+ # - name: UnexpecTEDIntentPolicy
45
+ # max_history: 5
46
+ # epochs: 100
47
+ # - name: TEDPolicy
48
+ # max_history: 5
49
+ # epochs: 100
50
+ # constrain_similarities: true
create_faiss_index.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """create_faiss_index.py
3
+ """
4
+
5
+ import pandas as pd
6
+ import numpy as np
7
+ import faiss
8
+ from sentence_transformers import InputExample, SentenceTransformer
9
+
10
+ DATA_FILE_PATH = "omdena_qna_dataset/omdena_faq_training_data.csv"
11
+ TRANSFORMER_MODEL_NAME = "all-distilroberta-v1"
12
+ CACHE_DIR_PATH = "../working/cache/"
13
+ MODEL_SAVE_PATH = "all-distilroberta-v1-model.pkl"
14
+ FAISS_INDEX_FILE_PATH = "index.faiss"
15
+
16
+ def load_data(file_path):
17
+ qna_dataset = pd.read_csv(file_path)
18
+ qna_dataset["id"] = qna_dataset.index
19
+ return qna_dataset.dropna(subset=['Answers']).copy()
20
+
21
+ def create_input_examples(qna_dataset):
22
+ qna_dataset['QNA'] = qna_dataset.apply(lambda row: f"Question: {row['Questions']}, Answer: {row['Answers']}", axis=1)
23
+ return qna_dataset.apply(lambda x: InputExample(texts=[x["QNA"]]), axis=1).tolist()
24
+
25
+ def load_transformer_model(model_name, cache_folder):
26
+ transformer_model = SentenceTransformer(model_name, cache_folder=cache_folder)
27
+ return transformer_model
28
+
29
+ def save_transformer_model(transformer_model, model_file):
30
+ transformer_model.save(model_file)
31
+
32
+ def create_faiss_index(transformer_model, qna_dataset):
33
+ faiss_embeddings = transformer_model.encode(qna_dataset.Answers.values.tolist())
34
+ qna_dataset_indexed = qna_dataset.set_index(["id"], drop=False)
35
+ id_index_array = np.array(qna_dataset_indexed.id.values).flatten().astype("int")
36
+ normalized_embeddings = faiss_embeddings.copy()
37
+ faiss.normalize_L2(normalized_embeddings)
38
+ faiss_index = faiss.IndexIDMap(faiss.IndexFlatIP(len(faiss_embeddings[0])))
39
+ faiss_index.add_with_ids(normalized_embeddings, id_index_array)
40
+ return faiss_index
41
+
42
+ def save_faiss_index(faiss_index, filename):
43
+ faiss.write_index(faiss_index, filename)
44
+
45
+ def load_faiss_index(filename):
46
+ return faiss.read_index(filename)
47
+
48
+ def main():
49
+ qna_dataset = load_data(DATA_FILE_PATH)
50
+ input_examples = create_input_examples(qna_dataset)
51
+ transformer_model = load_transformer_model(TRANSFORMER_MODEL_NAME, CACHE_DIR_PATH)
52
+ save_transformer_model(transformer_model, MODEL_SAVE_PATH)
53
+ faiss_index = create_faiss_index(transformer_model, qna_dataset)
54
+ save_faiss_index(faiss_index, FAISS_INDEX_FILE_PATH)
55
+ faiss_index = load_faiss_index(FAISS_INDEX_FILE_PATH)
56
+
57
+ if __name__ == "__main__":
58
+ main()
credentials.yml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file contains the credentials for the voice & chat platforms
2
+ # which your bot is using.
3
+ # https://rasa.com/docs/rasa/messaging-and-voice-channels
4
+
5
+ rest:
6
+ # # you don't need to provide anything here - this channel doesn't
7
+ # # require any credentials
8
+
9
+
10
+ #facebook:
11
+ # verify: "<verify>"
12
+ # secret: "<your secret>"
13
+ # page-access-token: "<your page access token>"
14
+
15
+ #slack:
16
+ # slack_token: "<your slack token>"
17
+ # slack_channel: "<the slack channel>"
18
+ # slack_signing_secret: "<your slack signing secret>"
19
+
20
+ socketio:
21
+ user_message_evt: user_uttered
22
+ bot_message_evt: bot_uttered
23
+ session_persistence: true
24
+
25
+ #mattermost:
26
+ # url: "https://<mattermost instance>/api/v4"
27
+ # token: "<bot token>"
28
+ # webhook_url: "<callback URL>"
29
+
30
+ # This entry is needed if you are using Rasa Enterprise. The entry represents credentials
31
+ # for the Rasa Enterprise "channel", i.e. Talk to your bot and Share with guest testers.
32
+ rasa:
33
+ url: "http://localhost:5002/api"
data/nlu.yml ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ nlu:
4
+ - intent: greet
5
+ examples: |
6
+ - hey
7
+ - hello
8
+ - hi
9
+ - hello there
10
+ - good morning
11
+ - good evening
12
+ - moin
13
+ - hey there
14
+ - let's go
15
+ - hey dude
16
+ - goodmorning
17
+ - goodevening
18
+ - good afternoon
19
+
20
+ - intent: goodbye
21
+ examples: |
22
+ - cu
23
+ - good by
24
+ - cee you later
25
+ - good night
26
+ - bye
27
+ - goodbye
28
+ - have a nice day
29
+ - see you around
30
+ - bye bye
31
+ - see you later
32
+
33
+ - intent: affirm
34
+ examples: |
35
+ - yes
36
+ - y
37
+ - indeed
38
+ - of course
39
+ - that sounds good
40
+ - correct
41
+
42
+ - intent: deny
43
+ examples: |
44
+ - no
45
+ - n
46
+ - never
47
+ - I don't think so
48
+ - don't like that
49
+ - no way
50
+ - not really
51
+
52
+ - intent: mood_great
53
+ examples: |
54
+ - perfect
55
+ - great
56
+ - amazing
57
+ - feeling like a king
58
+ - wonderful
59
+ - I am feeling very good
60
+ - I am great
61
+ - I am amazing
62
+ - I am going to save the world
63
+ - super stoked
64
+ - extremely good
65
+ - so so perfect
66
+ - so good
67
+ - so perfect
68
+
69
+ - intent: mood_unhappy
70
+ examples: |
71
+ - my day was horrible
72
+ - I am sad
73
+ - I don't feel very well
74
+ - I am disappointed
75
+ - super sad
76
+ - I'm so sad
77
+ - sad
78
+ - very sad
79
+ - unhappy
80
+ - not good
81
+ - not very good
82
+ - extremly sad
83
+ - so saad
84
+ - so sad
85
+
86
+ - intent: bot_challenge
87
+ examples: |
88
+ - are you a bot?
89
+ - are you a human?
90
+ - am I talking to a bot?
91
+ - am I talking to a human?
data/rules.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ rules:
4
+
5
+ - rule: Say goodbye anytime the user says goodbye
6
+ steps:
7
+ - intent: goodbye
8
+ - action: utter_goodbye
9
+
10
+ - rule: Say 'I am a bot' anytime the user challenges
11
+ steps:
12
+ - intent: bot_challenge
13
+ - action: utter_iamabot
data/stories.yml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ stories:
4
+
5
+ - story: happy path
6
+ steps:
7
+ - intent: greet
8
+ - action: utter_greet
9
+ - intent: mood_great
10
+ - action: utter_happy
11
+
12
+ - story: sad path 1
13
+ steps:
14
+ - intent: greet
15
+ - action: utter_greet
16
+ - intent: mood_unhappy
17
+ - action: utter_cheer_up
18
+ - action: utter_did_that_help
19
+ - intent: affirm
20
+ - action: utter_happy
21
+
22
+ - story: sad path 2
23
+ steps:
24
+ - intent: greet
25
+ - action: utter_greet
26
+ - intent: mood_unhappy
27
+ - action: utter_cheer_up
28
+ - action: utter_did_that_help
29
+ - intent: deny
30
+ - action: utter_goodbye
domain.yml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.1"
2
+
3
+ intents:
4
+ - greet
5
+ - goodbye
6
+ - affirm
7
+ - deny
8
+ - mood_great
9
+ - mood_unhappy
10
+ - bot_challenge
11
+
12
+ responses:
13
+ utter_greet:
14
+ - text: "Hey! How are you?"
15
+
16
+ utter_cheer_up:
17
+ - text: "Here is something to cheer you up:"
18
+ image: "https://i.imgur.com/nGF1K8f.jpg"
19
+
20
+ utter_did_that_help:
21
+ - text: "Did that help you?"
22
+
23
+ utter_happy:
24
+ - text: "Great, carry on!"
25
+
26
+ utter_goodbye:
27
+ - text: "Bye"
28
+
29
+ utter_iamabot:
30
+ - text: "I am a bot, powered by Rasa."
31
+
32
+ session_config:
33
+ session_expiration_time: 60
34
+ carry_over_slots_to_new_session: true
endpoints.yml ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file contains the different endpoints your bot can use.
2
+
3
+ # Server where the models are pulled from.
4
+ # https://rasa.com/docs/rasa/model-storage#fetching-models-from-a-server
5
+
6
+ #models:
7
+ # url: http://my-server.com/models/default_core@latest
8
+ # wait_time_between_pulls: 10 # [optional](default: 100)
9
+
10
+ # Server which runs your custom actions.
11
+ # https://rasa.com/docs/rasa/custom-actions
12
+
13
+ action_endpoint:
14
+ url: "http://localhost:7860/webhook"
15
+
16
+ # Tracker store which is used to store the conversations.
17
+ # By default the conversations are stored in memory.
18
+ # https://rasa.com/docs/rasa/tracker-stores
19
+
20
+ #tracker_store:
21
+ # type: redis
22
+ # url: <host of the redis instance, e.g. localhost>
23
+ # port: <port of your redis instance, usually 6379>
24
+ # db: <number of your database within redis, e.g. 0>
25
+ # password: <password used for authentication>
26
+ # use_ssl: <whether or not the communication is encrypted, default false>
27
+
28
+ #tracker_store:
29
+ # type: mongod
30
+ # url: <url to your mongo instance, e.g. mongodb://localhost:27017>
31
+ # db: <name of the db within your mongo instance, e.g. rasa>
32
+ # username: <username used for authentication>
33
+ # password: <password used for authentication>
34
+
35
+ # Event broker which all conversation events should be streamed to.
36
+ # https://rasa.com/docs/rasa/event-brokers
37
+
38
+ #event_broker:
39
+ # url: localhost
40
+ # username: username
41
+ # password: password
42
+ # queue: queue
omdena_qna_dataset/omdena_faq_training_data.csv ADDED
The diff for this file is too large to render. See raw diff
 
readme.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ API DEBUG COLAB
2
+ https://colab.research.google.com/drive/1iDJmwVHloe65ajywejV4PDwGY3D6rIFX?usp=sharing
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ rasa
2
+ transformers==4.11.0
3
+ datasets
4
+ torch
5
+ numpy
6
+ pandas
7
+ openai
8
+ faiss-cpu==1.7.4
9
+ sentence_transformers