main.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import json
  2. import os
  3. import sys
  4. import logging
  5. from datetime import datetime, timedelta
  6. from io import BytesIO
  7. from django.utils.text import slugify
  8. from django.conf import settings
  9. import openai
  10. from llama_index import VectorStoreIndex, Document, StorageContext, load_index_from_storage
  11. from llama_index.prompts import Prompt
  12. from langchain.prompts.chat import (ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate)
  13. from adm.constants import CTS
  14. from adm.storage import MediaStorage
  15. from adm.services import ParameterService
  16. logger = logging.getLogger('dsp')
  17. class Chatbot():
  18. def __init__(self) -> None:
  19. objParameter = ParameterService()
  20. openai.api_key = objParameter.getParameterByKey("OPENAI_API_KEY").value
  21. self.storage_path = CTS.CHATBOT_STORAGE_PATH
  22. media_storage = MediaStorage(self.storage_path)
  23. self.media_storage = media_storage
  24. # load index
  25. self.ai_storage_context = None
  26. self.ai_index = None
  27. base_dir = settings.BASE_DIR + '/storage'
  28. try:
  29. self.ai_storage_context = StorageContext.from_defaults(persist_dir=base_dir)
  30. self.ai_index = load_index_from_storage(self.ai_storage_context)
  31. except BaseException as error:
  32. # exc_type, exc_obj, exc_tb = sys.exc_info()
  33. # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
  34. # strErro = "ERRO: %s | %s | %s | %s" % (error, exc_type, fname, exc_tb.tb_lineno)
  35. logger.info('Chatbot() init: '+str(error))
  36. pass
  37. pass
  38. def train (self, chat=None):
  39. status = 400
  40. data = None
  41. logger.info('Chatbot Training started | Chat ? '+str(chat))
  42. docs = []
  43. if chat:
  44. # use chat to build up on existing store
  45. # save chat as doc in storage
  46. if not 'id' in chat:
  47. question = chat['chat'][0].split(':')[-1]
  48. chat['id'] = slugify(question)
  49. if not 'type' in chat:
  50. chat['type'] = 'instructions'
  51. if not 'category' in chat:
  52. chat['category'] = 'uncategorized'
  53. blob_name = chat['id']
  54. blob_ext = '.json'
  55. file_name = blob_name + blob_ext
  56. blob_dir = 'instructions/'
  57. blob_path = blob_dir + file_name
  58. text = json.dumps(chat, ensure_ascii=False)
  59. path_bucket = os.path.join(self.media_storage.location, self.storage_path, '/', blob_path)
  60. self.media_storage.save(path_bucket, BytesIO(text.encode("utf-8")))
  61. docs.append({
  62. 'id_': blob_name,
  63. 'text': text,
  64. 'metadata': {
  65. 'filename': file_name,
  66. 'category': chat['category']
  67. }
  68. })
  69. else:
  70. blobs = self.media_storage.list(self.storage_path + '/')
  71. for blob in blobs:
  72. text = blob.download_as_bytes().decode('utf-8')
  73. if len(text)>0:
  74. obj = json.loads(text) if text.startswith('{') else text
  75. if not 'category' in obj:
  76. obj['category'] = 'uncategorized'
  77. file_name = blob.name.split('/')[-1]
  78. docs.append({
  79. 'id_': obj['id'],
  80. 'text': text,
  81. 'metadata': {
  82. 'filename': file_name,
  83. 'category': obj['category']
  84. }
  85. })
  86. # parse documents
  87. ai_documents = []
  88. for doc in docs:
  89. ai_documents.append(Document(**doc))
  90. # create/add to index
  91. if self.ai_index is None:
  92. self.ai_index = VectorStoreIndex.from_documents(ai_documents, show_progress=True)
  93. else:
  94. for ai_doc in ai_documents:
  95. self.ai_index.insert(ai_doc)
  96. # save index to disk
  97. if ai_documents:
  98. self.ai_index.storage_context.persist()
  99. status = 200
  100. logger.info('Chatbot Training finished | Status '+str(status))
  101. return status, data
  102. def chat (self, question=None):
  103. status = 400
  104. pre_prompt = [
  105. SystemMessagePromptTemplate.from_template(
  106. "Act as an IT Support Level 1 for the company Mobees. Your name is Mel. You must answer the company's Drivers questions in Brazilian Portuguese, as they only speak this language. Mobees Drivers access support through a chatbot interface in the company's app, which is the only channel for support. If you're not sure how to answer, respond with only the following `<assignee:support>` (this will let our system know it should forward the issue to our support team and take it from there). "
  107. ),
  108. HumanMessagePromptTemplate.from_template(
  109. "Context information is below.\n"
  110. "---------------------\n"
  111. "{context_str}\n"
  112. "---------------------\n"
  113. "Given the context information and prior knowledge, "
  114. "answer the question: {query_str}\n"
  115. ),
  116. ]
  117. prompt_template = ChatPromptTemplate.from_messages(pre_prompt)
  118. text_qa_template = Prompt.from_langchain_prompt(prompt_template)
  119. answer = self.ai_index.as_query_engine(
  120. text_qa_template=text_qa_template
  121. ).query(question)
  122. print(answer)
  123. status = 200
  124. data = { 'answer': answer.response }
  125. return status, data
  126. # chat_engine = self.ai_index.as_chat_engine(
  127. # verbose=True
  128. # )
  129. # chat_engine.chat_repl()
  130. instance = Chatbot()