code: import os
  import glob
  import llama_index
  from llama_index.core import ServiceContext
  from llama_index.llms.anthropic import Anthropic
  from llama_index.core import SimpleDirectoryReader
  from llama_index.core.response_synthesizers import TreeSummarize
  
  # MODEL = "claude-3-opus-20240229"
  # MODEL = "claude-3-sonnet-20240229"
  MODEL = "claude-3-haiku-20240307"
  
  DATA_DIR = "data"
  SUMMARY_ROOT = "summaries"
  SUMMARY_DIR = os.path.join(SUMMARY_ROOT, MODEL).replace(":", "_")
  
  os.makedirs(SUMMARY_DIR, exist_ok=True)
  
  def saveText(path, text):
      "Save the given text to a file at the specified path."
      with open(path, "w") as f:
          f.write(text)
  
  def commentPaths(ticketNumber):
      "Returns a sorted list of file paths for the comments in Zendesk ticket `ticketNumber`."
      ticketDir = os.path.join(DATA_DIR, ticketNumber)
      return sorted(glob.glob(os.path.join(ticketDir, "*.txt")))
  
  def summaryPath(ticketNumber):
      "Returns the file path for where we store the summary of Zendesk ticket `ticketNumber`."
      return os.path.join(SUMMARY_DIR, f"{ticketNumber}.txt")
  
  def totalSizeKB(paths):
      "Returns the total size in kilobytes of the files specified by `paths`."
      return sum(os.path.getsize(path) for path in paths) / 1024
  
  def currentTime():
      "Returns the current time in the format 'dd/mm/YYYY HH:MM:SS'."
      from datetime import datetime
      now = datetime.now()
      return now.strftime("%d/%m/%Y %H:%M:%S")
  
  llm = Anthropic(model=MODEL, max_tokens=1024)
  service_context = ServiceContext.from_defaults(llm=llm, embed_model="local")
  summarizer = TreeSummarize(service_context=service_context, verbose=False)
  
  SUMMARY_PROMPT = "The following text is a series of messages from a PaperCut support ticket. Summarise the whole conversation, including a list of particpants and who they work for, the problem or problems, the key events and date they occurred, and the current status of the ticket. Include any log lines from the messages."
  
  def summariseTicket(ticketNumber):
      "Summarizes the Zendesk ticket with the given `ticketNumber` and returns the summary text."
      input_files = commentPaths(ticketNumber)
      reader = SimpleDirectoryReader(input_files=input_files)
      docs = reader.load_data()
      texts = [doc.text for doc in docs]
      return summarizer.get_response(SUMMARY_PROMPT, texts)
  
  if __name__ == "__main__":
      import time
      print(f"MODEL={MODEL}")
      ticketNumbers = sorted(os.path.basename(path) for path in glob.glob(os.path.join(DATA_DIR, "*")))
      ticketNumbers.sort(key=lambda k: (totalSizeKB(commentPaths(k)), k))
      print(ticketNumbers)
      for i, ticketNumber in enumerate(ticketNumbers):
          paths = commentPaths(ticketNumber)
          print(f"{i:4}: {ticketNumber:8} {len(paths):3} comments {totalSizeKB(paths):7.3f} kb")
  
      t00 = time.time()
      summaries = {}
      durations = {}
      commentCounts = {}
      commentSizes = {}
      for i, ticketNumber in enumerate(ticketNumbers):
          commentCount = len(commentPaths(ticketNumber))
          commentSize = totalSizeKB(commentPaths(ticketNumber))
  
          print(f"{i:2}: ticketNumber={ticketNumber:8} {commentCount:3} comments {commentSize:7.3f} kb {currentTime()}",
              flush=True)
  
          if os.path.exists(summaryPath(ticketNumber)):
              print(f"Skipping ticket {ticketNumber}", flush=True)
              continue   # Skip tickets that have already been summarised.
  
          t0 = time.time()
          summary = summariseTicket(ticketNumber)
          duration = time.time() - t0
          description = f"{commentCount} comments {commentSize:7.3f} kb {duration:5.2f} sec summary={len(summary)}"
  
          print(f"  {description}", flush=True)
  
          with open(summaryPath(ticketNumber), "w") as f:
              print(f"Summary: ticket {ticketNumber}: {description} -------------------------", file=f)
              print(summary, file=f)
  
          summaries[ticketNumber] = summary
          durations[ticketNumber] = duration
          commentCounts[ticketNumber] = commentCount
          commentSizes[ticketNumber] = commentSize
  
      duration = time.time() - t00
      print("====================^^^====================")
      print(f"Duration: {duration:.2f} seconds")
      for i, ticketNumber in enumerate(ticketNumbers):
          commentCount = commentCounts[ticketNumber]
          commentSize = totalSizeKB(commentPaths(ticketNumber))
          duration = durations[ticketNumber]
          print(f"{i:2}: {ticketNumber:8}: {commentCount:3} comments {commentSize:7.3f} kb {duration:5.2f} seconds")
  
