commons.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import datetime
  2. import json
  3. import os, re, configparser
  4. import time
  5. import boto3
  6. from loguru import logger
  7. from boto3.s3.transfer import TransferConfig
  8. from botocore.config import Config
  9. import fitz # 1.23.9中已经切换到rebase
  10. # import fitz_old as fitz # 使用1.23.9之前的pymupdf库
  11. def get_delta_time(input_time):
  12. return round(time.time() - input_time, 2)
  13. def join_path(*args):
  14. return '/'.join(str(s).rstrip('/') for s in args)
  15. #配置全局的errlog_path,方便demo同步引用
  16. error_log_path = "s3://llm-pdf-text/err_logs/"
  17. # json_dump_path = "s3://pdf_books_temp/json_dump/" # 这条路径仅用于临时本地测试,不能提交到main
  18. json_dump_path = "s3://llm-pdf-text/json_dump/"
  19. # s3_image_save_path = "s3://mllm-raw-media/pdf2md_img/" # 基础库不应该有这些存在的路径,应该在业务代码中定义
  20. def get_top_percent_list(num_list, percent):
  21. """
  22. 获取列表中前百分之多少的元素
  23. :param num_list:
  24. :param percent:
  25. :return:
  26. """
  27. if len(num_list) == 0:
  28. top_percent_list = []
  29. else:
  30. # 对imgs_len_list排序
  31. sorted_imgs_len_list = sorted(num_list, reverse=True)
  32. # 计算 percent 的索引
  33. top_percent_index = int(len(sorted_imgs_len_list) * percent)
  34. # 取前80%的元素
  35. top_percent_list = sorted_imgs_len_list[:top_percent_index]
  36. return top_percent_list
  37. def formatted_time(time_stamp):
  38. dt_object = datetime.datetime.fromtimestamp(time_stamp)
  39. output_time = dt_object.strftime("%Y-%m-%d-%H:%M:%S")
  40. return output_time
  41. def mymax(alist: list):
  42. if len(alist) == 0:
  43. return 0 # 空是0, 0*0也是0大小q
  44. else:
  45. return max(alist)
  46. def parse_aws_param(profile):
  47. if isinstance(profile, str):
  48. # 解析配置文件
  49. config_file = join_path(os.path.expanduser("~"), ".aws", "config")
  50. credentials_file = join_path(os.path.expanduser("~"), ".aws", "credentials")
  51. config = configparser.ConfigParser()
  52. config.read(credentials_file)
  53. config.read(config_file)
  54. # 获取 AWS 账户相关信息
  55. ak = config.get(profile, "aws_access_key_id")
  56. sk = config.get(profile, "aws_secret_access_key")
  57. if profile == "default":
  58. s3_str = config.get(f"{profile}", "s3")
  59. else:
  60. s3_str = config.get(f"profile {profile}", "s3")
  61. end_match = re.search("endpoint_url[\s]*=[\s]*([^\s\n]+)[\s\n]*$", s3_str, re.MULTILINE)
  62. if end_match:
  63. endpoint = end_match.group(1)
  64. else:
  65. raise ValueError(f"aws 配置文件中没有找到 endpoint_url")
  66. style_match = re.search("addressing_style[\s]*=[\s]*([^\s\n]+)[\s\n]*$", s3_str, re.MULTILINE)
  67. if style_match:
  68. addressing_style = style_match.group(1)
  69. else:
  70. addressing_style = "path"
  71. elif isinstance(profile, dict):
  72. ak = profile["ak"]
  73. sk = profile["sk"]
  74. endpoint = profile["endpoint"]
  75. addressing_style = "auto"
  76. return ak, sk, endpoint, addressing_style
  77. def parse_bucket_key(s3_full_path: str):
  78. """
  79. 输入 s3://bucket/path/to/my/file.txt
  80. 输出 bucket, path/to/my/file.txt
  81. """
  82. s3_full_path = s3_full_path.strip()
  83. if s3_full_path.startswith("s3://"):
  84. s3_full_path = s3_full_path[5:]
  85. if s3_full_path.startswith("/"):
  86. s3_full_path = s3_full_path[1:]
  87. bucket, key = s3_full_path.split("/", 1)
  88. return bucket, key
  89. def read_file(pdf_path: str, s3_profile):
  90. if pdf_path.startswith("s3://"):
  91. ak, sk, end_point, addressing_style = parse_aws_param(s3_profile)
  92. cli = boto3.client(service_name="s3", aws_access_key_id=ak, aws_secret_access_key=sk, endpoint_url=end_point,
  93. config=Config(s3={'addressing_style': addressing_style}, retries={'max_attempts': 10, 'mode': 'standard'}))
  94. bucket_name, bucket_key = parse_bucket_key(pdf_path)
  95. res = cli.get_object(Bucket=bucket_name, Key=bucket_key)
  96. file_content = res["Body"].read()
  97. return file_content
  98. else:
  99. with open(pdf_path, "rb") as f:
  100. return f.read()
  101. def get_docx_model_output(pdf_model_output, page_id):
  102. model_output_json = pdf_model_output[page_id]
  103. return model_output_json
  104. def list_dir(dir_path:str, s3_profile:str):
  105. """
  106. 列出dir_path下的所有文件
  107. """
  108. ret = []
  109. if dir_path.startswith("s3"):
  110. ak, sk, end_point, addressing_style = parse_aws_param(s3_profile)
  111. s3info = re.findall(r"s3:\/\/([^\/]+)\/(.*)", dir_path)
  112. bucket, path = s3info[0][0], s3info[0][1]
  113. try:
  114. cli = boto3.client(service_name="s3", aws_access_key_id=ak, aws_secret_access_key=sk, endpoint_url=end_point,
  115. config=Config(s3={'addressing_style': addressing_style}))
  116. def list_obj_scluster():
  117. marker = None
  118. while True:
  119. list_kwargs = dict(MaxKeys=1000, Bucket=bucket, Prefix=path)
  120. if marker:
  121. list_kwargs['Marker'] = marker
  122. response = cli.list_objects(**list_kwargs)
  123. contents = response.get("Contents", [])
  124. yield from contents
  125. if not response.get("IsTruncated") or len(contents)==0:
  126. break
  127. marker = contents[-1]['Key']
  128. for info in list_obj_scluster():
  129. file_path = info['Key']
  130. #size = info['Size']
  131. if path!="":
  132. afile = file_path[len(path):]
  133. if afile.endswith(".json"):
  134. ret.append(f"s3://{bucket}/{file_path}")
  135. return ret
  136. except Exception as e:
  137. logger.exception(e)
  138. exit(-1)
  139. else: #本地的目录,那么扫描本地目录并返会这个目录里的所有jsonl文件
  140. for root, dirs, files in os.walk(dir_path):
  141. for file in files:
  142. if file.endswith(".json"):
  143. ret.append(join_path(root, file))
  144. ret.sort()
  145. return ret
  146. def get_img_s3_client(save_path:str, image_s3_config:str):
  147. """
  148. """
  149. if save_path.startswith("s3://"): # 放这里是为了最少创建一个s3 client
  150. ak, sk, end_point, addressing_style = parse_aws_param(image_s3_config)
  151. img_s3_client = boto3.client(
  152. service_name="s3",
  153. aws_access_key_id=ak,
  154. aws_secret_access_key=sk,
  155. endpoint_url=end_point,
  156. config=Config(s3={"addressing_style": addressing_style}, retries={'max_attempts': 5, 'mode': 'standard'}),
  157. )
  158. else:
  159. img_s3_client = None
  160. return img_s3_client
  161. if __name__=="__main__":
  162. s3_path = "s3://llm-pdf-text/layout_det/scihub/scimag07865000-07865999/10.1007/s10729-011-9175-6.pdf/"
  163. s3_profile = "langchao"
  164. ret = list_dir(s3_path, s3_profile)
  165. print(ret)