main.py 6.0 KB

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