apis: llama_index.llms.anthropic.Anthropic llama_index.core.response_synthesizers.TreeSummarize llama_index.core.SimpleDirectoryReader llama_index.core.ServiceContext.from_defaults
extract_api: [((470, 509), 'os.makedirs', 'os.makedirs', (['SUMMARY_DIR'], {'exist_ok': '(True)'}), '(SUMMARY_DIR, exist_ok=True)\n', (481, 509), False, 'import os\n'), ((1440, 1479), 'llama_index.llms.anthropic.Anthropic', 'Anthropic', ([], {'model': 'MODEL', 'max_tokens': '(1024)'}), '(model=MODEL, max_tokens=1024)\n', (1449, 1479), False, 'from llama_index.llms.anthropic import Anthropic\n'), ((1498, 1556), 'llama_index.core.ServiceContext.from_defaults', 'ServiceContext.from_defaults', ([], {'llm': 'llm', 'embed_model': '"""local"""'}), "(llm=llm, embed_model='local')\n", (1526, 1556), False, 'from llama_index.core import ServiceContext\n'), ((1570, 1631), 'llama_index.core.response_synthesizers.TreeSummarize', 'TreeSummarize', ([], {'service_context': 'service_context', 'verbose': '(False)'}), '(service_context=service_context, verbose=False)\n', (1583, 1631), False, 'from llama_index.core.response_synthesizers import TreeSummarize\n'), ((791, 827), 'os.path.join', 'os.path.join', (['DATA_DIR', 'ticketNumber'], {}), '(DATA_DIR, ticketNumber)\n', (803, 827), False, 'import os\n'), ((1027, 1075), 'os.path.join', 'os.path.join', (['SUMMARY_DIR', 'f"""{ticketNumber}.txt"""'], {}), "(SUMMARY_DIR, f'{ticketNumber}.txt')\n", (1039, 1075), False, 'import os\n'), ((1373, 1387), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (1385, 1387), False, 'from datetime import datetime\n'), ((2149, 2195), 'llama_index.core.SimpleDirectoryReader', 'SimpleDirectoryReader', ([], {'input_files': 'input_files'}), '(input_files=input_files)\n', (2170, 2195), False, 'from llama_index.core import SimpleDirectoryReader\n'), ((2796, 2807), 'time.time', 'time.time', ([], {}), '()\n', (2805, 2807), False, 'import time\n'), ((417, 450), 'os.path.join', 'os.path.join', (['SUMMARY_ROOT', 'MODEL'], {}), '(SUMMARY_ROOT, MODEL)\n', (429, 450), False, 'import os\n'), ((3412, 3423), 'time.time', 'time.time', ([], {}), '()\n', (3421, 3423), False, 'import time\n'), ((4065, 4076), 'time.time', 'time.time', ([], {}), '()\n', (4074, 4076), False, 'import time\n'), ((856, 888), 'os.path.join', 'os.path.join', (['ticketDir', '"""*.txt"""'], {}), "(ticketDir, '*.txt')\n", (868, 888), False, 'import os\n'), ((2422, 2444), 'os.path.basename', 'os.path.basename', (['path'], {}), '(path)\n', (2438, 2444), False, 'import os\n'), ((3491, 3502), 'time.time', 'time.time', ([], {}), '()\n', (3500, 3502), False, 'import time\n'), ((1193, 1214), 'os.path.getsize', 'os.path.getsize', (['path'], {}), '(path)\n', (1208, 1214), False, 'import os\n'), ((2467, 2494), 'os.path.join', 'os.path.join', (['DATA_DIR', '"""*"""'], {}), "(DATA_DIR, '*')\n", (2479, 2494), False, 'import os\n')]