main.py 5.7 KB

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