Spaces:
Running
Running
HoneyTian
commited on
Commit
·
e94100d
0
Parent(s):
first commit
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +41 -0
- .gitignore +20 -0
- Dockerfile +17 -0
- README.md +11 -0
- data/files/doc/公司开票信息:深圳牛信.docx +3 -0
- data/files/doc/坏账处理流程 v1.0.docx +3 -0
- data/files/doc/账单管理流程 v1.0.doc +3 -0
- data/files/html/nxcloud.html +3 -0
- data/files/html/nxlink.html +3 -0
- data/files/pdf/1.Double Domain Guided Real-Time Low-Light Image Enhancement for Ultra-High-Definition Transportation Surveillance.pdf +3 -0
- data/files/pdf/2024.naacl-long.35.pdf +3 -0
- data/files/pdf/临时救助工作应知应会知识.pdf +3 -0
- data/files/ppt/AI能力分享.pptx +3 -0
- data/files/ppt/钉钉基础使用手册.pptx +3 -0
- data/files/xlsx/可对外提供资料清单说明-V1.0版本2022.1.13.xlsx +3 -0
- data/files/xlsx/财务部流程文档编号记录.xlsx +3 -0
- data/vocab.txt +0 -0
- examples/difflib_/difflib_.py +38 -0
- examples/document_load_score/step_1_convert_to_md_only_one.py +44 -0
- examples/document_load_score/step_2_convert_to_md_batch.py +67 -0
- examples/document_load_score/step_3_document_load_score_only_one.py +97 -0
- examples/document_load_score/step_4_document_load_score_batch.py +139 -0
- examples/document_load_score/step_5_document_load_score.py +95 -0
- examples/document_loaders/docx_load/docx2md_.py +44 -0
- examples/document_loaders/docx_load/docx2txt_.py +37 -0
- examples/document_loaders/docx_load/docx_.py +91 -0
- examples/document_loaders/docx_load/spire_doc.py +9 -0
- examples/document_loaders/docx_load/word_to_md.py +119 -0
- examples/document_loaders/excel_load/pandas_.py +41 -0
- examples/document_loaders/html_load/bs4_1.py +59 -0
- examples/document_loaders/html_load/bs4_2.py +41 -0
- examples/document_loaders/html_load/bs4_3.py +130 -0
- examples/document_loaders/html_load/html_to_pdf.py +27 -0
- examples/document_loaders/html_load/html_to_text_.py +44 -0
- examples/document_loaders/html_load/lxml_.py +42 -0
- examples/document_loaders/html_load/markdownify_.py +144 -0
- examples/document_loaders/html_load/selenium_.py +40 -0
- examples/document_loaders/pdf_load/aspose_words.py +33 -0
- examples/document_loaders/pdf_load/pdf_to_markdown.py +39 -0
- examples/document_loaders/pdf_load/pdfminer_.py +72 -0
- examples/document_loaders/pdf_load/pymupdf4llm_.py +34 -0
- examples/document_loaders/pdf_load/pypdf2_.py +39 -0
- examples/document_loaders/pdf_load/pypdf_.py +40 -0
- examples/document_loaders/ppt_load/pptx2md_.py +10 -0
- examples/document_loaders/ppt_load/pptx_.py +94 -0
- examples/document_loaders/ppt_load/unstructured_pptx_.py +38 -0
- examples/sentence_similarity.py +81 -0
- examples/unstructured_/unstructured_.py +19 -0
- examples_chunk_similar.json +37 -0
- log.py +229 -0
.gitattributes
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
*.doc filter=lfs diff=lfs merge=lfs -text
|
37 |
+
*.docx filter=lfs diff=lfs merge=lfs -text
|
38 |
+
*.html filter=lfs diff=lfs merge=lfs -text
|
39 |
+
*.pdf filter=lfs diff=lfs merge=lfs -text
|
40 |
+
*.pptx filter=lfs diff=lfs merge=lfs -text
|
41 |
+
*.xlsx filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
.git/
|
3 |
+
.gradio/
|
4 |
+
.idea/
|
5 |
+
|
6 |
+
/data/.wdm
|
7 |
+
/data/eval_dataset
|
8 |
+
#/data/files/doc
|
9 |
+
#/data/files/html
|
10 |
+
#/data/files/pdf
|
11 |
+
#/data/files/ppt
|
12 |
+
#/data/files/xlsx
|
13 |
+
/data/unstructured_eval
|
14 |
+
|
15 |
+
#/data/
|
16 |
+
/dotenv/
|
17 |
+
/logs/
|
18 |
+
/tmp/
|
19 |
+
|
20 |
+
**/__pycache__/
|
Dockerfile
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.12-slim
|
2 |
+
|
3 |
+
WORKDIR /code
|
4 |
+
|
5 |
+
COPY . /code
|
6 |
+
|
7 |
+
RUN apt-get update
|
8 |
+
RUN apt-get install -y libicu-dev
|
9 |
+
|
10 |
+
RUN pip install --upgrade pip
|
11 |
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
12 |
+
|
13 |
+
USER root
|
14 |
+
|
15 |
+
RUN chmod -R 777 .
|
16 |
+
|
17 |
+
CMD ["python3", "main.py"]
|
README.md
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: Document Loaders
|
3 |
+
emoji: 🐨
|
4 |
+
colorFrom: blue
|
5 |
+
colorTo: indigo
|
6 |
+
sdk: docker
|
7 |
+
pinned: false
|
8 |
+
license: apache-2.0
|
9 |
+
---
|
10 |
+
|
11 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
data/files/doc/公司开票信息:深圳牛信.docx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:b76c5097d1630e231e8e4476cb56e339cbbe3e2d0a7ce9c3f3c152cb76fec917
|
3 |
+
size 73873
|
data/files/doc/坏账处理流程 v1.0.docx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:b58d5b513434ab2a4f124cf66fe96494beea43fc773f6f0da4431dde6c8133d0
|
3 |
+
size 291596
|
data/files/doc/账单管理流程 v1.0.doc
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:010aa9e0212e6225f3667af57811cf5ea7e153fdb46f2f7c225e1a924ceccb62
|
3 |
+
size 269910
|
data/files/html/nxcloud.html
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:7dfe540d1faba32c5d8ced6c791145c2407334446fd43a30445e30b637be8bff
|
3 |
+
size 188839
|
data/files/html/nxlink.html
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:04c2df04d4aac08ac6fb80eefa9542cbb73dd1a543c178a5b31471ef37366f84
|
3 |
+
size 168616
|
data/files/pdf/1.Double Domain Guided Real-Time Low-Light Image Enhancement for Ultra-High-Definition Transportation Surveillance.pdf
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:46388f1eb27a93c793ba174684448d402de2bfcbc25db167f4ad7243534f403c
|
3 |
+
size 6825570
|
data/files/pdf/2024.naacl-long.35.pdf
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:db5d8e82b5b6aacf3eaa0db16f6437de14634e1761871379144626a2f585500f
|
3 |
+
size 532039
|
data/files/pdf/临时救助工作应知应会知识.pdf
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:eddf65315dbe7ffb9a2f321e0bd12c1ed0ea21ea40cbcc3fac9111f08f55f9a5
|
3 |
+
size 304984
|
data/files/ppt/AI能力分享.pptx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:68b2a6e255574de21e2f5f1a7b3b0408331cc5a352355eb0a771c2580ec9b4ad
|
3 |
+
size 4776424
|
data/files/ppt/钉钉基础使用手册.pptx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ee5249d10678e7b63beea333528eadda7b661d8968960f5c85df6cc58f51daae
|
3 |
+
size 13185881
|
data/files/xlsx/可对外提供资料清单说明-V1.0版本2022.1.13.xlsx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:9a629b2fad3f565e42e8b81fe0553d0fe80c0439ac5ce439d35ad00f21d16d94
|
3 |
+
size 8308
|
data/files/xlsx/财务部流程文档编号记录.xlsx
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:fc474f3e37e673c11ea3fce0db18c5a97dcd5feec32f1f49cf49e4aa77d0ba1a
|
3 |
+
size 9678
|
data/vocab.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
examples/difflib_/difflib_.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://docs.python.org/3/library/difflib.html
|
5 |
+
|
6 |
+
https://blog.csdn.net/stone0823/article/details/112310176
|
7 |
+
"""
|
8 |
+
import difflib
|
9 |
+
|
10 |
+
|
11 |
+
text1 = '''
|
12 |
+
I love HaiYan
|
13 |
+
I very love HaiYan
|
14 |
+
She's the one I love the most.
|
15 |
+
'''
|
16 |
+
|
17 |
+
text2 = '''
|
18 |
+
I love LiWang
|
19 |
+
I very love LiWang
|
20 |
+
I'm his favorite person.
|
21 |
+
'''
|
22 |
+
|
23 |
+
d = difflib.Differ()
|
24 |
+
|
25 |
+
result = d.compare(text1, text2)
|
26 |
+
result = "".join(list(result))
|
27 |
+
print(result)
|
28 |
+
|
29 |
+
seq_match = difflib.SequenceMatcher(None, text1, text2)
|
30 |
+
ratio = seq_match.ratio()
|
31 |
+
print(ratio)
|
32 |
+
|
33 |
+
match = seq_match.get_matching_blocks()
|
34 |
+
print(match)
|
35 |
+
|
36 |
+
|
37 |
+
if __name__ == "__main__":
|
38 |
+
pass
|
examples/document_load_score/step_1_convert_to_md_only_one.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
from pathlib import Path
|
5 |
+
|
6 |
+
from gradio_client import Client, handle_file
|
7 |
+
|
8 |
+
from project_settings import project_path
|
9 |
+
|
10 |
+
|
11 |
+
def get_args():
|
12 |
+
parser = argparse.ArgumentParser()
|
13 |
+
parser.add_argument(
|
14 |
+
"--filename",
|
15 |
+
default=(project_path / "data/eval_dataset/1.Double Domain Guided Real-Time Low-Light Image Enhancement for Ultra-High-Definition Transportation Surveillance.pdf").as_posix(),
|
16 |
+
type=str
|
17 |
+
)
|
18 |
+
args = parser.parse_args()
|
19 |
+
return args
|
20 |
+
|
21 |
+
|
22 |
+
def main():
|
23 |
+
args = get_args()
|
24 |
+
|
25 |
+
filename = Path(args.filename)
|
26 |
+
output_file = filename.parent / "tmp" / f"{filename.stem}.md"
|
27 |
+
output_file.parent.mkdir(parents=True, exist_ok=True)
|
28 |
+
|
29 |
+
client = Client("http://127.0.0.1:7860/")
|
30 |
+
filepath, md_render, md_text = client.predict(
|
31 |
+
filename=handle_file(filename.as_posix()),
|
32 |
+
engine="aliyun",
|
33 |
+
extension="pdf",
|
34 |
+
api_name="/run_to_markdown"
|
35 |
+
)
|
36 |
+
|
37 |
+
with open(output_file.as_posix(), "w", encoding="utf-8") as f:
|
38 |
+
f.write(md_text)
|
39 |
+
|
40 |
+
return
|
41 |
+
|
42 |
+
|
43 |
+
if __name__ == "__main__":
|
44 |
+
main()
|
examples/document_load_score/step_2_convert_to_md_batch.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
from pathlib import Path
|
5 |
+
from tqdm import tqdm
|
6 |
+
|
7 |
+
from gradio_client import Client, handle_file
|
8 |
+
|
9 |
+
from project_settings import project_path
|
10 |
+
|
11 |
+
|
12 |
+
def get_args():
|
13 |
+
parser = argparse.ArgumentParser()
|
14 |
+
parser.add_argument(
|
15 |
+
"--file_dir",
|
16 |
+
default=(project_path / "data/eval_dataset/pdf/pdf_text").as_posix(),
|
17 |
+
type=str
|
18 |
+
)
|
19 |
+
parser.add_argument(
|
20 |
+
"--output_dir",
|
21 |
+
default=(project_path / "data/eval_dataset/pdf/pdf_text_md").as_posix(),
|
22 |
+
type=str
|
23 |
+
)
|
24 |
+
args = parser.parse_args()
|
25 |
+
return args
|
26 |
+
|
27 |
+
|
28 |
+
def main():
|
29 |
+
args = get_args()
|
30 |
+
file_dir = Path(args.file_dir)
|
31 |
+
output_dir = Path(args.output_dir)
|
32 |
+
output_dir.mkdir(parents=True, exist_ok=True)
|
33 |
+
|
34 |
+
finished = set()
|
35 |
+
for filename in output_dir.glob("*.md"):
|
36 |
+
basename = filename.stem
|
37 |
+
finished.add(basename)
|
38 |
+
print(f"finished count: {len(finished)}")
|
39 |
+
|
40 |
+
client = Client("http://127.0.0.1:7860/")
|
41 |
+
|
42 |
+
for filename in tqdm(file_dir.glob("*.pdf")):
|
43 |
+
basename = filename.stem
|
44 |
+
if basename in finished:
|
45 |
+
continue
|
46 |
+
finished.add(basename)
|
47 |
+
|
48 |
+
print(f"filename: {filename.as_posix()}")
|
49 |
+
|
50 |
+
output_file = output_dir / f"{basename}.md"
|
51 |
+
|
52 |
+
filepath, md_render, md_text = client.predict(
|
53 |
+
filename=handle_file(filename.as_posix()),
|
54 |
+
engine="aliyun",
|
55 |
+
extension="pdf",
|
56 |
+
api_name="/run_to_markdown"
|
57 |
+
)
|
58 |
+
|
59 |
+
with open(output_file.as_posix(), "w", encoding="utf-8") as f:
|
60 |
+
f.write(md_text)
|
61 |
+
|
62 |
+
# break
|
63 |
+
return
|
64 |
+
|
65 |
+
|
66 |
+
if __name__ == "__main__":
|
67 |
+
main()
|
examples/document_load_score/step_3_document_load_score_only_one.py
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
import json
|
5 |
+
from pathlib import Path
|
6 |
+
import re
|
7 |
+
from tqdm import tqdm
|
8 |
+
|
9 |
+
from gradio_client import Client, handle_file
|
10 |
+
|
11 |
+
from project_settings import project_path
|
12 |
+
|
13 |
+
|
14 |
+
def get_args():
|
15 |
+
parser = argparse.ArgumentParser()
|
16 |
+
parser.add_argument(
|
17 |
+
"--md_file",
|
18 |
+
default=(project_path / "data/eval_dataset/pdf/pdf_md/1.Double Domain Guided Real-Time Low-Light Image Enhancement for Ultra-High-Definition Transportation Surveillance.md").as_posix(),
|
19 |
+
type=str
|
20 |
+
)
|
21 |
+
parser.add_argument(
|
22 |
+
"--jsonl_file",
|
23 |
+
default=(project_path / "data/eval_dataset/pdf/jsonl/1.jsonl").as_posix(),
|
24 |
+
type=str
|
25 |
+
)
|
26 |
+
parser.add_argument(
|
27 |
+
"--output_jsonl_dir",
|
28 |
+
default=(project_path / "data/eval_dataset/pdf/jsonl_with_score").as_posix(),
|
29 |
+
type=str
|
30 |
+
)
|
31 |
+
args = parser.parse_args()
|
32 |
+
return args
|
33 |
+
|
34 |
+
|
35 |
+
def main():
|
36 |
+
args = get_args()
|
37 |
+
|
38 |
+
md_file = Path(args.md_file)
|
39 |
+
jsonl_file = Path(args.jsonl_file)
|
40 |
+
output_jsonl_dir = Path(args.output_jsonl_dir)
|
41 |
+
output_jsonl_dir.mkdir(parents=True, exist_ok=True)
|
42 |
+
|
43 |
+
output_file = output_jsonl_dir / f"{jsonl_file.stem}.jsonl"
|
44 |
+
|
45 |
+
client = Client(
|
46 |
+
"http://127.0.0.1:7860/"
|
47 |
+
)
|
48 |
+
|
49 |
+
with open(md_file.as_posix(), "r", encoding="utf-8") as f:
|
50 |
+
md_text = f.read()
|
51 |
+
|
52 |
+
process_bar = tqdm(desc="chunk_similar")
|
53 |
+
with open(jsonl_file.as_posix(), "r", encoding="utf-8") as fin, open(output_file.as_posix(), "w", encoding="utf-8") as fout:
|
54 |
+
for row in fin:
|
55 |
+
row = json.loads(row)
|
56 |
+
doc_id = row["doc_id"]
|
57 |
+
type_ = row["type"]
|
58 |
+
chunk_id = row["chunk_id"]
|
59 |
+
content = row["content"]
|
60 |
+
|
61 |
+
content = str(content).strip()
|
62 |
+
content_length = len(content)
|
63 |
+
|
64 |
+
match, diff, scores = client.predict(
|
65 |
+
page_content=md_text,
|
66 |
+
chunk=content,
|
67 |
+
win_size_radio=1.6,
|
68 |
+
api_name="/run_chunk_similar"
|
69 |
+
)
|
70 |
+
|
71 |
+
order_idx = md_text.index(match)
|
72 |
+
|
73 |
+
ed_score = re.search(r"\| ed_score \| (.+?) \| .+? \|", scores, flags=re.DOTALL)
|
74 |
+
seq_match = re.search(r"\| seq_match \| (.+?) \| .+? \|", scores, flags=re.DOTALL)
|
75 |
+
|
76 |
+
ed_score = float(ed_score.group(1))
|
77 |
+
seq_match = float(seq_match.group(1))
|
78 |
+
|
79 |
+
row_ = {
|
80 |
+
"doc_id": doc_id,
|
81 |
+
"type": type_,
|
82 |
+
"chunk_id": chunk_id,
|
83 |
+
"content": content,
|
84 |
+
|
85 |
+
"content_length": content_length,
|
86 |
+
"match_idx": order_idx,
|
87 |
+
"ed_score": ed_score,
|
88 |
+
"seq_match": seq_match,
|
89 |
+
}
|
90 |
+
row_ = json.dumps(row_, ensure_ascii=False)
|
91 |
+
fout.write(f"{row_}\n")
|
92 |
+
process_bar.update(1)
|
93 |
+
return
|
94 |
+
|
95 |
+
|
96 |
+
if __name__ == "__main__":
|
97 |
+
main()
|
examples/document_load_score/step_4_document_load_score_batch.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
from collections import defaultdict
|
5 |
+
import json
|
6 |
+
from pathlib import Path
|
7 |
+
import re
|
8 |
+
from tqdm import tqdm
|
9 |
+
from typing import Dict
|
10 |
+
|
11 |
+
from gradio_client import Client, handle_file
|
12 |
+
|
13 |
+
from project_settings import project_path
|
14 |
+
|
15 |
+
|
16 |
+
def get_args():
|
17 |
+
parser = argparse.ArgumentParser()
|
18 |
+
parser.add_argument(
|
19 |
+
"--md_dir",
|
20 |
+
default=(project_path / "data/eval_dataset/pdf/pdf_text_md").as_posix(),
|
21 |
+
type=str
|
22 |
+
)
|
23 |
+
parser.add_argument(
|
24 |
+
"--jsonl_dir",
|
25 |
+
default=(project_path / "data/eval_dataset/pdf/jsonl").as_posix(),
|
26 |
+
type=str
|
27 |
+
)
|
28 |
+
parser.add_argument(
|
29 |
+
"--output_jsonl_dir",
|
30 |
+
default=(project_path / "data/eval_dataset/pdf/pdf_text_jsonl_with_score").as_posix(),
|
31 |
+
type=str
|
32 |
+
)
|
33 |
+
args = parser.parse_args()
|
34 |
+
return args
|
35 |
+
|
36 |
+
|
37 |
+
def main():
|
38 |
+
args = get_args()
|
39 |
+
|
40 |
+
md_dir = Path(args.md_dir)
|
41 |
+
jsonl_dir = Path(args.jsonl_dir)
|
42 |
+
output_jsonl_dir = Path(args.output_jsonl_dir)
|
43 |
+
output_jsonl_dir.mkdir(parents=True, exist_ok=True)
|
44 |
+
|
45 |
+
name_to_files: Dict[str, Dict[str, Path]] = defaultdict(dict)
|
46 |
+
for filename in md_dir.glob("*.md"):
|
47 |
+
key = filename.stem.split(".", maxsplit=1)[0]
|
48 |
+
name_to_files[key]["md"] = filename
|
49 |
+
|
50 |
+
for filename in jsonl_dir.glob("*.jsonl"):
|
51 |
+
key = filename.stem
|
52 |
+
name_to_files[key]["jsonl"] = filename
|
53 |
+
|
54 |
+
# print
|
55 |
+
print(f"print name_to_files start")
|
56 |
+
for key, value in name_to_files.items():
|
57 |
+
print(f"key: {key}")
|
58 |
+
for k, v in value.items():
|
59 |
+
print(f"k: {k}")
|
60 |
+
print(f"v: {v.as_posix()}")
|
61 |
+
print(f"print name_to_files end")
|
62 |
+
print("\n\n")
|
63 |
+
|
64 |
+
# finished
|
65 |
+
finished = set()
|
66 |
+
for filename in output_jsonl_dir.glob("*.jsonl"):
|
67 |
+
key = filename.stem
|
68 |
+
finished.add(key)
|
69 |
+
print(f"finished count: {len(finished)}")
|
70 |
+
|
71 |
+
client = Client(
|
72 |
+
"http://127.0.0.1:7860/"
|
73 |
+
)
|
74 |
+
|
75 |
+
for key, value in name_to_files.items():
|
76 |
+
if key in finished:
|
77 |
+
print(f"skip key: {key}")
|
78 |
+
continue
|
79 |
+
finished.add(key)
|
80 |
+
|
81 |
+
md_file = value["md"]
|
82 |
+
jsonl_file = value["jsonl"]
|
83 |
+
output_file = output_jsonl_dir / f"{jsonl_file.stem}.jsonl"
|
84 |
+
|
85 |
+
print("\n")
|
86 |
+
print(f"md_file: {md_file}")
|
87 |
+
print(f"jsonl_file: {jsonl_file}")
|
88 |
+
print("\n")
|
89 |
+
|
90 |
+
with open(md_file.as_posix(), "r", encoding="utf-8") as f:
|
91 |
+
md_text = f.read()
|
92 |
+
|
93 |
+
process_bar = tqdm(desc="chunk_similar")
|
94 |
+
with open(jsonl_file.as_posix(), "r", encoding="utf-8") as fin, open(output_file.as_posix(), "w", encoding="utf-8") as fout:
|
95 |
+
for row in fin:
|
96 |
+
row = json.loads(row)
|
97 |
+
doc_id = row["doc_id"]
|
98 |
+
type_ = row["type"]
|
99 |
+
chunk_id = row["chunk_id"]
|
100 |
+
content = row["content"]
|
101 |
+
|
102 |
+
content = str(content).strip()
|
103 |
+
content_length = len(content)
|
104 |
+
|
105 |
+
match, diff, scores = client.predict(
|
106 |
+
page_content=md_text,
|
107 |
+
chunk=content,
|
108 |
+
win_size_radio=1.6,
|
109 |
+
api_name="/run_chunk_similar"
|
110 |
+
)
|
111 |
+
|
112 |
+
order_idx = md_text.index(match)
|
113 |
+
|
114 |
+
ed_score = re.search(r"\| ed_score \| (.+?) \| .+? \|", scores, flags=re.DOTALL)
|
115 |
+
seq_match = re.search(r"\| seq_match \| (.+?) \| .+? \|", scores, flags=re.DOTALL)
|
116 |
+
|
117 |
+
ed_score = float(ed_score.group(1))
|
118 |
+
seq_match = float(seq_match.group(1))
|
119 |
+
|
120 |
+
row_ = {
|
121 |
+
"doc_id": doc_id,
|
122 |
+
"type": type_,
|
123 |
+
"chunk_id": chunk_id,
|
124 |
+
"content": content,
|
125 |
+
|
126 |
+
"content_length": content_length,
|
127 |
+
"match_idx": order_idx,
|
128 |
+
"ed_score": ed_score,
|
129 |
+
"seq_match": seq_match,
|
130 |
+
}
|
131 |
+
row_ = json.dumps(row_, ensure_ascii=False)
|
132 |
+
fout.write(f"{row_}\n")
|
133 |
+
process_bar.update(1)
|
134 |
+
|
135 |
+
return
|
136 |
+
|
137 |
+
|
138 |
+
if __name__ == "__main__":
|
139 |
+
main()
|
examples/document_load_score/step_5_document_load_score.py
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
import json
|
5 |
+
import math
|
6 |
+
from pathlib import Path
|
7 |
+
import re
|
8 |
+
|
9 |
+
import pandas as pd
|
10 |
+
from tqdm import tqdm
|
11 |
+
|
12 |
+
from gradio_client import Client, handle_file
|
13 |
+
import numpy as np
|
14 |
+
|
15 |
+
from project_settings import project_path
|
16 |
+
from toolbox.unstructured_eval.inversion import inversions
|
17 |
+
|
18 |
+
|
19 |
+
def get_args():
|
20 |
+
parser = argparse.ArgumentParser()
|
21 |
+
parser.add_argument(
|
22 |
+
"--file_dir",
|
23 |
+
default=(project_path / "data/eval_dataset/pdf/pdf_text_jsonl_with_score").as_posix(),
|
24 |
+
type=str
|
25 |
+
)
|
26 |
+
args = parser.parse_args()
|
27 |
+
return args
|
28 |
+
|
29 |
+
|
30 |
+
def main():
|
31 |
+
args = get_args()
|
32 |
+
|
33 |
+
file_dir = Path(args.file_dir)
|
34 |
+
output_file = file_dir / "eval.xlsx"
|
35 |
+
|
36 |
+
result = list()
|
37 |
+
for filename in file_dir.glob("*.jsonl"):
|
38 |
+
with open(filename.as_posix(), "r", encoding="utf-8") as f:
|
39 |
+
total_length = 0
|
40 |
+
total_ed_score = 0
|
41 |
+
total_seq_match = 0
|
42 |
+
match_idx_list = list()
|
43 |
+
for row in f:
|
44 |
+
row = json.loads(row)
|
45 |
+
|
46 |
+
|
47 |
+
doc_id = row["doc_id"]
|
48 |
+
type_ = row["type"]
|
49 |
+
chunk_id = row["chunk_id"]
|
50 |
+
content = row["content"]
|
51 |
+
|
52 |
+
content_length = row["content_length"]
|
53 |
+
match_idx = row["match_idx"]
|
54 |
+
ed_score = row["ed_score"]
|
55 |
+
seq_match = row["seq_match"]
|
56 |
+
|
57 |
+
total_length += content_length
|
58 |
+
total_ed_score += float(ed_score) * content_length
|
59 |
+
total_seq_match += float(seq_match) * content_length
|
60 |
+
|
61 |
+
match_idx_list.append(match_idx)
|
62 |
+
|
63 |
+
average_ed_score = total_ed_score / total_length
|
64 |
+
average_seq_match = total_seq_match / total_length
|
65 |
+
|
66 |
+
average_ed_score = round(average_ed_score, 4)
|
67 |
+
average_seq_match = round(average_seq_match, 4)
|
68 |
+
|
69 |
+
print(f"average_ed_score: {average_ed_score}, average_seq_match: {average_seq_match}")
|
70 |
+
|
71 |
+
arg_idx = np.argsort(match_idx_list)
|
72 |
+
print(f"arg_idx: {arg_idx}")
|
73 |
+
|
74 |
+
inversion_count = inversions(arg_idx)
|
75 |
+
print(f"inversion_count: {inversion_count}")
|
76 |
+
|
77 |
+
row_ = {
|
78 |
+
"doc_id": doc_id,
|
79 |
+
"type": type_,
|
80 |
+
|
81 |
+
"total_length": total_length,
|
82 |
+
"average_ed_score": average_ed_score,
|
83 |
+
"average_seq_match": average_seq_match,
|
84 |
+
"arg_idx": str(arg_idx),
|
85 |
+
"inversion_count": inversion_count,
|
86 |
+
}
|
87 |
+
result.append(row_)
|
88 |
+
|
89 |
+
result = pd.DataFrame(result)
|
90 |
+
result.to_excel(output_file.as_posix(), index=False)
|
91 |
+
return
|
92 |
+
|
93 |
+
|
94 |
+
if __name__ == "__main__":
|
95 |
+
main()
|
examples/document_loaders/docx_load/docx2md_.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/docx2md/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import docx2md
|
9 |
+
from docx2md.docxfile import DocxFile, DocxFileError
|
10 |
+
from docx2md.docxmedia import DocxMedia
|
11 |
+
from docx2md.converter import Converter
|
12 |
+
|
13 |
+
from project_settings import project_path
|
14 |
+
|
15 |
+
|
16 |
+
def get_args():
|
17 |
+
parser = argparse.ArgumentParser()
|
18 |
+
parser.add_argument(
|
19 |
+
"--filename",
|
20 |
+
# default=(project_path / "data/files/doc/公司开票信息:深圳牛信.docx").as_posix(),
|
21 |
+
default=(project_path / "data/files/doc/坏账处理流程 v1.0.docx").as_posix(),
|
22 |
+
# default=(project_path / "data/files/doc/账单管理流程 v1.0.doc").as_posix(),
|
23 |
+
type=str
|
24 |
+
)
|
25 |
+
args = parser.parse_args()
|
26 |
+
return args
|
27 |
+
|
28 |
+
|
29 |
+
def main():
|
30 |
+
args = get_args()
|
31 |
+
|
32 |
+
docx = DocxFile(args.filename)
|
33 |
+
xml_text = docx.document()
|
34 |
+
media = DocxMedia(docx)
|
35 |
+
|
36 |
+
converter = Converter(xml_text, media, True)
|
37 |
+
# converter = Converter(xml_text, media, False)
|
38 |
+
md_text = converter.convert()
|
39 |
+
print(md_text)
|
40 |
+
return
|
41 |
+
|
42 |
+
|
43 |
+
if __name__ == "__main__":
|
44 |
+
main()
|
examples/document_loaders/docx_load/docx2txt_.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/pypdf/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import docx2txt
|
9 |
+
|
10 |
+
from project_settings import project_path
|
11 |
+
|
12 |
+
|
13 |
+
def get_args():
|
14 |
+
parser = argparse.ArgumentParser()
|
15 |
+
parser.add_argument(
|
16 |
+
"--filename",
|
17 |
+
# default=(project_path / "data/files/doc/公司开票信息:深圳牛信.docx").as_posix(),
|
18 |
+
default=(project_path / "data/files/doc/坏账处理流程 v1.0.docx").as_posix(),
|
19 |
+
# default=(project_path / "data/files/doc/账单管理流程 v1.0.doc").as_posix(),
|
20 |
+
type=str
|
21 |
+
)
|
22 |
+
args = parser.parse_args()
|
23 |
+
return args
|
24 |
+
|
25 |
+
|
26 |
+
def main():
|
27 |
+
args = get_args()
|
28 |
+
|
29 |
+
# 包含表结构中的文字,但表结构被破坏。
|
30 |
+
text = docx2txt.process(args.filename)
|
31 |
+
print(text)
|
32 |
+
|
33 |
+
return
|
34 |
+
|
35 |
+
|
36 |
+
if __name__ == "__main__":
|
37 |
+
main()
|
examples/document_loaders/docx_load/docx_.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://blog.51cto.com/u_16213370/11698334
|
5 |
+
|
6 |
+
如果你可以将 .doc 文件转换为 .docx 格式,
|
7 |
+
可以使用 python-docx 库来读取 .docx 文件。
|
8 |
+
转换可以通过 libreoffice 或 unoconv 等工具完成。
|
9 |
+
|
10 |
+
sudo apt-get install libreoffice
|
11 |
+
|
12 |
+
libreoffice --headless --convert-to docx example.doc
|
13 |
+
|
14 |
+
"""
|
15 |
+
import argparse
|
16 |
+
|
17 |
+
from docx import Document
|
18 |
+
from docx.table import Table
|
19 |
+
from docx.text.paragraph import Paragraph
|
20 |
+
|
21 |
+
from project_settings import project_path
|
22 |
+
|
23 |
+
|
24 |
+
def get_args():
|
25 |
+
parser = argparse.ArgumentParser()
|
26 |
+
parser.add_argument(
|
27 |
+
"--filename",
|
28 |
+
# default=(project_path / "data/files/doc/公司开票信息:深圳牛信.docx").as_posix(),
|
29 |
+
# default=(project_path / "data/files/doc/坏账处理流程 v1.0.docx").as_posix(),
|
30 |
+
default=(project_path / "data/files/doc/账单管理流程 v1.0.doc").as_posix(),
|
31 |
+
type=str
|
32 |
+
)
|
33 |
+
args = parser.parse_args()
|
34 |
+
return args
|
35 |
+
|
36 |
+
|
37 |
+
def main():
|
38 |
+
args = get_args()
|
39 |
+
|
40 |
+
doc = Document(args.filename)
|
41 |
+
|
42 |
+
# 提取不到表格中的信息。
|
43 |
+
for para in doc.paragraphs:
|
44 |
+
print(para.text)
|
45 |
+
|
46 |
+
# 读取表格
|
47 |
+
for table in doc.tables:
|
48 |
+
for row in table.rows:
|
49 |
+
row_data = [cell.text for cell in row.cells]
|
50 |
+
print(row_data)
|
51 |
+
print("-------------------------------")
|
52 |
+
|
53 |
+
return
|
54 |
+
|
55 |
+
|
56 |
+
def main2():
|
57 |
+
args = get_args()
|
58 |
+
|
59 |
+
doc = Document(args.filename)
|
60 |
+
|
61 |
+
for section in doc.sections:
|
62 |
+
for content in section.iter_inner_content():
|
63 |
+
if isinstance(content, Paragraph):
|
64 |
+
text = content.text.strip()
|
65 |
+
if content.style.name == "Heading 1" and len(text) != 0:
|
66 |
+
text = f"# {content.text}"
|
67 |
+
elif content.style.name == "Heading 2" and len(text) != 0:
|
68 |
+
text = f"## {content.text}"
|
69 |
+
elif content.style.name == "Heading 3" and len(text) != 0:
|
70 |
+
text = f"### {content.text}"
|
71 |
+
elif content.style.name in ("Normal", "List Paragraph"):
|
72 |
+
pass
|
73 |
+
else:
|
74 |
+
# print(content.style.name)
|
75 |
+
text = content.text
|
76 |
+
print(text)
|
77 |
+
elif isinstance(content, Table):
|
78 |
+
print("-------------------------------")
|
79 |
+
for row in content.rows:
|
80 |
+
row_data = [cell.text for cell in row.cells]
|
81 |
+
row_data = [cell.replace("\n", "<br>") for cell in row_data]
|
82 |
+
row_ = "| {} |".format(" | ".join(row_data))
|
83 |
+
print(row_)
|
84 |
+
print("-------------------------------")
|
85 |
+
else:
|
86 |
+
raise AssertionError
|
87 |
+
return
|
88 |
+
|
89 |
+
|
90 |
+
if __name__ == "__main__":
|
91 |
+
main2()
|
examples/document_loaders/docx_load/spire_doc.py
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://www.e-iceblue.cn/docforpython/spire-doc-for-python-program-guide-content.html
|
5 |
+
"""
|
6 |
+
|
7 |
+
|
8 |
+
if __name__ == "__main__":
|
9 |
+
pass
|
examples/document_loaders/docx_load/word_to_md.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://blog.51cto.com/u_16213370/11698334
|
5 |
+
|
6 |
+
如果你可以将 .doc 文件转换为 .docx 格式,
|
7 |
+
可以使用 python-docx 库来读取 .docx 文件。
|
8 |
+
转换可以通过 libreoffice 或 unoconv 等工具完成。
|
9 |
+
|
10 |
+
sudo apt-get install libreoffice
|
11 |
+
|
12 |
+
libreoffice --headless --convert-to docx example.doc
|
13 |
+
|
14 |
+
|
15 |
+
|
16 |
+
https://blog.aspose.com/words/convert-word-to-markdown-using-python/
|
17 |
+
https://pypi.org/project/docx2md/
|
18 |
+
|
19 |
+
"""
|
20 |
+
import argparse
|
21 |
+
|
22 |
+
from docx import Document
|
23 |
+
from docx.table import Table
|
24 |
+
from docx.text.paragraph import Paragraph
|
25 |
+
|
26 |
+
from project_settings import project_path
|
27 |
+
|
28 |
+
|
29 |
+
def get_args():
|
30 |
+
parser = argparse.ArgumentParser()
|
31 |
+
parser.add_argument(
|
32 |
+
"--filename",
|
33 |
+
default=(project_path / "data/files/doc/公司开票信息:深圳牛信.docx").as_posix(),
|
34 |
+
# default=(project_path / "data/files/doc/坏账处理流程 v1.0.docx").as_posix(),
|
35 |
+
# default=(project_path / "data/files/doc/账单管理流程 v1.0.doc").as_posix(),
|
36 |
+
type=str
|
37 |
+
)
|
38 |
+
parser.add_argument(
|
39 |
+
"--output_file",
|
40 |
+
default="temp.md",
|
41 |
+
type=str
|
42 |
+
)
|
43 |
+
args = parser.parse_args()
|
44 |
+
return args
|
45 |
+
|
46 |
+
|
47 |
+
class Word(object):
|
48 |
+
def __init__(self, filename: str):
|
49 |
+
self.filename = filename
|
50 |
+
|
51 |
+
self.doc = Document(filename)
|
52 |
+
|
53 |
+
def get_markdown_text(self):
|
54 |
+
result = ""
|
55 |
+
|
56 |
+
for section in self.doc.sections:
|
57 |
+
for content in section.iter_inner_content():
|
58 |
+
if isinstance(content, Paragraph):
|
59 |
+
result += self.word_paragraph_to_markdown(content)
|
60 |
+
elif isinstance(content, Table):
|
61 |
+
result += self.word_table_to_markdown(content)
|
62 |
+
else:
|
63 |
+
raise AssertionError
|
64 |
+
return result
|
65 |
+
|
66 |
+
@staticmethod
|
67 |
+
def word_paragraph_to_markdown(paragraph: Paragraph):
|
68 |
+
text = paragraph.text.strip()
|
69 |
+
# print(paragraph.style.name)
|
70 |
+
if paragraph.style.name == "Heading 1" and len(text) != 0:
|
71 |
+
text = f"# {text}"
|
72 |
+
elif paragraph.style.name == "Heading 2" and len(text) != 0:
|
73 |
+
text = f"## {text}"
|
74 |
+
elif paragraph.style.name == "Heading 3" and len(text) != 0:
|
75 |
+
text = f"### {text}"
|
76 |
+
elif paragraph.style.name in ("Normal", "List Paragraph"):
|
77 |
+
pass
|
78 |
+
else:
|
79 |
+
pass
|
80 |
+
|
81 |
+
result = f"{text}\n"
|
82 |
+
return result
|
83 |
+
|
84 |
+
@staticmethod
|
85 |
+
def word_table_to_markdown(table: Table):
|
86 |
+
table_md = ""
|
87 |
+
for idx, row in enumerate(table.rows):
|
88 |
+
row_data = [cell.text for cell in row.cells]
|
89 |
+
row_data = [cell.replace("\n", "<br>") for cell in row_data]
|
90 |
+
row_ = "| {} |".format(" | ".join(row_data))
|
91 |
+
table_md += f"{row_}\n"
|
92 |
+
|
93 |
+
if idx == 0:
|
94 |
+
table_md += "| {} |\n".format("|".join(["---"] * len(row_data)))
|
95 |
+
|
96 |
+
result = f"{table_md}\n"
|
97 |
+
return result
|
98 |
+
|
99 |
+
def save_to_markdown(self, filename: str):
|
100 |
+
markdown_text = self.get_markdown_text()
|
101 |
+
with open(filename, "w", encoding="utf-8") as f:
|
102 |
+
f.write(markdown_text)
|
103 |
+
|
104 |
+
|
105 |
+
def main():
|
106 |
+
args = get_args()
|
107 |
+
|
108 |
+
word = Word(args.filename)
|
109 |
+
|
110 |
+
# result = word.get_markdown_text()
|
111 |
+
# print(result)
|
112 |
+
|
113 |
+
word.save_to_markdown(args.output_file)
|
114 |
+
|
115 |
+
return
|
116 |
+
|
117 |
+
|
118 |
+
if __name__ == "__main__":
|
119 |
+
main()
|
examples/document_loaders/excel_load/pandas_.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/pypdf/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import pandas as pd
|
9 |
+
|
10 |
+
from project_settings import project_path
|
11 |
+
|
12 |
+
|
13 |
+
def get_args():
|
14 |
+
parser = argparse.ArgumentParser()
|
15 |
+
parser.add_argument(
|
16 |
+
"--filename",
|
17 |
+
default=(project_path / "data/files/xlsx/可对外提供资料清单说明-V1.0版本2022.1.13.xlsx").as_posix(),
|
18 |
+
# default=(project_path / "data/files/xlsx/财务部流程文档编号记录.xlsx").as_posix(),
|
19 |
+
type=str
|
20 |
+
)
|
21 |
+
args = parser.parse_args()
|
22 |
+
return args
|
23 |
+
|
24 |
+
|
25 |
+
def main():
|
26 |
+
args = get_args()
|
27 |
+
|
28 |
+
sheet_name_to_df = pd.read_excel(args.filename, sheet_name=None)
|
29 |
+
|
30 |
+
for sheet_name, df in sheet_name_to_df.items():
|
31 |
+
print(f"----------- {sheet_name} -----------")
|
32 |
+
|
33 |
+
# text = df.to_string(index=False)
|
34 |
+
text = df.to_markdown(index=False)
|
35 |
+
print(text)
|
36 |
+
|
37 |
+
return
|
38 |
+
|
39 |
+
|
40 |
+
if __name__ == "__main__":
|
41 |
+
main()
|
examples/document_loaders/html_load/bs4_1.py
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/beautifulsoup4/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
from bs4 import BeautifulSoup
|
9 |
+
import lxml
|
10 |
+
|
11 |
+
from project_settings import project_path
|
12 |
+
|
13 |
+
|
14 |
+
def get_args():
|
15 |
+
parser = argparse.ArgumentParser()
|
16 |
+
parser.add_argument(
|
17 |
+
"--filename",
|
18 |
+
# default=(project_path / "data/files/html/nxlink.html").as_posix(),
|
19 |
+
default=(project_path / "data/files/html/nxcloud.html").as_posix(),
|
20 |
+
type=str
|
21 |
+
)
|
22 |
+
args = parser.parse_args()
|
23 |
+
return args
|
24 |
+
|
25 |
+
|
26 |
+
def main():
|
27 |
+
args = get_args()
|
28 |
+
|
29 |
+
with open(args.filename, "r", encoding="utf-8") as f:
|
30 |
+
html_doc = f.read()
|
31 |
+
|
32 |
+
soup = BeautifulSoup(html_doc, 'html.parser')
|
33 |
+
|
34 |
+
# 提取所有链接
|
35 |
+
print(f"--------- url ---------")
|
36 |
+
links = soup.find_all('a')
|
37 |
+
for link in links:
|
38 |
+
url = link.get('href')
|
39 |
+
print(url)
|
40 |
+
|
41 |
+
name_list = ["title", "p", "span", "div"]
|
42 |
+
for name in name_list:
|
43 |
+
print(f"--------- {name} ---------")
|
44 |
+
elements = soup.find_all(name)
|
45 |
+
for element in elements:
|
46 |
+
print(element.text)
|
47 |
+
|
48 |
+
name_list = ["meta"]
|
49 |
+
for name in name_list:
|
50 |
+
print(f"--------- {name} ---------")
|
51 |
+
elements = soup.find_all(name)
|
52 |
+
for element in elements:
|
53 |
+
print(element["content"])
|
54 |
+
|
55 |
+
return
|
56 |
+
|
57 |
+
|
58 |
+
if __name__ == "__main__":
|
59 |
+
main()
|
examples/document_loaders/html_load/bs4_2.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/beautifulsoup4/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
from bs4 import BeautifulSoup
|
9 |
+
import lxml
|
10 |
+
|
11 |
+
from project_settings import project_path
|
12 |
+
|
13 |
+
|
14 |
+
def get_args():
|
15 |
+
parser = argparse.ArgumentParser()
|
16 |
+
parser.add_argument(
|
17 |
+
"--filename",
|
18 |
+
# default=(project_path / "data/files/html/nxlink.html").as_posix(),
|
19 |
+
default=(project_path / "data/files/html/nxcloud.html").as_posix(),
|
20 |
+
type=str
|
21 |
+
)
|
22 |
+
args = parser.parse_args()
|
23 |
+
return args
|
24 |
+
|
25 |
+
|
26 |
+
def main():
|
27 |
+
args = get_args()
|
28 |
+
|
29 |
+
with open(args.filename, "r", encoding="utf-8") as f:
|
30 |
+
html_doc = f.read()
|
31 |
+
|
32 |
+
soup = BeautifulSoup(html_doc, 'html.parser')
|
33 |
+
|
34 |
+
text = soup.get_text(separator="\n\n")
|
35 |
+
print(text)
|
36 |
+
|
37 |
+
return
|
38 |
+
|
39 |
+
|
40 |
+
if __name__ == "__main__":
|
41 |
+
main()
|
examples/document_loaders/html_load/bs4_3.py
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/beautifulsoup4/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
import re
|
8 |
+
|
9 |
+
from bs4 import BeautifulSoup
|
10 |
+
import lxml
|
11 |
+
|
12 |
+
from project_settings import project_path
|
13 |
+
|
14 |
+
|
15 |
+
def get_args():
|
16 |
+
parser = argparse.ArgumentParser()
|
17 |
+
parser.add_argument(
|
18 |
+
"--filename",
|
19 |
+
# default=(project_path / "data/files/html/nxlink.html").as_posix(),
|
20 |
+
default=(project_path / "data/files/html/nxcloud.html").as_posix(),
|
21 |
+
type=str
|
22 |
+
)
|
23 |
+
args = parser.parse_args()
|
24 |
+
return args
|
25 |
+
|
26 |
+
|
27 |
+
def remove_script(html_doc: str):
|
28 |
+
pattern = "<script.*?</script>"
|
29 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
30 |
+
return html_doc
|
31 |
+
|
32 |
+
|
33 |
+
def remove_comment(html_doc: str):
|
34 |
+
pattern = "<!--.*?-->"
|
35 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
36 |
+
return html_doc
|
37 |
+
|
38 |
+
|
39 |
+
def remove_img(html_doc: str):
|
40 |
+
pattern = "<img.*?>"
|
41 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
42 |
+
return html_doc
|
43 |
+
|
44 |
+
|
45 |
+
def remove_no_script(html_doc: str):
|
46 |
+
pattern = "<noscript>.*?</noscript>"
|
47 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
48 |
+
return html_doc
|
49 |
+
|
50 |
+
|
51 |
+
def remove_style(html_doc: str):
|
52 |
+
remove_script_pattern = "<style.*?</style>"
|
53 |
+
html_doc = re.sub(remove_script_pattern, "", html_doc, flags=re.DOTALL)
|
54 |
+
return html_doc
|
55 |
+
|
56 |
+
|
57 |
+
def remove_class_property(html_doc: str):
|
58 |
+
pattern = " class=\".+?\""
|
59 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
60 |
+
return html_doc
|
61 |
+
|
62 |
+
|
63 |
+
def remove_id_property(html_doc: str):
|
64 |
+
pattern = " id=\".+?\""
|
65 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
66 |
+
return html_doc
|
67 |
+
|
68 |
+
|
69 |
+
def remove_onclick_property(html_doc: str):
|
70 |
+
pattern = " onclick=\".+?\""
|
71 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
72 |
+
return html_doc
|
73 |
+
|
74 |
+
|
75 |
+
def remove_style_property(html_doc: str):
|
76 |
+
pattern = " style=\".+?\""
|
77 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
78 |
+
pattern = " style='.+?'"
|
79 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
80 |
+
return html_doc
|
81 |
+
|
82 |
+
|
83 |
+
def remove_multiple_newlines(html_doc: str):
|
84 |
+
html_doc = re.sub(r"(\n\s*\n)+", "\n", html_doc, flags=re.DOTALL)
|
85 |
+
return html_doc
|
86 |
+
|
87 |
+
|
88 |
+
def replace_a(html_doc: str):
|
89 |
+
pattern = r"<a\b[^>]*>(.*?)</a>"
|
90 |
+
html_doc = re.sub(pattern, r"\1", html_doc, flags=re.DOTALL)
|
91 |
+
return html_doc
|
92 |
+
|
93 |
+
|
94 |
+
def replace_div(html_doc: str):
|
95 |
+
pattern = r"<div\b[^>]*>(.*?)</div>"
|
96 |
+
html_doc = re.sub(pattern, r"\1", html_doc, flags=re.DOTALL)
|
97 |
+
return html_doc
|
98 |
+
|
99 |
+
|
100 |
+
def main():
|
101 |
+
args = get_args()
|
102 |
+
|
103 |
+
with open(args.filename, "r", encoding="utf-8") as f:
|
104 |
+
html_doc = f.read()
|
105 |
+
|
106 |
+
soup = BeautifulSoup(html_doc, "html.parser")
|
107 |
+
html_doc = soup.prettify()
|
108 |
+
|
109 |
+
html_doc = remove_script(html_doc)
|
110 |
+
html_doc = remove_comment(html_doc)
|
111 |
+
html_doc = remove_img(html_doc)
|
112 |
+
html_doc = remove_no_script(html_doc)
|
113 |
+
html_doc = remove_style(html_doc)
|
114 |
+
|
115 |
+
html_doc = remove_class_property(html_doc)
|
116 |
+
html_doc = remove_id_property(html_doc)
|
117 |
+
html_doc = remove_onclick_property(html_doc)
|
118 |
+
html_doc = remove_style_property(html_doc)
|
119 |
+
|
120 |
+
html_doc = replace_a(html_doc)
|
121 |
+
html_doc = replace_div(html_doc)
|
122 |
+
|
123 |
+
html_doc = remove_multiple_newlines(html_doc)
|
124 |
+
|
125 |
+
# print(html_doc)
|
126 |
+
return
|
127 |
+
|
128 |
+
|
129 |
+
if __name__ == "__main__":
|
130 |
+
main()
|
examples/document_loaders/html_load/html_to_pdf.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
参考:
|
5 |
+
https://blog.csdn.net/weixin_39278265/article/details/118394553
|
6 |
+
https://stackoverflow.com/questions/23359083/how-to-convert-webpage-into-pdf-by-using-python
|
7 |
+
https://pypi.org/project/pdfkit/
|
8 |
+
|
9 |
+
安装 wkhtmltopdf
|
10 |
+
https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf
|
11 |
+
https://wkhtmltopdf.org/downloads.html
|
12 |
+
|
13 |
+
"""
|
14 |
+
import pdfkit
|
15 |
+
from pdfkit.configuration import Configuration
|
16 |
+
|
17 |
+
|
18 |
+
pdfkit.from_url(
|
19 |
+
"https://www.nxcloud.com/",
|
20 |
+
'out.pdf', configuration=Configuration(
|
21 |
+
wkhtmltopdf=r"D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe"
|
22 |
+
)
|
23 |
+
)
|
24 |
+
|
25 |
+
|
26 |
+
if __name__ == "__main__":
|
27 |
+
pass
|
examples/document_loaders/html_load/html_to_text_.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/html2text/
|
5 |
+
https://pypi.org/project/beautifulsoup4/
|
6 |
+
"""
|
7 |
+
import argparse
|
8 |
+
|
9 |
+
from bs4 import BeautifulSoup
|
10 |
+
import lxml
|
11 |
+
from html2text import HTML2Text
|
12 |
+
|
13 |
+
from project_settings import project_path
|
14 |
+
|
15 |
+
|
16 |
+
def get_args():
|
17 |
+
parser = argparse.ArgumentParser()
|
18 |
+
parser.add_argument(
|
19 |
+
"--filename",
|
20 |
+
# default=(project_path / "data/files/html/nxlink.html").as_posix(),
|
21 |
+
default=(project_path / "data/files/html/nxcloud.html").as_posix(),
|
22 |
+
type=str
|
23 |
+
)
|
24 |
+
args = parser.parse_args()
|
25 |
+
return args
|
26 |
+
|
27 |
+
|
28 |
+
def main():
|
29 |
+
args = get_args()
|
30 |
+
|
31 |
+
with open(args.filename, "r", encoding="utf-8") as f:
|
32 |
+
html_doc = f.read()
|
33 |
+
|
34 |
+
soup = BeautifulSoup(html_doc, 'html.parser')
|
35 |
+
|
36 |
+
converter = HTML2Text()
|
37 |
+
markdown_content = converter.handle(str(soup))
|
38 |
+
print(markdown_content)
|
39 |
+
|
40 |
+
return
|
41 |
+
|
42 |
+
|
43 |
+
if __name__ == "__main__":
|
44 |
+
main()
|
examples/document_loaders/html_load/lxml_.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/beautifulsoup4/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import lxml
|
9 |
+
from lxml import etree
|
10 |
+
|
11 |
+
from project_settings import project_path
|
12 |
+
|
13 |
+
|
14 |
+
def get_args():
|
15 |
+
parser = argparse.ArgumentParser()
|
16 |
+
parser.add_argument(
|
17 |
+
"--filename",
|
18 |
+
# default=(project_path / "data/files/html/nxlink.html").as_posix(),
|
19 |
+
default=(project_path / "data/files/html/nxcloud.html").as_posix(),
|
20 |
+
type=str
|
21 |
+
)
|
22 |
+
args = parser.parse_args()
|
23 |
+
return args
|
24 |
+
|
25 |
+
|
26 |
+
def main():
|
27 |
+
args = get_args()
|
28 |
+
|
29 |
+
with open(args.filename, "r", encoding="utf-8") as f:
|
30 |
+
html_doc = f.read()
|
31 |
+
|
32 |
+
tree = etree.HTML(html_doc)
|
33 |
+
root = tree.getroottree()
|
34 |
+
|
35 |
+
# 提取所有段落
|
36 |
+
for p in root.xpath('//p'):
|
37 |
+
print(p.text)
|
38 |
+
return
|
39 |
+
|
40 |
+
|
41 |
+
if __name__ == "__main__":
|
42 |
+
main()
|
examples/document_loaders/html_load/markdownify_.py
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/markdownify/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
import re
|
8 |
+
|
9 |
+
from bs4 import BeautifulSoup
|
10 |
+
from markdownify import markdownify as md
|
11 |
+
|
12 |
+
from project_settings import project_path
|
13 |
+
|
14 |
+
|
15 |
+
def get_args():
|
16 |
+
parser = argparse.ArgumentParser()
|
17 |
+
parser.add_argument(
|
18 |
+
"--filename",
|
19 |
+
# default=(project_path / "data/files/html/nxlink.html").as_posix(),
|
20 |
+
default=(project_path / "data/files/html/nxcloud.html").as_posix(),
|
21 |
+
type=str
|
22 |
+
)
|
23 |
+
args = parser.parse_args()
|
24 |
+
return args
|
25 |
+
|
26 |
+
|
27 |
+
def remove_script(html_doc: str):
|
28 |
+
pattern = "<script.*?</script>"
|
29 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
30 |
+
return html_doc
|
31 |
+
|
32 |
+
|
33 |
+
def remove_comment(html_doc: str):
|
34 |
+
pattern = "<!--.*?-->"
|
35 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
36 |
+
return html_doc
|
37 |
+
|
38 |
+
|
39 |
+
def remove_img(html_doc: str):
|
40 |
+
pattern = "<img.*?>"
|
41 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
42 |
+
return html_doc
|
43 |
+
|
44 |
+
|
45 |
+
def remove_no_script(html_doc: str):
|
46 |
+
pattern = "<noscript>.*?</noscript>"
|
47 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
48 |
+
return html_doc
|
49 |
+
|
50 |
+
|
51 |
+
def remove_style(html_doc: str):
|
52 |
+
remove_script_pattern = "<style.*?</style>"
|
53 |
+
html_doc = re.sub(remove_script_pattern, "", html_doc, flags=re.DOTALL)
|
54 |
+
return html_doc
|
55 |
+
|
56 |
+
|
57 |
+
def remove_class_property(html_doc: str):
|
58 |
+
pattern = " class=\".+?\""
|
59 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
60 |
+
return html_doc
|
61 |
+
|
62 |
+
|
63 |
+
def remove_id_property(html_doc: str):
|
64 |
+
pattern = " id=\".+?\""
|
65 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
66 |
+
return html_doc
|
67 |
+
|
68 |
+
|
69 |
+
def remove_onclick_property(html_doc: str):
|
70 |
+
pattern = " onclick=\".+?\""
|
71 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
72 |
+
return html_doc
|
73 |
+
|
74 |
+
|
75 |
+
def remove_style_property(html_doc: str):
|
76 |
+
pattern = " style=\".+?\""
|
77 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
78 |
+
pattern = " style='.+?'"
|
79 |
+
html_doc = re.sub(pattern, "", html_doc, flags=re.DOTALL)
|
80 |
+
return html_doc
|
81 |
+
|
82 |
+
|
83 |
+
def remove_multiple_newlines(html_doc: str):
|
84 |
+
html_doc = re.sub(r"(\n\s*\n)+", "\n", html_doc, flags=re.DOTALL)
|
85 |
+
return html_doc
|
86 |
+
|
87 |
+
|
88 |
+
def replace_a(html_doc: str):
|
89 |
+
pattern = r"<a\b[^>]*>(.*?)</a>"
|
90 |
+
html_doc = re.sub(pattern, r"\1", html_doc, flags=re.DOTALL)
|
91 |
+
return html_doc
|
92 |
+
|
93 |
+
|
94 |
+
def replace_br(html_doc: str):
|
95 |
+
pattern = r"(<br>|<br/>|<br />)"
|
96 |
+
html_doc = re.sub(pattern, "\n", html_doc, flags=re.DOTALL)
|
97 |
+
return html_doc
|
98 |
+
|
99 |
+
|
100 |
+
def replace_div(html_doc: str):
|
101 |
+
pattern = r"<div\b[^>]*>(.*?)</div>"
|
102 |
+
html_doc = re.sub(pattern, r"\1", html_doc, flags=re.DOTALL)
|
103 |
+
return html_doc
|
104 |
+
|
105 |
+
|
106 |
+
def main():
|
107 |
+
args = get_args()
|
108 |
+
|
109 |
+
with open(args.filename, "r", encoding="utf-8") as f:
|
110 |
+
html_doc = f.read()
|
111 |
+
|
112 |
+
soup = BeautifulSoup(html_doc, "html.parser")
|
113 |
+
html_doc = soup.prettify()
|
114 |
+
print(html_doc)
|
115 |
+
|
116 |
+
html_doc = remove_script(html_doc)
|
117 |
+
html_doc = remove_comment(html_doc)
|
118 |
+
html_doc = remove_img(html_doc)
|
119 |
+
html_doc = remove_no_script(html_doc)
|
120 |
+
html_doc = remove_style(html_doc)
|
121 |
+
|
122 |
+
html_doc = remove_class_property(html_doc)
|
123 |
+
html_doc = remove_id_property(html_doc)
|
124 |
+
html_doc = remove_onclick_property(html_doc)
|
125 |
+
html_doc = remove_style_property(html_doc)
|
126 |
+
|
127 |
+
html_doc = replace_a(html_doc)
|
128 |
+
html_doc = replace_br(html_doc)
|
129 |
+
html_doc = replace_div(html_doc)
|
130 |
+
|
131 |
+
html_doc = remove_multiple_newlines(html_doc)
|
132 |
+
|
133 |
+
markdown_doc = md(html_doc)
|
134 |
+
markdown_doc = remove_multiple_newlines(markdown_doc)
|
135 |
+
|
136 |
+
print(markdown_doc)
|
137 |
+
with open("temp.md", "w", encoding="utf-8") as f:
|
138 |
+
f.write(markdown_doc)
|
139 |
+
|
140 |
+
return
|
141 |
+
|
142 |
+
|
143 |
+
if __name__ == "__main__":
|
144 |
+
main()
|
examples/document_loaders/html_load/selenium_.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://selenium-python-zh.readthedocs.io/en/latest/getting-started.html
|
5 |
+
https://selenium-python.readthedocs.io/
|
6 |
+
|
7 |
+
https://sites.google.com/chromium.org/driver/
|
8 |
+
|
9 |
+
"""
|
10 |
+
from selenium import webdriver
|
11 |
+
from selenium.webdriver.chrome.service import Service
|
12 |
+
from webdriver_manager.chrome import ChromeDriverManager, DriverCacheManager
|
13 |
+
from bs4 import BeautifulSoup
|
14 |
+
|
15 |
+
from project_settings import project_path
|
16 |
+
|
17 |
+
|
18 |
+
chrome_driver_manager = ChromeDriverManager(
|
19 |
+
cache_manager=DriverCacheManager(
|
20 |
+
root_dir=(project_path / "data").as_posix()
|
21 |
+
)
|
22 |
+
)
|
23 |
+
driver_path = chrome_driver_manager.install()
|
24 |
+
print(f"driver_path: {driver_path}")
|
25 |
+
|
26 |
+
driver = webdriver.Chrome(
|
27 |
+
service=Service(driver_path=driver_path),
|
28 |
+
)
|
29 |
+
|
30 |
+
driver.get("http://www.python.org")
|
31 |
+
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
|
32 |
+
|
33 |
+
html_doc = driver.page_source
|
34 |
+
driver.quit()
|
35 |
+
|
36 |
+
soup = BeautifulSoup(html_doc, "html.parser")
|
37 |
+
|
38 |
+
|
39 |
+
if __name__ == "__main__":
|
40 |
+
pass
|
examples/document_loaders/pdf_load/aspose_words.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://products.aspose.com/words/python-net/merge/pdf-to-markdown/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import aspose.words as aw
|
9 |
+
|
10 |
+
from project_settings import project_path
|
11 |
+
|
12 |
+
|
13 |
+
def get_args():
|
14 |
+
parser = argparse.ArgumentParser()
|
15 |
+
parser.add_argument(
|
16 |
+
"--filename",
|
17 |
+
default=(project_path / "data/files/pdf/2024.naacl-long.35.pdf").as_posix(),
|
18 |
+
type=str
|
19 |
+
)
|
20 |
+
args = parser.parse_args()
|
21 |
+
return args
|
22 |
+
|
23 |
+
|
24 |
+
def main():
|
25 |
+
args = get_args()
|
26 |
+
|
27 |
+
output = aw.Document(args.filename)
|
28 |
+
output.save("Output.md")
|
29 |
+
return
|
30 |
+
|
31 |
+
|
32 |
+
if __name__ == "__main__":
|
33 |
+
main()
|
examples/document_loaders/pdf_load/pdf_to_markdown.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/pdf-to-markdown/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import PyPDF2 as pypdf2
|
9 |
+
from PyPDF2 import PdfReader
|
10 |
+
|
11 |
+
from project_settings import project_path
|
12 |
+
|
13 |
+
|
14 |
+
def get_args():
|
15 |
+
parser = argparse.ArgumentParser()
|
16 |
+
parser.add_argument(
|
17 |
+
"--filename",
|
18 |
+
default=(project_path / "data/files/pdf/2024.naacl-long.35.pdf").as_posix(),
|
19 |
+
type=str
|
20 |
+
)
|
21 |
+
args = parser.parse_args()
|
22 |
+
return args
|
23 |
+
|
24 |
+
|
25 |
+
def main():
|
26 |
+
args = get_args()
|
27 |
+
|
28 |
+
reader = pypdf2.PdfReader(args.filename)
|
29 |
+
print(f"pages count: {len(reader.pages)}")
|
30 |
+
|
31 |
+
for page in reader.pages:
|
32 |
+
print(page.extract_text())
|
33 |
+
print("-" * 150)
|
34 |
+
|
35 |
+
return
|
36 |
+
|
37 |
+
|
38 |
+
if __name__ == "__main__":
|
39 |
+
main()
|
examples/document_loaders/pdf_load/pdfminer_.py
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/pdfminer/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
from pdfminer.high_level import extract_text
|
9 |
+
from pdfminer.pdfparser import PDFParser
|
10 |
+
from pdfminer.pdfdocument import PDFDocument
|
11 |
+
from pdfminer.pdfpage import PDFPage
|
12 |
+
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
|
13 |
+
from pdfminer.pdfdevice import PDFDevice
|
14 |
+
from pdfminer.layout import LAParams
|
15 |
+
from pdfminer.converter import PDFPageAggregator
|
16 |
+
from pdfminer.layout import LTTextBox
|
17 |
+
|
18 |
+
from project_settings import project_path
|
19 |
+
|
20 |
+
|
21 |
+
def get_args():
|
22 |
+
parser = argparse.ArgumentParser()
|
23 |
+
parser.add_argument(
|
24 |
+
"--filename",
|
25 |
+
default=(project_path / "data/files/pdf/2024.naacl-long.35.pdf").as_posix(),
|
26 |
+
type=str
|
27 |
+
)
|
28 |
+
args = parser.parse_args()
|
29 |
+
return args
|
30 |
+
|
31 |
+
|
32 |
+
def main():
|
33 |
+
args = get_args()
|
34 |
+
|
35 |
+
# text = extract_text(args.filename)
|
36 |
+
# print(text)
|
37 |
+
|
38 |
+
# with open(args.filename, "rb") as f:
|
39 |
+
# parser = PDFParser(f)
|
40 |
+
#
|
41 |
+
# document = PDFDocument(parser)
|
42 |
+
# if not document.is_extractable:
|
43 |
+
# raise AssertionError
|
44 |
+
#
|
45 |
+
# manager = PDFResourceManager()
|
46 |
+
#
|
47 |
+
# params = LAParams()
|
48 |
+
# device = PDFPageAggregator(manager, laparams=params)
|
49 |
+
#
|
50 |
+
# interpreter = PDFPageInterpreter(manager, device)
|
51 |
+
#
|
52 |
+
# for page in PDFPage.create_pages(document):
|
53 |
+
# interpreter.process_page(page)
|
54 |
+
#
|
55 |
+
# layout = device.get_result()
|
56 |
+
# for obj in layout:
|
57 |
+
# print(obj)
|
58 |
+
# if isinstance(obj, LTTextBox):
|
59 |
+
# print(obj.get_text())
|
60 |
+
|
61 |
+
with open(args.filename, "rb") as f:
|
62 |
+
pages = PDFPage.get_pages(f)
|
63 |
+
for i, _ in enumerate(pages):
|
64 |
+
text = extract_text(f, page_numbers=[i])
|
65 |
+
# metadata = {"source": blob.source, "page": str(i)} # type: ignore[attr-defined]
|
66 |
+
print(text)
|
67 |
+
# print(metadata)
|
68 |
+
return
|
69 |
+
|
70 |
+
|
71 |
+
if __name__ == "__main__":
|
72 |
+
main()
|
examples/document_loaders/pdf_load/pymupdf4llm_.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pymupdf.readthedocs.io/en/latest/pymupdf4llm/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import pymupdf4llm
|
9 |
+
|
10 |
+
from project_settings import project_path
|
11 |
+
|
12 |
+
|
13 |
+
def get_args():
|
14 |
+
parser = argparse.ArgumentParser()
|
15 |
+
parser.add_argument(
|
16 |
+
"--filename",
|
17 |
+
default=(project_path / "data/files/pdf/2024.naacl-long.35.pdf").as_posix(),
|
18 |
+
type=str
|
19 |
+
)
|
20 |
+
args = parser.parse_args()
|
21 |
+
return args
|
22 |
+
|
23 |
+
|
24 |
+
def main():
|
25 |
+
args = get_args()
|
26 |
+
|
27 |
+
md_text = pymupdf4llm.to_markdown(args.filename)
|
28 |
+
print(md_text)
|
29 |
+
|
30 |
+
return
|
31 |
+
|
32 |
+
|
33 |
+
if __name__ == "__main__":
|
34 |
+
main()
|
examples/document_loaders/pdf_load/pypdf2_.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/pypdf/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import PyPDF2 as pypdf2
|
9 |
+
from PyPDF2 import PdfReader
|
10 |
+
|
11 |
+
from project_settings import project_path
|
12 |
+
|
13 |
+
|
14 |
+
def get_args():
|
15 |
+
parser = argparse.ArgumentParser()
|
16 |
+
parser.add_argument(
|
17 |
+
"--filename",
|
18 |
+
default=(project_path / "data/files/pdf/2024.naacl-long.35.pdf").as_posix(),
|
19 |
+
type=str
|
20 |
+
)
|
21 |
+
args = parser.parse_args()
|
22 |
+
return args
|
23 |
+
|
24 |
+
|
25 |
+
def main():
|
26 |
+
args = get_args()
|
27 |
+
|
28 |
+
reader = pypdf2.PdfReader(args.filename)
|
29 |
+
print(f"pages count: {len(reader.pages)}")
|
30 |
+
|
31 |
+
for page in reader.pages:
|
32 |
+
print(page.extract_text())
|
33 |
+
print("-" * 150)
|
34 |
+
|
35 |
+
return
|
36 |
+
|
37 |
+
|
38 |
+
if __name__ == "__main__":
|
39 |
+
main()
|
examples/document_loaders/pdf_load/pypdf_.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://pypi.org/project/pypdf/
|
5 |
+
"""
|
6 |
+
import argparse
|
7 |
+
|
8 |
+
import pypdf
|
9 |
+
|
10 |
+
from project_settings import project_path
|
11 |
+
|
12 |
+
|
13 |
+
def get_args():
|
14 |
+
parser = argparse.ArgumentParser()
|
15 |
+
parser.add_argument(
|
16 |
+
"--filename",
|
17 |
+
# default=(project_path / "data/files/pdf/2024.naacl-long.35.pdf").as_posix(),
|
18 |
+
# default=(project_path / "data/files/pdf/临时救助工作应知应会知识.pdf").as_posix(),
|
19 |
+
default=(project_path / "data/unstructured_eval/pdf/麦肯锡2023年AI现状_生成式AI的爆发之年.pdf").as_posix(),
|
20 |
+
type=str
|
21 |
+
)
|
22 |
+
args = parser.parse_args()
|
23 |
+
return args
|
24 |
+
|
25 |
+
|
26 |
+
def main():
|
27 |
+
args = get_args()
|
28 |
+
|
29 |
+
reader = pypdf.PdfReader(args.filename)
|
30 |
+
# print(f"pages count: {len(reader.pages)}\n")
|
31 |
+
|
32 |
+
for page in reader.pages:
|
33 |
+
print(page.extract_text())
|
34 |
+
# print("-" * 150)
|
35 |
+
|
36 |
+
return
|
37 |
+
|
38 |
+
|
39 |
+
if __name__ == "__main__":
|
40 |
+
main()
|
examples/document_loaders/ppt_load/pptx2md_.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://github.com/ptsefton/pptx_to_md
|
5 |
+
"""
|
6 |
+
import pptx2md
|
7 |
+
|
8 |
+
|
9 |
+
if __name__ == "__main__":
|
10 |
+
pass
|
examples/document_loaders/ppt_load/pptx_.py
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
from typing import Iterator
|
5 |
+
|
6 |
+
import pptx.slide
|
7 |
+
import pptx.shapes
|
8 |
+
from pptx import Presentation
|
9 |
+
from pptx.shapes.shapetree import _BaseGroupShapes, Shape
|
10 |
+
from pptx.shapes.group import GroupShape
|
11 |
+
from pptx.shapes.base import BaseShape
|
12 |
+
|
13 |
+
from langchain_community import document_loaders
|
14 |
+
|
15 |
+
from project_settings import project_path
|
16 |
+
|
17 |
+
|
18 |
+
def get_args():
|
19 |
+
parser = argparse.ArgumentParser()
|
20 |
+
parser.add_argument(
|
21 |
+
"--filename",
|
22 |
+
# default=(project_path / "data/files/doc/公司开票信息:深圳牛信.docx").as_posix(),
|
23 |
+
default=(project_path / "data/files/ppt/钉钉基础使用手册.pptx").as_posix(),
|
24 |
+
type=str
|
25 |
+
)
|
26 |
+
args = parser.parse_args()
|
27 |
+
return args
|
28 |
+
|
29 |
+
|
30 |
+
def get_slide_notes(slide: pptx.slide.Slide):
|
31 |
+
if not slide.has_notes_slide:
|
32 |
+
return None
|
33 |
+
notes_slide = slide.notes_slide
|
34 |
+
notes_text_frame = notes_slide.notes_text_frame
|
35 |
+
|
36 |
+
if not notes_text_frame:
|
37 |
+
return None
|
38 |
+
notes_text = notes_text_frame.text.strip()
|
39 |
+
|
40 |
+
if not notes_text:
|
41 |
+
return None
|
42 |
+
|
43 |
+
return notes_text
|
44 |
+
|
45 |
+
|
46 |
+
def order_shapes(slide: pptx.slide.Slide):
|
47 |
+
def iter_shapes(shapes: _BaseGroupShapes) -> Iterator[BaseShape]:
|
48 |
+
for shape in shapes:
|
49 |
+
if isinstance(shape, GroupShape):
|
50 |
+
yield from iter_shapes(shape.shapes)
|
51 |
+
else:
|
52 |
+
yield shape
|
53 |
+
|
54 |
+
def sort_key(shape: BaseShape) -> tuple[int, int]:
|
55 |
+
return shape.top or 0, shape.left or 0
|
56 |
+
|
57 |
+
ordered_shapes = sorted(iter_shapes(slide.shapes), key=sort_key)
|
58 |
+
return slide.shapes.title, ordered_shapes
|
59 |
+
|
60 |
+
|
61 |
+
def main():
|
62 |
+
args = get_args()
|
63 |
+
|
64 |
+
presentation = Presentation(args.filename)
|
65 |
+
|
66 |
+
for slide in presentation.slides:
|
67 |
+
print("-------------------------- slide --------------------------")
|
68 |
+
slide_notes = get_slide_notes(slide)
|
69 |
+
|
70 |
+
title_shape, ordered_shapes = order_shapes(slide)
|
71 |
+
for shape in ordered_shapes:
|
72 |
+
if shape.has_text_frame:
|
73 |
+
assert isinstance(shape, Shape)
|
74 |
+
|
75 |
+
print(f"shape.has_text_frame")
|
76 |
+
for paragraph in shape.text_frame.paragraphs:
|
77 |
+
text = paragraph.text
|
78 |
+
if text.strip() == "":
|
79 |
+
continue
|
80 |
+
|
81 |
+
if not hasattr(shape, "text"):
|
82 |
+
continue
|
83 |
+
|
84 |
+
text = shape.text.strip()
|
85 |
+
if len(text) == 0:
|
86 |
+
continue
|
87 |
+
print("------------- shape -------------")
|
88 |
+
print(shape.text)
|
89 |
+
|
90 |
+
return
|
91 |
+
|
92 |
+
|
93 |
+
if __name__ == "__main__":
|
94 |
+
main()
|
examples/document_loaders/ppt_load/unstructured_pptx_.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import argparse
|
4 |
+
from typing import Iterator
|
5 |
+
|
6 |
+
import unstructured
|
7 |
+
|
8 |
+
from unstructured.partition.pptx import partition_pptx
|
9 |
+
|
10 |
+
from project_settings import project_path
|
11 |
+
|
12 |
+
|
13 |
+
def get_args():
|
14 |
+
parser = argparse.ArgumentParser()
|
15 |
+
parser.add_argument(
|
16 |
+
"--filename",
|
17 |
+
# default=(project_path / "data/files/doc/公司开票信息:深圳牛信.docx").as_posix(),
|
18 |
+
default=(project_path / "data/files/ppt/钉钉基础使用手册.pptx").as_posix(),
|
19 |
+
type=str
|
20 |
+
)
|
21 |
+
args = parser.parse_args()
|
22 |
+
return args
|
23 |
+
|
24 |
+
|
25 |
+
def main():
|
26 |
+
args = get_args()
|
27 |
+
|
28 |
+
elements = partition_pptx(
|
29 |
+
filename=args.filename,
|
30 |
+
)
|
31 |
+
for element in elements:
|
32 |
+
print(element)
|
33 |
+
|
34 |
+
return
|
35 |
+
|
36 |
+
|
37 |
+
if __name__ == "__main__":
|
38 |
+
main()
|
examples/sentence_similarity.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import difflib
|
4 |
+
from typing import List, Tuple
|
5 |
+
|
6 |
+
import editdistance
|
7 |
+
|
8 |
+
|
9 |
+
class ChunkSimilarity(object):
|
10 |
+
def edit_distance(self, chunk: str, match_content: str) -> List[Tuple[str, float, str]]:
|
11 |
+
edit_distance = editdistance.distance(chunk, match_content)
|
12 |
+
|
13 |
+
chunk_length = len(chunk)
|
14 |
+
content_length = len(match_content)
|
15 |
+
|
16 |
+
normalized_edit_distance = edit_distance / (chunk_length + content_length)
|
17 |
+
normalized_edit_distance2 = 2 * edit_distance / (chunk_length + content_length)
|
18 |
+
|
19 |
+
result = [
|
20 |
+
("edit_distance", edit_distance, ""),
|
21 |
+
(
|
22 |
+
"ed_score", round(1 - normalized_edit_distance, 4),
|
23 |
+
"1 - d / (l1 + l2)"
|
24 |
+
),
|
25 |
+
(
|
26 |
+
"ed_score2", round(1 - normalized_edit_distance2, 4),
|
27 |
+
"1 - 2*d / (l1 + l2)"
|
28 |
+
),
|
29 |
+
]
|
30 |
+
return result
|
31 |
+
|
32 |
+
def seq_match(self, chunk: str, match_content: str) -> List[Tuple[str, str, str]]:
|
33 |
+
seq_match = difflib.SequenceMatcher()
|
34 |
+
seq_match.set_seqs(chunk, match_content)
|
35 |
+
score = seq_match.ratio()
|
36 |
+
|
37 |
+
result = [
|
38 |
+
("seq_match", round(score, 4), "(2.0*M / T) similar to edit_distance"),
|
39 |
+
]
|
40 |
+
return result
|
41 |
+
|
42 |
+
def similar(self, chunk: str, match_content: str):
|
43 |
+
result = [
|
44 |
+
("metric", "score", "note")
|
45 |
+
]
|
46 |
+
scores = self.edit_distance(chunk, match_content)
|
47 |
+
result.extend(scores)
|
48 |
+
scores = self.seq_match(chunk, match_content)
|
49 |
+
result.extend(scores)
|
50 |
+
|
51 |
+
return result
|
52 |
+
|
53 |
+
|
54 |
+
CHUNK_TRUE = """
|
55 |
+
2023年人工智能发展现状:生成式AI的突破之年
|
56 |
+
"""
|
57 |
+
|
58 |
+
|
59 |
+
CHUNK_EDIT = """
|
60 |
+
Among these PEFT methods, the reparameterization-based method low-rank adaptation (LoRA) (Hu et al.,2021) is considered one of the most efficient and effective methods at present.
|
61 |
+
LoRA is especially popular after open-sourced LLMs become ubiquitous (Dettmers et al., 2023).
|
62 |
+
LoRA assumes that the change of the model’s parameters for adaptation is intrinsically low-dimensional and performs adaptation by optimizing the matrix obtained from low-rank decomposition.
|
63 |
+
Since it is in the form of weight matrix reparameterization, LoRA parameters can be merged with the original LLMs and cause no forward propagation latency.
|
64 |
+
"""
|
65 |
+
|
66 |
+
|
67 |
+
def main():
|
68 |
+
|
69 |
+
chunk_similarity = ChunkSimilarity()
|
70 |
+
scores = chunk_similarity.similar(
|
71 |
+
CHUNK_TRUE,
|
72 |
+
CHUNK_EDIT
|
73 |
+
)
|
74 |
+
for score in scores:
|
75 |
+
metric, score, _ = score
|
76 |
+
print(f"{metric}: {score}")
|
77 |
+
return
|
78 |
+
|
79 |
+
|
80 |
+
if __name__ == "__main__":
|
81 |
+
main()
|
examples/unstructured_/unstructured_.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
https://unstructured.io/
|
5 |
+
|
6 |
+
https://github.com/Unstructured-IO/unstructured
|
7 |
+
"""
|
8 |
+
import unstructured
|
9 |
+
import unstructured_inference
|
10 |
+
from unstructured.partition.pdf import partition_pdf
|
11 |
+
|
12 |
+
|
13 |
+
elements = partition_pdf(filename=r"E:\Users\tianx\intelli-zen\document_loaders\data\files\pdf\2024.naacl-long.35.pdf")
|
14 |
+
for element in elements:
|
15 |
+
print(element)
|
16 |
+
|
17 |
+
|
18 |
+
if __name__ == "__main__":
|
19 |
+
pass
|
examples_chunk_similar.json
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
[
|
3 |
+
"Proceedings of the 2024 Conference of the North American Chapter of the Association for Computational Linguistics:\nHuman Language Technologies (Volume 1: Long Papers) , pages 622–641\nJune 16-21, 2024 ©2024 Association for Computational Linguistics\nALoRA: Allocating Low-Rank Adaptation for Fine-tuning\nLarge Language Models\nZequan Liu1⋆Jiawen Lyn2∗Wei Zhu3†Xing Tian4Yvette Graham2\n1RWTH Aachen University, Aachen, Germany\n2Trinity College Dublin, Dublin, Ireland\n3East China Normal University, Shanghai, China\n4Niuxin Network Technology Co., Ltd.\nAbstract\nParameter-efficient fine-tuning (PEFT) is\nwidely studied for its effectiveness and effi-\nciency in the era of large language models.\nLow-rank adaptation (LoRA) has demonstrated\ncommendable performance as a popular and\nrepresentative method. However, it is imple-\nmented with a fixed intrinsic rank that might not\nbe the ideal setting for the downstream tasks.\nRecognizing the need for more flexible down-\nstream task adaptation, we extend the methodol-\nogy of LoRA to an innovative approach we call\nallocating low-rank adaptation (ALoRA) that\nenables dynamic adjustments to the intrinsic\nrank during the adaptation process. First, we\npropose a novel method, AB-LoRA, that can ef-\nfectively estimate the importance score of each\nLoRA rank. Second, guided by AB-LoRA, we\ngradually prune abundant and negatively im-\npacting LoRA ranks and allocate the pruned\nLoRA budgets to important Transformer mod-\nules needing higher ranks. We have conducted\nexperiments on various tasks, and the exper-\nimental results demonstrate that our ALoRA\nmethod can outperform the recent baselines\nwith comparable tunable parameters.\n1 Introduction\nLarge language models (LLMs) have been\nemerging and achieving state-of-the-art (SOTA) re-\nsults not only on a variety of natural language pro-\ncessing tasks (Qin et al., 2023; Zhu et al., 2023; Zhu\net al., 2023a,b, 2021a; Li et al., 2023b; Zhu et al.,\n2023c; Zhang et al., 2023a; Zhu et al., 2023e; Guo\net al., 2021b; Zhu et al., 2021b; Zheng et al., 2023;\nSun et al., 2020; Zhang et al., 2023d,e; Wang et al.,\n2023; Zhu et al., 2019a), but also many challeng-\ning evaluation tasks (Huang et al., 2023; Li et al.,\n2023a; Cui et al., 2023) like question answering in\nspecial domains, reasoning, math, safety, instruc-\ntion following. Despite LLMs becoming general\n∗Equal contributions.\n†Corresponding author: [email protected] solvers, fine-tuning still plays a vital role in\nefficient LLM inference and controlling the style\nof the LLMs’ generated contents.1Fine-tuning\nsuch large models by full parameters is prohibitive\nsince it requires a large amount of GPU memory\nand computations. Thus, parameter-efficient fine-\ntuning (PEFT) (Zhang et al., 2023f; Zhao et al.,\n2023; Ding et al., 2022) has raised much attention\nin the research field since in PEFT, the tunable\nparameters are often less than 1% of the LLMs\nand the computation costs will be significantly de-\ncreased.\nMany PEFT methods have been validated to be\neffective across various models and tasks, often\nyielding comparable results with full-parameter\nfine-tuning (He et al., 2021; Zhu and Tan, 2023;\nZhang et al., 2023f; Ding et al., 2022). Among\nthese PEFT methods, the reparameterization-based\nmethod low-rank adaptation (LoRA) (Hu et al.,\n2021) is considered one of the most efficient and\neffective methods at present. LoRA is especially\npopular after open-sourced LLMs become ubiqui-\ntous (Dettmers et al., 2023). LoRA assumes that\nthe change of the model’s parameters for adapta-\ntion is intrinsically low-dimensional and performs\nadaptation by optimizing the matrix obtained from\nlow-rank decomposition. Since it is in the form\nof weight matrix reparameterization, LoRA param-\neters can be merged with the original LLMs and\ncause no forward propagation latency.\nAlthough LoRA is effective and can bring stable\nperformance with the original setting in Hu et al.\n(2021), how to fully exploit its potential for down-\nstream tasks still needs to be determined. First,\nhow to determine the intrinsic rank for each model\nweight in the Transformer block is still unclear.\nMoreover, is it reasonable to set the same LoRA\nrank number for adapting the query, key, and value\n1Recently, OpenAI also released the fine-tuning API for\nGPT-3.5-turbo. See blog post: https://openai.com/blog/\ngpt-3-5-turbo-fine-tuning-and-api-updates .622",
|
4 |
+
"ALoRA: Allocating Low-Rank Adaptation for Fine-tuning Large Language Models\nZequan Liu1⋆ Jiawen Lyn2∗ Wei Zhu3† Xing Tian4 Yvette Graham2\n1 RWTH Aachen University, Aachen, Germany\n2 Trinity College Dublin, Dublin, Ireland\n3 East China Normal University, Shanghai, China\n4 Niuxin Network Technology Co., Ltd.",
|
5 |
+
1.6
|
6 |
+
],
|
7 |
+
[
|
8 |
+
"Proceedings of the 2024 Conference of the North American Chapter of the Association for Computational Linguistics:\nHuman Language Technologies (Volume 1: Long Papers) , pages 622–641\nJune 16-21, 2024 ©2024 Association for Computational Linguistics\nALoRA: Allocating Low-Rank Adaptation for Fine-tuning\nLarge Language Models\nZequan Liu1⋆Jiawen Lyn2∗Wei Zhu3†Xing Tian4Yvette Graham2\n1RWTH Aachen University, Aachen, Germany\n2Trinity College Dublin, Dublin, Ireland\n3East China Normal University, Shanghai, China\n4Niuxin Network Technology Co., Ltd.\nAbstract\nParameter-efficient fine-tuning (PEFT) is\nwidely studied for its effectiveness and effi-\nciency in the era of large language models.\nLow-rank adaptation (LoRA) has demonstrated\ncommendable performance as a popular and\nrepresentative method. However, it is imple-\nmented with a fixed intrinsic rank that might not\nbe the ideal setting for the downstream tasks.\nRecognizing the need for more flexible down-\nstream task adaptation, we extend the methodol-\nogy of LoRA to an innovative approach we call\nallocating low-rank adaptation (ALoRA) that\nenables dynamic adjustments to the intrinsic\nrank during the adaptation process. First, we\npropose a novel method, AB-LoRA, that can ef-\nfectively estimate the importance score of each\nLoRA rank. Second, guided by AB-LoRA, we\ngradually prune abundant and negatively im-\npacting LoRA ranks and allocate the pruned\nLoRA budgets to important Transformer mod-\nules needing higher ranks. We have conducted\nexperiments on various tasks, and the exper-\nimental results demonstrate that our ALoRA\nmethod can outperform the recent baselines\nwith comparable tunable parameters.\n1 Introduction\nLarge language models (LLMs) have been\nemerging and achieving state-of-the-art (SOTA) re-\nsults not only on a variety of natural language pro-\ncessing tasks (Qin et al., 2023; Zhu et al., 2023; Zhu\net al., 2023a,b, 2021a; Li et al., 2023b; Zhu et al.,\n2023c; Zhang et al., 2023a; Zhu et al., 2023e; Guo\net al., 2021b; Zhu et al., 2021b; Zheng et al., 2023;\nSun et al., 2020; Zhang et al., 2023d,e; Wang et al.,\n2023; Zhu et al., 2019a), but also many challeng-\ning evaluation tasks (Huang et al., 2023; Li et al.,\n2023a; Cui et al., 2023) like question answering in\nspecial domains, reasoning, math, safety, instruc-\ntion following. Despite LLMs becoming general\n∗Equal contributions.\n†Corresponding author: [email protected] solvers, fine-tuning still plays a vital role in\nefficient LLM inference and controlling the style\nof the LLMs’ generated contents.1Fine-tuning\nsuch large models by full parameters is prohibitive\nsince it requires a large amount of GPU memory\nand computations. Thus, parameter-efficient fine-\ntuning (PEFT) (Zhang et al., 2023f; Zhao et al.,\n2023; Ding et al., 2022) has raised much attention\nin the research field since in PEFT, the tunable\nparameters are often less than 1% of the LLMs\nand the computation costs will be significantly de-\ncreased.\nMany PEFT methods have been validated to be\neffective across various models and tasks, often\nyielding comparable results with full-parameter\nfine-tuning (He et al., 2021; Zhu and Tan, 2023;\nZhang et al., 2023f; Ding et al., 2022). Among\nthese PEFT methods, the reparameterization-based\nmethod low-rank adaptation (LoRA) (Hu et al.,\n2021) is considered one of the most efficient and\neffective methods at present. LoRA is especially\npopular after open-sourced LLMs become ubiqui-\ntous (Dettmers et al., 2023). LoRA assumes that\nthe change of the model’s parameters for adapta-\ntion is intrinsically low-dimensional and performs\nadaptation by optimizing the matrix obtained from\nlow-rank decomposition. Since it is in the form\nof weight matrix reparameterization, LoRA param-\neters can be merged with the original LLMs and\ncause no forward propagation latency.\nAlthough LoRA is effective and can bring stable\nperformance with the original setting in Hu et al.\n(2021), how to fully exploit its potential for down-\nstream tasks still needs to be determined. First,\nhow to determine the intrinsic rank for each model\nweight in the Transformer block is still unclear.\nMoreover, is it reasonable to set the same LoRA\nrank number for adapting the query, key, and value\n1Recently, OpenAI also released the fine-tuning API for\nGPT-3.5-turbo. See blog post: https://openai.com/blog/\ngpt-3-5-turbo-fine-tuning-and-api-updates .622",
|
9 |
+
"Among these PEFT methods, the reparameterization-based method low-rank adaptation (LoRA) (Hu et al.,2021) is considered one of the most efficient and effective methods at present. \nLoRA is especially popular after open-sourced LLMs become ubiquitous (Dettmers et al., 2023). \nLoRA assumes that the change of the model’s parameters for adaptation is intrinsically low-dimensional and performs adaptation by optimizing the matrix obtained from low-rank decomposition. \nSince it is in the form of weight matrix reparameterization, LoRA parameters can be merged with the original LLMs and cause no forward propagation latency.",
|
10 |
+
1.6
|
11 |
+
],
|
12 |
+
[
|
13 |
+
"Proceedings of the 2024 Conference of the North American Chapter of the Association for Computational Linguistics:\nHuman Language Technologies (Volume 1: Long Papers) , pages 622–641\nJune 16-21, 2024 ©2024 Association for Computational Linguistics\nALoRA: Allocating Low-Rank Adaptation for Fine-tuning\nLarge Language Models\nZequan Liu1⋆Jiawen Lyn2∗Wei Zhu3†Xing Tian4Yvette Graham2\n1RWTH Aachen University, Aachen, Germany\n2Trinity College Dublin, Dublin, Ireland\n3East China Normal University, Shanghai, China\n4Niuxin Network Technology Co., Ltd.\nAbstract\nParameter-efficient fine-tuning (PEFT) is\nwidely studied for its effectiveness and effi-\nciency in the era of large language models.\nLow-rank adaptation (LoRA) has demonstrated\ncommendable performance as a popular and\nrepresentative method. However, it is imple-\nmented with a fixed intrinsic rank that might not\nbe the ideal setting for the downstream tasks.\nRecognizing the need for more flexible down-\nstream task adaptation, we extend the methodol-\nogy of LoRA to an innovative approach we call\nallocating low-rank adaptation (ALoRA) that\nenables dynamic adjustments to the intrinsic\nrank during the adaptation process. First, we\npropose a novel method, AB-LoRA, that can ef-\nfectively estimate the importance score of each\nLoRA rank. Second, guided by AB-LoRA, we\ngradually prune abundant and negatively im-\npacting LoRA ranks and allocate the pruned\nLoRA budgets to important Transformer mod-\nules needing higher ranks. We have conducted\nexperiments on various tasks, and the exper-\nimental results demonstrate that our ALoRA\nmethod can outperform the recent baselines\nwith comparable tunable parameters.\n1 Introduction\nLarge language models (LLMs) have been\nemerging and achieving state-of-the-art (SOTA) re-\nsults not only on a variety of natural language pro-\ncessing tasks (Qin et al., 2023; Zhu et al., 2023; Zhu\net al., 2023a,b, 2021a; Li et al., 2023b; Zhu et al.,\n2023c; Zhang et al., 2023a; Zhu et al., 2023e; Guo\net al., 2021b; Zhu et al., 2021b; Zheng et al., 2023;\nSun et al., 2020; Zhang et al., 2023d,e; Wang et al.,\n2023; Zhu et al., 2019a), but also many challeng-\ning evaluation tasks (Huang et al., 2023; Li et al.,\n2023a; Cui et al., 2023) like question answering in\nspecial domains, reasoning, math, safety, instruc-\ntion following. Despite LLMs becoming general\n∗Equal contributions.\n†Corresponding author: [email protected] solvers, fine-tuning still plays a vital role in\nefficient LLM inference and controlling the style\nof the LLMs’ generated contents.1Fine-tuning\nsuch large models by full parameters is prohibitive\nsince it requires a large amount of GPU memory\nand computations. Thus, parameter-efficient fine-\ntuning (PEFT) (Zhang et al., 2023f; Zhao et al.,\n2023; Ding et al., 2022) has raised much attention\nin the research field since in PEFT, the tunable\nparameters are often less than 1% of the LLMs\nand the computation costs will be significantly de-\ncreased.\nMany PEFT methods have been validated to be\neffective across various models and tasks, often\nyielding comparable results with full-parameter\nfine-tuning (He et al., 2021; Zhu and Tan, 2023;\nZhang et al., 2023f; Ding et al., 2022). Among\nthese PEFT methods, the reparameterization-based\nmethod low-rank adaptation (LoRA) (Hu et al.,\n2021) is considered one of the most efficient and\neffective methods at present. LoRA is especially\npopular after open-sourced LLMs become ubiqui-\ntous (Dettmers et al., 2023). LoRA assumes that\nthe change of the model’s parameters for adapta-\ntion is intrinsically low-dimensional and performs\nadaptation by optimizing the matrix obtained from\nlow-rank decomposition. Since it is in the form\nof weight matrix reparameterization, LoRA param-\neters can be merged with the original LLMs and\ncause no forward propagation latency.\nAlthough LoRA is effective and can bring stable\nperformance with the original setting in Hu et al.\n(2021), how to fully exploit its potential for down-\nstream tasks still needs to be determined. First,\nhow to determine the intrinsic rank for each model\nweight in the Transformer block is still unclear.\nMoreover, is it reasonable to set the same LoRA\nrank number for adapting the query, key, and value\n1Recently, OpenAI also released the fine-tuning API for\nGPT-3.5-turbo. See blog post: https://openai.com/blog/\ngpt-3-5-turbo-fine-tuning-and-api-updates .622",
|
14 |
+
"Recognizing the need for more flexible down-stream task adaptation, we extend the methodology of LoRA to an innovative approach we call\nallocating low-rank adaptation (ALoRA) that enables dynamic adjustments to the intrinsic rank during the adaptation process. \n\nFirst, we propose a novel method, AB-LoRA, that can effectively estimate the importance score of each LoRA rank. \n\nSecond, guided by AB-LoRA, we gradually prune abundant and negatively impacting LoRA ranks and allocate",
|
15 |
+
1.6
|
16 |
+
],
|
17 |
+
[
|
18 |
+
"-2-救助申请,也可通过互联网政务服务平台或委托其他单位、\n个人提出申请。家庭和个人在非户籍地遭遇急难情况,可以\n直接向急难发生地提出申请。申请人应按规定填写临时救助\n申请书,提交相关申请材料,并签字确认。\n申请��需提交的材料:(一)家庭成员(个人)居民身\n份证、居住证,委托代为申请的,应当提供授权委托书及受\n托人有效身份证件;(二)家庭(个人)经济状况核查授权\n承诺书;(三)家庭(个人)必需支出增加,或家庭(个人)\n遭遇急难情况等基本生活困难相关材料;(四)其它相关材\n料。\n申请受理。乡镇人民政府(街道办事处)经办机构、县\n级民政部门应当对申请人通过现场或互联网提交的申请材\n料进行初审。\n审核确认。(一)支出型临时救助适用一般程序,应当\n按照工作规程第十六条至第二十条相关要求开展审核确认。\n(二)急难型临时救助适用紧急程序,可以简化一般程序中\n的家庭经济状况核对、民主评议、初审公示等。对于事实清\n楚、情况紧急、需立即采取临时救助措施的,应当先行救助。\n紧急情况解除之后,在10个工作日内补充完善审核确认有\n关材料和手续。\n调查核实。参加调查人员(不少于2人)应当形成调查\n核实材料并签字,同时将调查核实材料送申请人签字。(一)\n家庭经济状况核对。(二)入户调查。调查人员到申请人家",
|
19 |
+
"申请人需提交的材料:\n1. 家庭成员(个人)居民身份证、居住证,委托代为申请的,应当提供授权委托书及受托人有效身份证件;\n2. 家庭(个人)经济状况核查授权承诺书;\n3. 家庭(个人)必需支出增加,或家庭(个人)遭遇急难情况等基本生活困难相关材料;\n4. 其它相关材料。",
|
20 |
+
1.6
|
21 |
+
],
|
22 |
+
[
|
23 |
+
"40\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n2023年人工智能发展现状: \n生成式 AI的突破之年\nMichael Chui ,Eric Hazan ,Lareina Yee ,Bryce Hall ,Alex Singla \n和Alexander Sukharevsky如 今 ,生 成 式 AI工具遍地开花, 各组织均在快速部署; 麦肯锡调查的\n受访者们预计, 该技术将对自己所在行业及就业产生重大影响。\n\n41\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡针对人工智能发展现状的最新年度全球调研结果证实, 生\n成式人工智能 (简称 GenAI )工 具 已 出 现 爆 炸 式 增 长 。许 多 此 类 工\n具 至 今 推 出 尚 不 满 一 年 ,但 已 有 1/3的 受 访 者 表 示 ,其 所 在 组 织 会 在\n至少一项业务职能中经常使 用 GenAI 。 随着这些最新进展, 人工智\n能 已 经 从 一 个 技 术 话 题 上 升 为 企 业 领 导 的 关 注 焦 点 :近 1/4受访高\n管 表 示 ,他 们 会 在 工 作 中 使 用 GenAI 工具; 而在已应用人工智能的\n企 业 中,有 超 过 1/4的受访者表示 GenAI 已 被 列 入 董 事 会 议 程 。此 外 ,\n40% 的受访者表示, 其所在组织将会因 GenAI 的最新进 展而增加对\n人工智能的整体投入。 调查结果表明, GenAI 相关风险管理仍处于\n早期阶段: 即便是针对受访者眼中最常见的不准确问题, 也只有不",
|
24 |
+
"2023年人工智能发展现状:生成式AI的突破之年",
|
25 |
+
1.4
|
26 |
+
],
|
27 |
+
[
|
28 |
+
"麦肯锡中国金融业 CEO季刊 2023年秋季刊\n2023年人工智能发展现状: \n生成式 AI的突破之年\nMichael Chui ,Eric Hazan ,Lareina Yee ,Bryce Hall ,Alex Singla \n和Alexander Sukharevsky如 今 ,生 成 式 AI工具遍地开花, 各组织均在快速部署; 麦肯锡调查的\n受访者们预计, 该技术将对自己所在行业及就业产生重大影响。\n\n41\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡针对人工智能发展现状的最新年度全球调研结果证实, 生\n成式人工智能 (简称 GenAI )工 具 已 出 现 爆 炸 式 增 长 。许 多 此 类 工\n具 至 今 推 出 尚 不 满 一 年 ,但 已 有 1/3的 受 访 者 表 示 ,其 所 在 组 织 会 在\n至少一项业务职能中经常使 用 GenAI 。 随着这些最新进展, 人工智\n能 已 经 从 一 个 技 术 话 题 上 升 为 企 业 领 导 的 关 注 焦 点 :近 1/4受访高\n管 表 示 ,他 们 会 在 工 作 中 使 用 GenAI 工具; 而在已应用人工智能的\n企 业 中,有 超 过 1/4的受访者表示 GenAI 已 被 列 入 董 事 会 议 程 。此 外 ,\n40% 的受访者表示, 其所在组织将会因 GenAI 的最新进 展而增加对\n人工智能的整体投入。 调查结果表明, GenAI 相关风险管理仍处于\n早期阶段: 即便是针对受访者眼中最常见的不准确问题, 也只有不\n到 一 半 受 访 者 表 示 ,所 在 企 业 正 在 采 取 措 施 降 低 风 险 。\n原本已在 自 身 系统内嵌入人工智能能力的组织, 也在积极探索\nGenAI 的 潜 力 ;而 那 些 最 看 好 传 统 AI价 值 潜 力 的 组 织( 我 们 称 之 为\n人 工 智 能 高 绩 效 组 织 )在 GenAI 工 具 应 用 上 同 样 当 仁 不 让 ,走 在 了\n其他企业前面1。\n受访者们预测, GenAI 将 对 业 务 产 生 巨 大 影 响 ,组 织 的 员 工 状 况 也\n将发生较大改变。 他们预计某些领域会减员, 而且为应对人才需求\n变化, 企业需要开展大规模技能再培训。 不过, 虽然 GenAI 应用有\n可能促使企业增加对其他人工智能工具的采用, 但我们发现, 组织\n对其他技术工具的采用几乎并无实质性增加。 2022 年以来, 采用\n人工智能工具的组织 占 比一 直保持稳定, 而且人工智能应用也仅集\n中在少数 几项业务职能上。\n尽 管 仍 在 早 期 阶 段 ,但 GenAI的应用已\n相当普遍\n这项调查于 2023 年4月中旬进 行, 调查结果 表明, 尽 管 GenAI 进入 公\n众视野并不久, 但对这些工具的尝试性应用已经相当普遍, 受访者\n42\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n们预计这些新能力将改变其所在行业 (见图 1)。GenAI 已引起商界\n人士的兴趣: 受访者不分地区、 行业和资历等级, 人人都在工作中\n和工作之外尝试使用 GenAI 。79% 的受访者表示, 他们至少在工作\n中或 工作之 外接触过 GenAI 。22% 的 受 访 者 表 示 ,他 们 会 在 工 作 中\n经常使用 GenAI 。 不同资历受访者的 GenAI 使 用 率 非 常 相 似 ,而 从 行\n业和地区来看, 技术行业和北美地区受访者的 GenAI 使用率最高。\n图图1:各各地地区区、、行行业业和和资资历历级级别别的的受受访访者者表表示示,,他他们们已已经经\n在在使使用用生生成成式式人人工工智智能能工工具具。。\n4\n9\n10\n9\n6\n5\n7\n7\n6\n8\n6\n14\n8\n10\n7\n6\n7\n5\n8\n1218\n11\n14\n10\n22\n11\n16\n11\n8\n16\n10\n19\n16\n14\n16\n17\n18\n22\n16\n1519\n20\n11\n18\n13\n16\n13\n12\n15\n18\n17\n17\n13\n16\n20\n21\n18\n24\n16\n636\n34\n45\n46\n38\n47\n41\n40\n50\n41\n44\n37\n42\n42\n35\n30\n37\n36\n37\n4619\n23\n15\n14\n19\n15\n21\n26\n19\n14\n15\n9\n18\n15\n19\n18\n17\n11\n19\n183\n3\n6\n3\n3\n5\n2\n4\n3\n4\n7\n3\n2\n3\n4\n9\n3\n3\n4\n3大中华区欧洲亚太\n发展中市场\n企业领导北美\n先进制造业\n健康、制药和医疗产品商业、法律和专业服务\n消费品 /零售\n能源和材料\n金融服务\n科技、媒体和电信\n1964年或更早出生高级管理层\n中级管理层\n出生于 1965-1980年\n出生于1981-1996年\n男性\n女性在工作中经常使用\n至少尝试过一次 在工作中和工作之外经常使用没有接触过 在工作之外经常使用\n不知道\n按按办办公公地地点点\n按按行行业业\n按按职职位位\n按按年年龄龄\n按按性性别别\n备注:由于四舍五入,各项数据加总后不一定等于 100%。亚太地区受访人数 = 164;欧洲 = \n515;北美 = 392;大中华区(包括香港和台湾)= 337;发展中市场(包括印度、拉丁美洲、\n中东和北非) = 276。先进制造业(包括汽车和装配、航空航天和国防、先进电子和半导体)\n受访人数 = 96;商业、法律和专业服务 = 215;消费品和零售业 = 128;能源和材料 = 96;\n金融服务 = 248;健康、制药和医疗产品 = 130;科技、媒体和电信 = 244。企业领导受访人\n数 = 541;高级管理层 = 437;中层管理层 = 339。1964 年或更早出生的受访者人数 = 143;\n1965 年-1980年出生的受访者 = 268;1981 年-1996年出生的受访者= 80 。不是所有受访者都\n提供了年龄信息。男性受访者人数 = 1025;女性受访者人数 = 156。调查样本还包括选择\n“非二元性别”或“其他”的受访者,但数量不多,不具有统计意义。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行\n43\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n组织层面上, GenAI 的应用现 在也十分普及。 1/3的 受 访 者 表 示 ,他\n们所在的组织至少在一个职能中经常使用 GenAI ,在 已 经 应 用 AI的\n组 织 中,有 60% 都在使用 GenAI 。 更重要的是, 在已采用人工智能\n的 组 织 中,有 40% 都表示由于 GenAI 的巨大潜力, 他们的公司预期\n将增大对人工智能的投入, 28% 的企业表示 GenAI 的应用已被 列入\n董 事 会 议 程 。从 应 用 AI技 术 的 业 务 职 能 来 看 ,新 工 具 与 人 工 智 能 的\n整 体应用状况相同, 应用最多的职能部门都是营销和销售、 产品服\n务开发以及客户服务和后台支持等服务运营部门 (见图 2)。这 表 明\n企 业 正 将 这 些 新 工 具 部 署 到 价 值 潜 力 最 大 的 地 方 。在 我 们 之 前 的\n研 究 中,上 述 3个 职 能 领 域 , 再 加 上 软 件 工 程 ,可 实 现 GenAI 用例全\n年总价值的 75% 左右。\n表表示示其其组组织织在在相相应应职职能能中中经经常常使使用用GenAI的的受受访访者者占占比比(%��1图图2:生生成成式式AI工工具具最最常常见见的的用用途途是是营营销销和和销销售售、、产产品品服服\n务务开开发发以以及及服服务务运运营营。。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. 问题仅针对表示其企业已至少在一个职能中采纳人工智能技术的受访者。显示数据已经过\n调整,以代表所有受访者。营销与\n销售\n14产品和/\n或服务开发\n13服务\n运营\n10风险\n4战略与\n资金管理\n4HR\n3供应链\n管理\n3制造\n2\n各职能的 GenAI常见用例,受访者占比%\n9 7 6起草文本初稿 识别客户需求趋势采用聊天机器人\n(如用于客户服务)\n8 5 5个性化营销 起草技术文件 预测服务趋势或异常情况\n8 4 5总结文本文档 设计新产品 起草文件初稿营销和销售 产品和 /或服务开发 服务运营\n44\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n麦肯锡评论\nAlex Singla \n全球资深董事合伙人, QuantumBlack ,AI by McKinsey\n全球负责人\n有关 GenAI 讨论愈发成就在几个月前, 高管之间的对话\n还相当初级, 主要是理解它是什么, 看看哪些是炒作, 哪\n些 是 现 实 。现 在 ,短 短 6个 月 过 后 ,商 界 领 袖 们 已 经 在 讨\n论更加复杂的问题了 。 从调查结果中我们看到, 有近 1/3的\n公司在至少一个业务职能中使 用 GenAI 。这 凸 显 出 企 业 对\n“GenAI 在商界可行”这一看法的理解和接受程度。\n接下来问题将是, 企业该如何采取下一步行动, 以及\nGenAI 的发 展轨迹是否会与我们在更广泛的人工智能领\n域观察到的模式 相同, 即采用率稳定 在 50% 左 右 。我 们\n从 数 据 中 看 到 ,在 GenAI 发 展 潜 力 的 鼓 舞 下 ,已 经 使 用 人\n工智能的企业中有近一半企业计划增加对人工智能的投\n入, 部分原因是他们认识到, 企业需要具备更广泛的能力\n才能充分利用 GenAI 。\n若 要 迈 出 下 一 步 ,将 GenAI 从实验 性工具 转变为商业引擎,\n运用它为企业实现丰厚的投资回报, 则要先解决一大批\n问题。 这些问题包括: 确定 GenAI 在组织中有哪些具体\n机 会 、治 理 和 运 营 模 式 应 该 是 什 么 、如 何 最 好 地 管 理 第\n三方 (例如云和大语言模型提供商) 、 需要具备哪些条件\n才能有效管理各种风险, 并理解该技术对人员和技术 栈\n的影响, 清楚如何在实现短期收益与奠定大规模应用所\n需的长期基础之间找到平衡。 这些问题都很复杂, 但它\n们是释放真正 重要价值的关键。\n\n45\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n在 当 前 这 一 早 期 阶 段 ,人 们 对 GenAI 未来影响的预期很高: 3/4的受\n访者预计 GenAI 将在未来 3年内对其所在行业的竞争性质产生重大\n或颠覆性影响。 技术和金融服务行业的受访者预期 GenAI 将产生\n颠覆性影响的比例最高。 我们之前的研究表明, 虽然所有行业都会\n受到一定程度的冲击, 但受影响程度会有所不同2。最 依 赖 知 识 工\n作的行业可能会受到较大影响, 也因此有望收获较多价值。 我们的\n估算显示, 毫无意外, 科技公司受到 GenAI 的影响最大——价值潜\n力相当于行业全球 收 入的 9%; 但除此之外 , 银行业 ( 价值潜力 可达\n5%) 、 制药和医疗产品 (增值同样可达 5%)和 教 育( 可 达 4%)等 基\n于知识的行业, 也会受到重大影响。 相比之下 , 航空航天、 汽车和先\n进电子等制造业受到的颠覆性影响可能较小。 这与之前对制造业影\n响最大的技术浪潮形成鲜明对比, 出现这一局面是因为, GenAI 的\n优势在于基于语言的活动, 而非那些需要体力劳动的活动。\n调查结果显示, 许多组织尚未着手解决来自\nGenAI的潜在风险\n根 据 调 查 ,几 乎 没 有 企 业 已 为 GenAI 的广泛 使 用做 好了充 分准\n备——或者说, 企业并没有准备好应对这些工具可能带来的商业风\n险( 见 图 3) 。 在已采用人工智能的企业受访者中 , 只有 21%的人表\n示, 企业已制定相关政策, 规范员 工工作中的 GenAI 技术使用行为。\n在被问及 GenAI 的具体应用风险问题时, 针对最常被提及的 GenAI\n的风险 (即不准确问题) , 很少有受访者表示他们的公司已有风险\n防范措施到位。 受访者提及不准确问题的频率高于网络安全和监\n管合规, 后两项是之前调查显示的整体人工智能技术最常见风险。\n只有 32% 的受访者表示正在着手应对不准确问题, 这一比例低于网\n络 安 全 风 险 的 应 对 比 例( 38% )。有 趣 的 是 ,网 络 安 全 的 应 对 比 例\n明显低于去年调查中的相关数���, 去年提及正采取措施应对人工\n智能相关网络安全风险的受访者比例为 51%。总 体 而 言 ,正 如 我 们\n前几年所看到的那样, 大多数受访者表示他们的组织并未着手解决\n人工智能相关风险。\n46\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n麦肯锡评论\nAlexander Sukharevsky \n全球资深董事合伙人, QuantumBlack ,AI by McKinsey\n全球负责人\n大家都知道 GenAI 有风险。 但同时, 普遍存在的焦虑和\n害怕使企业领导难以有效应对这些风险。 我们最新的调\n查结果显示, 只有略多于 20% 的公 司制定了生 成 式 AI相\n关风险防范政策。 这些政策往往侧重于保护公司的数据、\n知识和其他知识产权等专有信息。 这些当然很重要, 但我\n们发现, 许多风险可以通过改变反映既定政策的业务技\n术架构来解决。\n然 而 ,真 正 的 问 题 在 于 企 业 对 风 险 的 看 法 过 于 狭 隘 。企\n业还需要关注一系列重大风险, 包括社会风险、 人道主\n义风险、 可持续性风险。 事实上, 与一些人想象的世界末\n日场景 相比, GenAI 那些意想不到的后果更有可能给世\n界带来问题和麻烦。 以最具建设性的方式接触 GenAI 的\n企业正在尝试应用这项技术, 同时制定结构化流程来\n识别和解决更广泛的风险。 这些企业会部署测试版用户 ,\n并设置专门团队, 预判 GenAI 应 用 可 能 的 脱 轨 之 处 ,从 而\n更好地预测某些不良后果。 这些企业还与业内最优秀、 最\n具创造力的人才合作, 确定什么是对组织和整个社会而\n言都最有益的结果。 对于可能出现的新风险以及新机遇\n进行全盘、 结构化的深入思考 , 理解其本质 , 这对于促成\nGenAI 以负责任的方式实现增长、 有效提升生产效率至关\n重要。\n\n47\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n企企业业认认为为重重要要且且正正在在着着手手解解决决的的生生成成式式AI相相关关风风险险,,\n受访者占比( %) 1图图3:不不准准确确、、网网络络安安全全和和知知识识产产权权侵侵权权是是生生成成式式AI应应用用\n中中最最常常被被提提及及的的风风险险。。\n56 32\n53 38\n46 25\n45 28\n39 18\n39 20\n34 13\n31 16\n29 16\n14 4\n11 6\n11 5\n10 2\n1 8不准确\n网络安全\n知识产权侵权\n监管合规\n可解释性 \n个人隐私 \n取代人工\n公平公正 \n组织声誉\n国家安全 \n人身安全 \n环境影响 \n政治稳定\n以上都不是\n1. 仅对表示其所在企业已在至少一个职能采纳AI 技术的受访者提问。上述两组受访者人数\n均为913。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日\n至21日进行\nAI领域的领先企业已在 GenAI应用上\n抢先一步\n调查结果显示, 人工智能高绩效企业 (即据受访者披露, 2022 年至\n少20% 的息税前利润源自人工智能应用的组织) 正全力投入包括\nGenAI 和较传统人工智能在内的所有人工智能能力。 这些早先就已\n从 人 工 智 能 中 获 得 巨 大 价 值 的 组 织 ,在 GenAI 应用方面也已经比其\n他组织领先一步 , 这些企业会在更多职能领域应用 GenAI ,特 别 是\n在产品和服务开发、 及风险和供应链管理方面。 放眼所有人工智能\n能力 ( 包括较传统的机器学习、 机器人流程自动化和聊天机器人) ,\n人工智能高绩效企业比其他企业在产品和服务开发上都有较多应\n用; 这些企业利用人 工智能来优化产品开发 周期, 为现 有产品添加\n新 功 能 ,以 及 创 建 新 的 基 于 人 工 智 能 的 产 品 等 。此 外 ,这 些 企 业 在\n风险模拟和人力资源领域 (例如绩效管理、 组织设计和劳动力部署\n优 化 )也 会 更 多 使 用 人 工 智 能 。\n48\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n还有一个不同于其他企业的方面是: 高绩效企业的人工智能活动更\n少以降本为目标, 而其他组织会将降本 视为首要 任务 (见图 4)。就\n来 自 人 工 智 能 高 绩 效 企 业 的 受 访 者 而 言 ,他 们 表 示 GenAI 的首要目\n标是创造全新业务或收入来源的可能性是其他人的两倍, 而且他\n们最有可能提到基于人工智能的新功能提高了现有产品的价值。\n组组织织GenAI活活动动的的首首要要目目标标,,\n受访者占比( %) 1图图4:来来自自人人工工智智能能高高绩绩效效企企业业的的受受访访者者将将降降本本视视为为生生成成\n式式AI首首要要目目标标的的比比例例较较低低。。\n备注:由于四舍五入,各项数据加总后不一定等于 100%。\n1. 仅对表示其所在企业已至少在一个职能采纳AI 技术的受访者提问。\n2. 表示其组织2022年至少有20% 的息税前利润源自AI 应用的受访者。人工智能高绩效企业受\n访者人数 = 45;所有其他受访者人数 = 712。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行30272319\n3321100%1233\n通过嵌入 AI功\n能或洞见,提\n升产品/服务价\n值增加核心\n业务收入创造新业务和 /\n或收入来源核心业务\n降本AI领先公司的\n受访者2所有其他\n受访者\n正如我们前几年所见, 这些高绩效组织在人工智能方面的投资远\n多于其他组织: 来自人工智能高绩效组织的受访者更有可能 (可能\n性是其他受访者的五倍以上) 表示, 他们将超过 20% 的数字预算用\n于人工智能。 这些组织内部也更广泛地使用人工智能能力。 来自高\n绩效企业的受访者比其他人更有可能表示, 他们的组织已在 4个或\n49\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n更多业务职能中采用了 人工智能, 并且他们在工作流程中嵌入的人\n工智能能力数也较多。 例如, 来自高绩效企业的受访者更常表示, 除\n了GenAI 和 相 关 的 自 然 语 言 能 力 之 外 ,他 们 还 将 知 识 图 谱 嵌 入 到 至\n少一 种产品或 业务 职 能 流 程中。\n虽然人工智能高绩效企业也面临获取人工智能价值方面的挑战,\n但调查结果表明, 他们所面临的困难反映出其在人工智能应用方面\n相对成熟, 而其他企业面对的则是人工智能采用方面更基 础的战\n略 性 问 题( 见 图 5) 。 人工智能高绩效企业的受访者最常提到的最\n大挑战在于模型和工具 (如在生产中监控模型性能、 以及需要随着\n时间推移重新训练模型) 。 相比之下 , 其他受访者提到的则是战略\n问题, 例如设定明确的人工智能愿景并与业务价值挂钩, 或寻求足\n够的资源支持。\n实实现现人人工工智智能能潜潜力力价价值值的的最最大大挑挑战战,,\n在受访者中占比( %)1图图5:模模型型和和工工具具是是领领先先企企业业面面临临的的最最大大AI挑挑战战,,其其他他企企\n业业则则更更多多被被战战略略难难题题所所困困。。\n100%\n242011\n6212\n42\n1913111\n151318其他\n数据\n技术\n应用与推广\n人才\n模型和工具AI高绩效企业\n受访者2所有其他\n受访者\n战略\n注:由于四舍五入,各项数据加总后不一定等于 100%。\n1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者。\n2. 表示其组织2022年至少有20% 的息税前利润源自AI 应用的受访者。AI 高绩效企业受访者人\n数 = 49;其他受访者人数 = 792。\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行\n50\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n麦肯锡评论\nBryce Hall \n全球副董事合伙人\n过去 6年 ,我 们 每 年 开 展 一 次 全 球 人 工 智 能 研 究 ,每 次 都\n能得出一个相同的结论——领先企业通常会从更广阔的\n视角出发, 权衡考量成功必备的要素。 领先企业格外善\n于 聚 焦 价 值 ,并 有 针 对 性 地 调 整 组 织 架 构 ,成 功 捕 捉 价\n值 。观 察 领 先 企 业 运 用 GenAI 技 术 的 方 式 ,可 以 清 晰 地 看\n到上述规律。\n例如, 就战略而言, 我们分析中的领先企业会梳理各个业\n务领域, 寻找人工智能创造高价值的机会。 值得注意的\n是, 他们不仅仅是在应用 GenAI 时 这 么 做 。虽 然 炙 手 可 热\n的GenAI 新 技 术 让 人 心 动 ,但 其 实 AI应用中有远 超过半\n数的潜在价值来自非 GenAI 技 术 。领 先 企 业 往 往 会 秉 持\n审慎态度, 根据潜在价值全面评估人工智能领域的机会。\n这样的方法适用于所有能力相关领域。 以技术和数据为\n例, 领先企业会精准识别捕捉目标价值所需的能力, 包\n括运用公司和行业数据训练大型语言模型的能力。 目前\n存在两条路线, 一是直接采用现有的人工智能服务 (即\n所谓的“接受者”方式) , 二是通过诸如调整并训练模型、\n使 其 能 够 运 用 内 部 自 有 数 据 的 方 式 ,培 养 自 身 能 力 ,打 造\n竞争优势 (即所谓的“创造者”方式) 。 领先企业会对这两\n者的效果和效率进行评估和测试。\n\n51\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n调研结果进一步验证了我们的结论: 在诸如机器学习运维\n(MLOps ) 法等人工智能技术的应用方面, 即使是人工智能高绩效\n企业也尚未达到最佳实践水平, 不过它们更有潜力做到这一点。 例\n如 ,来 自 人 工 智 能 高 绩 效 企 业 的 受 访 者 中 ,仅 35% 表示��所在组织\n会尽量选择整合现有模块, 而非重新创造; 不过, 这已远高于 19%\n这一其他企业受访者回复的比例。\n目 前 ,为 落 地 一 些 更 具 转 型 意 义 的 AI用例, 并尽可能保证过程中的\n安 全 ,亟 需 大 量 的 专 业 MLOps 技术和实践经验。 其中包括实时模型\n运行, 即通过检测系统和即时预警, 快速解决问题, 保证 GenAI 系\n统始终处于管控之下。 虽然领先企业在这一方面表现突出, 但仍有\n进 步 空 间 :来 自 AI高 绩 效 企 业 的 受 访 者 中,有 1/4表示所在企业会全\n面监控所有系统, 并已配备即时预警机制, 而其他企业中 , 仅 12%能\n够做到这一点。\n人工智能相关人才需求已发生变化,人\n工智能技术或将给劳动力带来巨大影响\n我们的最新调研结果表明, 企业为支持人工智能目标而需要的人才\n岗位已发生变化 (见图 6)。过 去 一 年 ,应 用 人 工 智 能 技 术 的 企 业 招\n募最多的岗位是数据工程师、 机器学习工程师和 AI数 据 科 学 家 ,这\n些 都 是 上 一 次 调 研 中 受 访 者 普 遍 提 及 的 岗 位 。不 过 ,招 募 AI相关软\n件工程师 (去年最热门的招聘岗位) 的受访企业占比大大缩小, 比例\n由上一次调 研的 39% 降至 28% 。随 着 GenAI 技 术 的 应 用 ,对 相 关 技\n能的需求也在增加, 提示工程等新兴领域的岗位悄然兴起, 采用人\n工 智 能 技 术 的 企 业中, 7%的受 访者表示 在 过去 一年里招募了提示\n工程领域的人才。\n52\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n表表示示其其所所在在组组织织面面临临人人工工智智能能相相关关岗岗位位招招聘聘难难题题的的受受访访者者占占比比(%)1图图6:人人工工智智能能相相关关岗岗位位招招聘聘仍仍然然很很难难,,不不过过受受访访者者反反映映\n许许多多岗岗位位的的招招聘聘难难度度在在2022年年后后有有所所下下降降。。\n20 40 60\n机器学习工程师\nAI数据科学家\n转译员\nAI产品负责人或经理\n数据架构师\n提示工程师2\n软件工程师\n数据工程师\n设计专家\n数据可视化专家难度较低 难度较高\n0 80 100\n2022 2023\n1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术、且过去12个月招聘相\n关岗位的受访者。未展示回复“简单” 、“不简单也不难”或“不知道”的受访者。\n2. 2022年未询问受访者。\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行\n研 究 结 果 还 显 示 ,招 募 人 工 智 能 相 关 人 才 依 然 很 难 ,不 过 ,过 去 一\n年 的 情 况 多 少 有 所 好 转 ,这 与 2022 年底到 2023 年上半年科技公司的\n裁 员 潮 可 能 有 关 。同 时 ,反 映 很 难 招 到 AI数据科学家、 数据工程师和\n数据可视化专家的受访企业较上一次调查有所减少 , 而机器学习工\n程师和 AI产品负责人的招募工作难度仍然较大, 与去年基本一致。\n受 访 者 预 测 ,未 来 3年, 人工智能技术将重塑许多工作岗位 (见图\n7) 。 整体而言, 受访者预计会有更多 员工转换技能, 而非离职。 已应\n用AI企业的近 4成 受 访 者 预 计 ,企 业 将 有 超 过 20% 的成员经历技 能\n重 塑 ,而 8%的受访者认为组织规模将缩减 20% 以上。\n具体到各职能部门可能受到的 GenAI 冲击, 服务运营是唯一一个大\n多 数 受 访 者 均 认 为 员 工 数 会 减 少 的 职 能 部 门( 见 图 8)。这 与 我 们 近\n期 的 研 究 成 果 基 本 一 致 ,即 虽 然 GenAI 技术会进一步提高我们所估\n算 的 可 自 动 化 工 作 内 容 的 占 比(由 50% 升至 60%~70% ),但 这 并 不\n代表相关岗位的全部工作可以完全实现自动化。\n53\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n图图7:受受访访者者预预计计人人工工智智能能将将对对企企业业的的员员工工队队伍伍有有重重大大影影响响\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行注:由于四舍五入,各项数据加总后不一定等于 100%\n1. 仅对表示其所在企业已至少在一个职能采纳AI 技术的受访者提问,受访者人数 = 913对对未未来来3年年应应用用人人工工智智能能技技术术对对企企业业员员工工队队伍伍所所产产生生影影响响的的预预期期,,\n受访者占比( %)1\n员工数量变化 将重塑技能的员工占比\n8102512\n8\n303\n4不知道\n增加20%以上\n增加11%~20%\n增加3%~10%\n变化很小或没有变化\n(变化幅度不超过2% )\n减少3%~10%\n减少11%~20%\n减少20%以上201718388\n≤5%6-10%11-20%>20%不知道\n图图8:服服务务运运营营是是唯唯一一一一个个大大多多数数受受访访者者都都认认为为会会因因生生成成\n式式AI而而缩缩减减规规模模的的职职能能部部门门。。\n30 35 20 15\n31 37 20 12\n37 28 25 10\n39 33 17 12\n40 33 12 15\n41 30 17 11\n45 32 14 9\n54 23 12 10未未来来3年年生生成成式式AI对对员员工工数数量量的的影影响响,,按按业业务务职职能能划划分分,,\n受访者占比( %)1\n下降 变化很小或没有变化 增加 不知道\n注:由于四舍五入,各项数据加总后不一定等于 100%\n1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行产品和 /或服务开发\n风险\n战略与企业资金管理融\n营销与销售\n制造\nHR\n供应链管理\n服务运营\n54\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\nAI领 先 公 司 重 塑 员 工 技 能 的 力 度 预 计 将 超 过 其 他 企 业( 见 图 9)。在\n表示所在企业未来 3年会重塑 30% 以上员工技能的受访者中 , 来自\nAI领先公司的受访者人数 是其他企业的 3倍。\n图图9:来来自自AI领领先先公公司司的的受受访访者者所所预预计计的的企企业业重重塑塑员员工工技技\n能能的的力力度度大大于于其其他他公公司司。。\n资料来源:麦肯锡全球人工智能调查的1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者\n2. 表示其组织2022年至少有20% 的息税前利润源自AI 应用的受访者。来自AI 领先企业的受访\n者人数 = 50;所有其他受访者人数 = 863预预计计应应用用人人工工智智能能后后公公司司未未来来3年年需需要要重重塑塑技技能能的的员员工工比比例例,,\n受访者占比( %)1\n来自AI领先公司\n的受访者2所有其他受\n访者\n11-20%21-30%>30%\n≤10%73\n9\n10\n89\n3821\n1814不知道\n\n55\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡评论\nLareina Yee \n麦肯锡全球资深董事合伙人; 麦肯锡技术委员会主席\nGenAI 技术初试锋芒, 企业就已经在预见该技术将对人\n才 队 伍 产 生 的 巨 大 影 响 ,包 括 开 放 新 的 工 作 机 会 ,改 变 工\n作方式, 乃至引入提示工程等全新的岗位类型。 GenAI 技\n术可用于辅助几乎所有工作岗位, 这既是它的优势, 也是\n它最大的挑战。\n传统 AI技术虽然重要, 但影响到的员工范围较小, 仅针对\n在机器学习、 数据科学或机器人领域拥有深厚技能积累\n的 人 才,这 一 点 与 GenAI 技 术 存 在 显 著 差 异 。传 统 AI技\n术 人 才 的 专 业 化 程 度 较 高 ,因 此 在 市 场 中 总 是 一 才 难 求 。\n我们的调研结果也凸显出相关岗位的招聘难度。 而反观\nGenAI 技术, 虽然开发大型语言模型、 训练生成式模型等\n工作, 对从业者技能的要求依然很高, 但几乎人 人 都可\n以使用这一技术, 用户不需要任何数据科学专业背景或\n机器学习专业知识, 就能有效地利用 GenAI 技术完成工\n作。 这有些像是从主机电脑到个人 电脑的发展, 前者 只\n有技术专家才能操作, 而个人电脑人人皆可掌握。 这是一\n次颠覆性转变, 技术成了人人可用的强大工具。\n以GenAI 为工具的观点在我们的调查中也有所体现。 大\n多 数 情 况 下,企 业 都 将 GenAI 技术看作是强化人工工作\n的 工 具 ,而 非 人 工 的 替 代 品 。目 前 ,我 们 看 到 很 多 公 司 都\n在不断探索 GenAI 技 术 ,重 点 关 注 最 有 可 能 有 效 提 升 营\n收 或 生 产 效 率 的 实 用 领 域 ,如 利 用 GenAI 工具更新遗留\n代码, 或缩短科学研究和探索的周期。 上述列举的种种\n只是 GenAI 技术的冰山一角, 预计未 来 相关应用的落地\n速 度会显 著提升。\n\n56\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n图图10:不不足足1/3的的受受访访者者表表示示,,所所在在企企业业已已经经1个个以以上上职职能能\n部部门门采采用用人人工工智智能能技技术术——该该数数字字在在2021年年后后几几乎乎没没有有\n变变化化。。\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. In 2021, n = 1843; in 2022, n = 1492; in 2023, n = 168456\n5055\n312731\n1417 16\n6 69\n24 31个或以上\n职能部门2个或以上\n职能部门3个或以上\n职能部门4个或以上\n职能部门5个或以上\n职能部门受受访访者者所所在在组组织织应应用用人人工工智智能能技技术术的的业业务务部部门���数数,,受受访访者者占占比比(%)1\n2021 2022 2023 2021 2022 2023 2021 2022 2023 2021 2022 2023 2021 2022 2023虽然GenAI技 术 备 受 瞩目,但 普及 率 和\n影响范围依然有限\n虽然 GenAI 工具的应用正在快速普及, 但调研数据表明, 企业整体\n的AI技术普及率并未因为这些新工具而显著提升 (见图 10)。采 用\n人 工 智 能 技 术 的 公 司 比 例 依 然 止 步 不 前 ,目 前 为 止 , 55% 的受访企\n业表示已采用相关技术。 表示所在企业已在 1个以上职能部门采用\n人工智能技术的受访者比例不足 1/3,这 表 明 AI应用范围依然较为\n有限。 根据受访者的回答, 应用人工智能技术最多的职能部门是产\n品和服务开发及服务运营, 这与此前 4次 调 研 的 结 果 一 致 。仅 23%\n的受访者称, 去年息税前利润中有至少 5%来自人工智能技术的应\n用, 比例与上一次调查基本 相同, 表明价值挖掘潜力依然较大。\n57\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡评论\nMichael Chui \n麦肯锡全球研究院董事合伙人\n我们总在强调 GenAI 技术的重要性——当然, 有鉴于该\n技术的革命性潜力 , 如此强调并不过分——但这次调研\n结果提醒我们, 在更广阔的人工智能领域, 还有更多价\n值等待挖掘。 事实上, 部分研究成果表明, 非生成式 AI的\n潜在价值有可能甚至比 GenAI 更 大 。在 提 升 预 测 准 确 率 、\n优化物流网络 、 生成下一次购物推 荐等领域 应用更广泛\n的AI技 术 ,有 望 为 企 业 创 造 更 多 价 值 。\n尽管受访者反馈的整体人工智能普及率稳定维持在 55%\n左 右 ,但 有 超 过 2/3的受访者表示自 己所在公司已计划加\n大对人工智能领域的投资力度。 我们不断看到 AI领域的\n佼佼者着手构建基础、 培养能力、 为价值创造铺路。 这\n件 事 可 以 这 样 理 解 ,在 挖 掘 人 工 智 能 价 值 潜 力 方 面 ,“ 富\n者 愈 富 ” 此 言 不 虚 。企 业 对 GenAI 技术的浓 厚兴 趣能否成\n为推动人工智能广泛普及的契机, 让我们拭目以待吧。\n超过2/3的受访者预测 \n未来3年所在组织将加大对 \n人工智能领域的投资力度。\n58\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n图图11:企企业业继继续续在在采采用用人人工工智智能能技技术术的的职职能能部部门门看看到到长长期期\n效效益益。。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者。不展示回答\n“成本上涨”、“无变化”、“不适用”或“不知道”的受访者。\n2. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者。不展示回答\n“营收下降”、“无变化”、“不适用”或“不知道”的受访者2022年年AI技技术术应应用用的的降降本本成成效效,,受访者占比(% )1\n2022年年AI用用例例落落地地后后营营收收增增加加,,受访者占比(% )24\n14\n4\n4\n5\n8\n7\n9\n410\n41\n11\n9\n13\n12\n5\n24\n1026\n26\n18\n26\n34\n19\n28人力资源\n制造\n供应链管理风险营销与销售55\n服务运营研发、产品或产品开发\n战略与企业资金管理\n所有职能的平均值40\n3141\n44\n54\n31\n33\n42≥20% 10-19% <10%\n9\n16\n8\n12\n13\n10\n10\n3\n634\n16\n19\n25\n16\n14\n16\n23\n1817\n34\n38\n24\n35\n33\n32\n30\n35风险人力资源\n服务运营61制造\n营销与销售\n研发、产品或产品开发\n供应链管理58 战略与企业资金管理\n所有职能的平均值60\n66\n6465\n57\n56\n59>10% 6-10% ≤5%\n59\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n企业继续在采用人工智能技术的业务领域中看到长期效益, 并计\n划在未来加大相关领域的投资力度 (见图 11)。多 数 受 访 者 表 示 ,人\n工智能技术在相关业务部门的应用带来了营收增长。 超过 2/3的受\n访 者 预 测 ,未 来 3年 ,所 在 企 业 将 增 加 在 人 工 智 能 领 域 的 投 入 。\n本次研究相关信息\n本次调研于 2023 年4月11日至 21日 在 线 上 开 展 ,共 收 到 1684\n份问卷回复, 全面覆盖各地区、 行业、 公司规模、 专业职能和\n工 作 年 限 。其 中, 913名受访者表示所在公司至少已在 1个职能\n部门采用 AI技术, 并被问及有关其组织中人工智能应用的问\n题。 为针对回复率差异 做出调整, 我们根据受访者国家对全球\nGDP 的 贡献值 对数据 进 行了加 权 处 理 。\n1 我 们 将 人 工 智 能 高 绩 效 企 业 定 义 为 ,至 少 20% 的息税前利润源自人工智能应用的企业 (根据受访者\n提 供 数 据 )。\n2 《The economic potential of generative AI :The next productivity frontier 》 , 麦肯锡, 2023 年6月14\n日。\nMichael Chui 是麦肯锡全球研究院董事合伙人, 常驻湾区分公司; \nLareina Yee 是麦肯锡全球资深董事合伙人, 常驻湾区分公司; \nBryce Hall 是麦肯锡全球资深董事合伙人、 QuantumBlack 全球负责人, 常驻芝加哥分公\n司; \nAlexander Sukharevsky 是麦肯锡全球资深董事合伙人、 QuantumBlack 全 球 负 责 人 ,常\n驻伦敦分公司。\n鸣谢 Shivani Gupta 、Abhisek Jena 、Begum Ortaoglu 、Barr Seitz 和张力对本次调研工作\n的贡献。\n麦肯锡公司 2023 年版 权 所有。\n",
|
29 |
+
"2023年人工智能发展现状:生成式AI的突破之年\n如今,生成式AI工具遍地开花,各组织均在快速部署;麦肯锡调查的受访者们预计,该技术将对自己所在行业及就业产生重大影响。 \nMichael Chui,Eric Hazan,Lareina Yee,Bryce Hall,Alex Singla 和 Alexander Sukharevsky",
|
30 |
+
1.4
|
31 |
+
],
|
32 |
+
[
|
33 |
+
"麦肯锡中国金融业 CEO季刊 2023年秋季刊\n2023年人工智能发展现状: \n生成式 AI的突破之年\nMichael Chui ,Eric Hazan ,Lareina Yee ,Bryce Hall ,Alex Singla \n和Alexander Sukharevsky如 今 ,生 成 式 AI工具遍地开花, 各组织均在快速部署; 麦肯锡调查的\n受访者们预计, 该技术将对自己所在行业及就业产生重大影响。\n\n41\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡针对人工智能发展现状的最新年度全球调研结果证实, 生\n成式人工智能 (简称 GenAI )工 具 已 出 现 爆 炸 式 增 长 。许 多 此 类 工\n具 至 今 推 出 尚 不 满 一 年 ,但 已 有 1/3的 受 访 者 表 示 ,其 所 在 组 织 会 在\n至少一项业务职能中经常使 用 GenAI 。 随着这些最新进展, 人工智\n能 已 经 从 一 个 技 术 话 题 上 升 为 企 业 领 导 的 关 注 焦 点 :近 1/4受访高\n管 表 示 ,他 们 会 在 工 作 中 使 用 GenAI 工具; 而在已应用人工智能的\n企 业 中,有 超 过 1/4的受访者表示 GenAI 已 被 列 入 董 事 会 议 程 。此 外 ,\n40% 的受访者表示, 其所在组织将会因 GenAI 的最新进 展而增加对\n人工智能的整体投入。 调查结果表明, GenAI 相关风险管理仍处于\n早期阶段: 即便是针对受访者眼中最常见的不准确问题, 也只有不\n到 一 半 受 访 者 表 示 ,所 在 企 业 正 在 采 取 措 施 降 低 风 险 。\n原本已在 自 身 系统内嵌入人工智能能力的组织, 也在积极探索\nGenAI 的 潜 力 ;而 那 些 最 看 好 传 统 AI价 值 潜 力 的 组 织( 我 们 称 之 为\n人 工 智 能 高 绩 效 组 织 )在 GenAI 工 具 应 用 上 同 样 当 仁 不 让 ,走 在 了\n其他企业前面1。\n受访者们预测, GenAI 将 对 业 务 产 生 巨 大 影 响 ,组 织 的 员 工 状 况 也\n将发生较大改变。 他们预计某些领域会减员, 而且为应对人才需求\n变化, 企业需要开展大规模技能再培训。 不过, 虽然 GenAI 应用有\n可能促使企业增加对其他人工智能工具的采用, 但我们发现, 组织\n对其他技术工具的采用几乎并无实质性增加。 2022 年以来, 采用\n人工智能工具的组织 占 比一 直保持稳定, 而且人工智能应用也仅集\n中在少数 几项业务职能上。\n尽 管 仍 在 早 期 阶 段 ,但 GenAI的应用已\n相当普遍\n这项调查于 2023 年4月中旬进 行, 调查结果 表明, 尽 管 GenAI 进入 公\n众视野并不久, 但对这些工具的尝试性应用已经相当普遍, 受访者\n42\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n们预计这些新能力将改变其所在行业 (见图 1)。GenAI 已引起商界\n人士的兴趣: 受访者不分地区、 行业和资历等级, 人人都在工作中\n和工作之外尝试使用 GenAI 。79% 的受访者表示, 他们至少在工作\n中或 工作之 外接触过 GenAI 。22% 的 受 访 者 表 示 ,他 们 会 在 工 作 中\n经常使用 GenAI 。 不同资历受访者的 GenAI 使 用 率 非 常 相 似 ,而 从 行\n业和地区来看, 技术行业和北美地区受访者的 GenAI 使用率最高。\n图图1:各各地地区区、、行行业业和和资资历历级级别别的的受受访访者者表表示示,,他他们们已已经经\n在在使使用用生生成成式式人人工工智智能能工工具具。。\n4\n9\n10\n9\n6\n5\n7\n7\n6\n8\n6\n14\n8\n10\n7\n6\n7\n5\n8\n1218\n11\n14\n10\n22\n11\n16\n11\n8\n16\n10\n19\n16\n14\n16\n17\n18\n22\n16\n1519\n20\n11\n18\n13\n16\n13\n12\n15\n18\n17\n17\n13\n16\n20\n21\n18\n24\n16\n636\n34\n45\n46\n38\n47\n41\n40\n50\n41\n44\n37\n42\n42\n35\n30\n37\n36\n37\n4619\n23\n15\n14\n19\n15\n21\n26\n19\n14\n15\n9\n18\n15\n19\n18\n17\n11\n19\n183\n3\n6\n3\n3\n5\n2\n4\n3\n4\n7\n3\n2\n3\n4\n9\n3\n3\n4\n3大中华区欧洲亚太\n发展中市场\n企业领导北美\n先进制造业\n健康、制药和医疗产品商业、法律和专业服务\n消费品 /零售\n能源和材料\n金融服务\n科技、媒体和电信\n1964年或更早出生高级管理层\n中级管理层\n出生于 1965-1980年\n出生于1981-1996年\n男性\n女性在工作中经常使用\n至少尝试过一次 在工作中和工作之外经常使用没有接触过 在工作之外经常使用\n不知道\n按按办办公公地地点点\n按按行行业业\n按按职职位位\n按按年年龄龄\n按按性性别别\n备注:由于四舍五入,各项数据加总后不一定等于 100%。亚太地区受访人数 = 164;欧洲 = \n515;北美 = 392;大中华区(包括香港和台湾)= 337;发展中市场(包括印度、拉丁美洲、\n中东和北非) = 276。先进制造业(包括汽车和装配、航空航天和国防、先进电子和半导体)\n受访人数 = 96;商业、法律和专业服务 = 215;消费品和零售业 = 128;能源和材料 = 96;\n金融服务 = 248;健康、制药和医疗产品 = 130;科技、媒体和电信 = 244。企业领导受访人\n数 = 541;高级管理层 = 437;中层管理层 = 339。1964 年或更早出生的受访者人数 = 143;\n1965 年-1980年出生的受访者 = 268;1981 年-1996年出生的受访者= 80 。不是所有受访者都\n提供了年龄信息。男性受访者人数 = 1025;女性受访者人数 = 156。调查样本还包括选择\n“非二元性别”或“其他”的受访者,但数量不多,不具有统计意义。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行\n43\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n组织层面上, GenAI 的应用现 在也十分普及。 1/3的 受 访 者 表 示 ,他\n们所在的组织至少在一个职能中经常使用 GenAI ,在 已 经 应 用 AI的\n组 织 中,有 60% 都在使用 GenAI 。 更重要的是, 在已采用人工智能\n的 组 织 中,有 40% 都表示由于 GenAI 的巨大潜力, 他们的公司预期\n将增大对人工智能的投入, 28% 的企业表示 GenAI 的应用已被 列入\n董 事 会 议 程 。从 应 用 AI技 术 的 业 务 职 能 来 看 ,新 工 具 与 人 工 智 能 的\n整 体应用状况相同, 应用最多的职能部门都是营销和销售、 产品服\n务开发以及客户服务和后台支持等服务运营部门 (见图 2)。这 表 明\n企 业 正 将 这 些 新 工 具 部 署 到 价 值 潜 力 最 大 的 地 方 。在 我 们 之 前 的\n研 究 中,上 述 3个 职 能 领 域 , 再 加 上 软 件 工 程 ,可 实 现 GenAI 用例全\n年总价值的 75% 左右。\n表表示示其其组组织织在在相相应应职职能能中中经经常常使使用用GenAI的的受受访访者者占占比比(%)1图图2:生生成成式式AI工工具具最最常常见见的的用用途途是是营营销销和和销销售售、、产产品品服服\n务务开开发发以以及及服服务务运运营营。。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. 问题仅针对表示其企业已至少在一个职能中采纳人工智能技术的受访者。显示数据已经过\n调整,以代表所有受访者。营销与\n销售\n14产品和/\n或服务开发\n13服务\n运营\n10风险\n4战略与\n资金管理\n4HR\n3供应链\n管理\n3制造\n2\n各职能的 GenAI常见用例,受访者占比%\n9 7 6起草文本初稿 识别客户需求趋势采用聊天机器人\n(如用于客户服务)\n8 5 5个性化营销 起草技术文件 预测服务趋势或异常情况\n8 4 5总结文本文档 设计新产品 起草文件初稿营销和销售 产品和 /或服务开发 服务运营\n44\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n麦肯锡评论\nAlex Singla \n全球资深董事合伙人, QuantumBlack ,AI by McKinsey\n全球负责人\n有关 GenAI 讨论愈发成就在几个月前, 高管之间的对话\n还相当初级, 主要是理解它是什么, 看看哪些是炒作, 哪\n些 是 现 实 。现 在 ,短 短 6个 月 过 后 ,商 界 领 袖 们 已 经 在 讨\n论更加复杂的问题了 。 从调查结果中我们看到, 有近 1/3的\n公司在至少一个业务职能中使 用 GenAI 。这 凸 显 出 企 业 对\n“GenAI 在商界可行”这一看法的理解和接受程度。\n接下来问题将是, 企业该如何采取下一步行动, 以及\nGenAI 的发 展轨迹是否会与我们在更广泛的人工智能领\n域观察到的模式 相同, 即采用率稳定 在 50% 左 右 。我 们\n从 数 据 中 看 到 ,在 GenAI 发 展 潜 力 的 鼓 舞 下 ,已 经 使 用 人\n工智能的企业中有近一半企业计划增加对人工智能的投\n入, 部分原因是他们认识到, 企业需要具备更广泛的能力\n才能充分利用 GenAI 。\n若 要 迈 出 下 一 步 ,将 GenAI 从实验 性工具 转变为商业引擎,\n运用它为���业实现丰厚的投资回报, 则要先解决一大批\n问题。 这些问题包括: 确定 GenAI 在组织中有哪些具体\n机 会 、治 理 和 运 营 模 式 应 该 是 什 么 、如 何 最 好 地 管 理 第\n三方 (例如云和大语言模型提供商) 、 需要具备哪些条件\n才能有效管理各种风险, 并理解该技术对人员和技术 栈\n的影响, 清楚如何在实现短期收益与奠定大规模应用所\n需的长期基础之间找到平衡。 这些问题都很复杂, 但它\n们是释放真正 重要价值的关键。\n\n45\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n在 当 前 这 一 早 期 阶 段 ,人 们 对 GenAI 未来影响的预期很高: 3/4的受\n访者预计 GenAI 将在未来 3年内对其所在行业的竞争性质产生重大\n或颠覆性影响。 技术和金融服务行业的受访者预期 GenAI 将产生\n颠覆性影响的比例最高。 我们之前的研究表明, 虽然所有行业都会\n受到一定程度的冲击, 但受影响程度会有所不同2。最 依 赖 知 识 工\n作的行业可能会受到较大影响, 也因此有望收获较多价值。 我们的\n估算显示, 毫无意外, 科技公司受到 GenAI 的影响最大——价值潜\n力相当于行业全球 收 入的 9%; 但除此之外 , 银行业 ( 价值潜力 可达\n5%) 、 制药和医疗产品 (增值同样可达 5%)和 教 育( 可 达 4%)等 基\n于知识的行业, 也会受到重大影响。 相比之下 , 航空航天、 汽车和先\n进电子等制造业受到的颠覆性影响可能较小。 这与之前对制造业影\n响最大的技术浪潮形成鲜明对比, 出现这一局面是因为, GenAI 的\n优势在于基于语言的活动, 而非那些需要体力劳动的活动。\n调查结果显示, 许多组织尚未着手解决来自\nGenAI的潜在风险\n根 据 调 查 ,几 乎 没 有 企 业 已 为 GenAI 的广泛 使 用做 好了充 分准\n备——或者说, 企业并没有准备好应对这些工具可能带来的商业风\n险( 见 图 3) 。 在已采用人工智能的企业受访者中 , 只有 21%的人表\n示, 企业已制定相关政策, 规范员 工工作中的 GenAI 技术使用行为。\n在被问及 GenAI 的具体应用风险问题时, 针对最常被提及的 GenAI\n的风险 (即不准确问题) , 很少有受访者表示他们的公司已有风险\n防范措施到位。 受访者提及不准确问题的频率高于网络安全和监\n管合规, 后两项是之前调查显示的整体人工智能技术最常见风险。\n只有 32% 的受访者表示正在着手应对不准确问题, 这一比例低于网\n络 安 全 风 险 的 应 对 比 例( 38% )。有 趣 的 是 ,网 络 安 全 的 应 对 比 例\n明显低于去年调查中的相关数字, 去年提及正采取措施应对人工\n智能相关网络安全风险的受访者比例为 51%。总 体 而 言 ,正 如 我 们\n前几年所看到的那样, 大多数受访者表示他们的组织并未着手解决\n人工智能相关风险。\n46\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n麦肯锡评论\nAlexander Sukharevsky \n全球资深董事合伙人, QuantumBlack ,AI by McKinsey\n全球负责人\n大家都知道 GenAI 有风险。 但同时, 普遍存在的焦虑和\n害怕使企业领导难以有效应对这些风险。 我们最新的调\n查结果显示, 只有略多于 20% 的公 司制定了生 成 式 AI相\n关风险防范政策。 这些政策往往侧重于保护公司的数据、\n知识和其他知识产权等专有信息。 这些当然很重要, 但我\n们发现, 许多风险可以通过改变反映既定政策的业务技\n术架构来解决。\n然 而 ,真 正 的 问 题 在 于 企 业 对 风 险 的 看 法 过 于 狭 隘 。企\n业还需要关注一系列重大风险, 包括社会风险、 人道主\n义风险、 可持续性风险。 事实上, 与一些人想象的世界末\n日场景 相比, GenAI 那些意想不到的后果更有可能给世\n界带来问题和麻烦。 以最具建设性的方式接触 GenAI 的\n企业正在尝试应用这项技术, 同时制定结构化流程来\n识别和解决更广泛的风险。 这些企业会部署测试版用户 ,\n并设置专门团队, 预判 GenAI 应 用 可 能 的 脱 轨 之 处 ,从 而\n更好地预测某些不良后果。 这些企业还与业内最优秀、 最\n具创造力的人才合作, 确定什么是对组织和整个社会而\n言都最有益的结果。 对于可能出现的新风险以及新机遇\n进行全盘、 结构化的深入思考 , 理解其本质 , 这对于促成\nGenAI 以负责任的方式实现增长、 有效提升生产效率至关\n重要。\n\n47\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n企企业业认认为为重重要要且且正正在在着着手手解解决决的的生生成成式式AI相相关关风风险险,,\n受访者占比( %) 1图图3:不不准准确确���、网网络络安安全全和和知知识识产产权权侵侵权权是是生生成成式式AI应应用用\n中中最最常常被被提提及及的的风风险险。。\n56 32\n53 38\n46 25\n45 28\n39 18\n39 20\n34 13\n31 16\n29 16\n14 4\n11 6\n11 5\n10 2\n1 8不准确\n网络安全\n知识产权侵权\n监管合规\n可解释性 \n个人隐私 \n取代人工\n公平公正 \n组织声誉\n国家安全 \n人身安全 \n环境影响 \n政治稳定\n以上都不是\n1. 仅对表示其所在企业已在至少一个职能采纳AI 技术的受访者提问。上述两组受访者人数\n均为913。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日\n至21日进行\nAI领域的领先企业已在 GenAI应用上\n抢先一步\n调查结果显示, 人工智能高绩效企业 (即据受访者披露, 2022 年至\n少20% 的息税前利润源自人工智能应用的组织) 正全力投入包括\nGenAI 和较传统人工智能在内的所有人工智能能力。 这些早先就已\n从 人 工 智 能 中 获 得 巨 大 价 值 的 组 织 ,在 GenAI 应用方面也已经比其\n他组织领先一步 , 这些企业会在更多职能领域应用 GenAI ,特 别 是\n在产品和服务开发、 及风险和供应链管理方面。 放眼所有人工智能\n能力 ( 包括较传统的机器学习、 机器人流程自动化和聊天机器人) ,\n人工智能高绩效企业比其他企业在产品和服务开发上都有较多应\n用; 这些企业利用人 工智能来优化产品开发 周期, 为现 有产品添加\n新 功 能 ,以 及 创 建 新 的 基 于 人 工 智 能 的 产 品 等 。此 外 ,这 些 企 业 在\n风险模拟和人力资源领域 (例如绩效管理、 组织设计和劳动力部署\n优 化 )也 会 更 多 使 用 人 工 智 能 。\n48\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n还有一个不同于其他企业的方面是: 高绩效企业的人工智能活动更\n少以降本为目标, 而其他组织会将降本 视为首要 任务 (见图 4)。就\n来 自 人 工 智 能 高 绩 效 企 业 的 受 访 者 而 言 ,他 们 表 示 GenAI 的首要目\n标是创造全新业务或收入来源的可能性是其他人的两倍, 而且他\n们最有可能提到基于人工智能的新功能提高了现有产品的价值。\n组组织织GenAI活活动动的的首首要要目目标标,,\n受访者占比( %) 1图图4:来来自自人人工工智智能能高高绩绩效效企企业业的的受受访访者者将将降降本本视视为为生生成成\n式式AI首首要要目目标标的的比比例例较较低低。。\n备注:由于四舍五入,各项数据加总后不一定等于 100%。\n1. 仅对表示其所在企业已至少在一个职能采纳AI 技术的受访者提问。\n2. 表示其组织2022年至少有20% 的息税前利润源自AI 应用的受访者。人工智能高绩效企业受\n访者人数 = 45;所有其他受访者人数 = 712。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行30272319\n3321100%1233\n通过嵌入 AI功\n能或洞见,提\n升产品/服务价\n值增加核心\n业务收入创造新业务和 /\n或收入来源核心业务\n降本AI领先公司的\n受访者2所有其他\n受访者\n正如我们前几年所见, 这些高绩效组织在人工智能方面的投资远\n多于其他组织: 来自人工智能高绩效组织的受访者更有可能 (可能\n性是其他受访者的五倍以上) 表示, 他们将超过 20% 的数字预算用\n于人工智能。 这些组织内部也更广泛地使用人工智能能力。 来自高\n绩效企业的受访者比其他人更有可能表示, 他们的组织已在 4个或\n49\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n更多业务职能中采用了 人工智能, 并且他们在工作流程中嵌入的人\n工智能能力数也较多。 例如, 来自高绩效企业的受访者更常表示, 除\n了GenAI 和 相 关 的 自 然 语 言 能 力 之 外 ,他 们 还 将 知 识 图 谱 嵌 入 到 至\n少一 种产品或 业务 职 能 流 程中。\n虽然人工智能高绩效企业也面临获取人工智能价值方面的挑战,\n但调查结果表明, 他们所面临的困难反映出其在人工智能应用方面\n相对成熟, 而其他企业面对的则是人工智能采用方面更基 础的战\n略 性 问 题( 见 图 5) 。 人工智能高绩效企业的受访者最常提到的最\n大挑战在于模型和工具 (如在生产中监控模型性能、 以及需要随着\n时间推移重新训练模型) 。 相比之下 , 其他受访者提到的则是战略\n问题, 例如设定明确的人工智能愿景并与业务价值挂钩, 或寻求足\n够的资源支持。\n实实现现人人工工智智能能潜潜力力价价值值的的最最大大挑挑战战,,\n在受访者中占比( %)1图图5:模模型型和和工工具具是是领��先先企企业业面面临临的的最最大大AI挑挑战战,,其其他他企企\n业业则则更更多多被被战战略略难难题题所所困困。。\n100%\n242011\n6212\n42\n1913111\n151318其他\n数据\n技术\n应用与推广\n人才\n模型和工具AI高绩效企业\n受访者2所有其他\n受访者\n战略\n注:由于四舍五入,各项数据加总后不一定等于 100%。\n1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者。\n2. 表示其组织2022年至少有20% 的息税前利润源自AI 应用的受访者。AI 高绩效企业受访者人\n数 = 49;其他受访者人数 = 792。\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行\n50\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n麦肯锡评论\nBryce Hall \n全球副董事合伙人\n过去 6年 ,我 们 每 年 开 展 一 次 全 球 人 工 智 能 研 究 ,每 次 都\n能得出一个相同的结论——领先企业通常会从更广阔的\n视角出发, 权衡考量成功必备的要素。 领先企业格外善\n于 聚 焦 价 值 ,并 有 针 对 性 地 调 整 组 织 架 构 ,成 功 捕 捉 价\n值 。观 察 领 先 企 业 运 用 GenAI 技 术 的 方 式 ,可 以 清 晰 地 看\n到上述规律。\n例如, 就战略而言, 我们分析中的领先企业会梳理各个业\n务领域, 寻找人工智能创造高价值的机会。 值得注意的\n是, 他们不仅仅是在应用 GenAI 时 这 么 做 。虽 然 炙 手 可 热\n的GenAI 新 技 术 让 人 心 动 ,但 其 实 AI应用中有远 超过半\n数的潜在价值来自非 GenAI 技 术 。领 先 企 业 往 往 会 秉 持\n审慎态度, 根据潜在价值全面评估人工智能领域的机会。\n这样的方法适用于所有能力相关领域。 以技术和数据为\n例, 领先企业会精准识别捕捉目标价值所需的能力, 包\n括运用公司和行业数据训练大型语言模型的能力。 目前\n存在两条路线, 一是直接采用现有的人工智能服务 (即\n所谓的“接受者”方式) , 二是通过诸如调整并训练模型、\n使 其 能 够 运 用 内 部 自 有 数 据 的 方 式 ,培 养 自 身 能 力 ,打 造\n竞争优势 (即所谓的“创造者”方式) 。 领先企业会对这两\n者的效果和效率进行评估和测试。\n\n51\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n调研结果进一步验证了我们的结论: 在诸如机器学习运维\n(MLOps ) 法等人工智能技术的应用方面, 即使是人工智能高绩效\n企业也尚未达到最佳实践水平, 不过它们更有潜力做到这一点。 例\n如 ,来 自 人 工 智 能 高 绩 效 企 业 的 受 访 者 中 ,仅 35% 表示其所在组织\n会尽量选择整合现有模块, 而非重新创造; 不过, 这已远高于 19%\n这一其他企业受访者回复的比例。\n目 前 ,为 落 地 一 些 更 具 转 型 意 义 的 AI用例, 并尽可能保证过程中的\n安 全 ,亟 需 大 量 的 专 业 MLOps 技术和实践经验。 其中包括实时模型\n运行, 即通过检测系统和即时预警, 快速解决问题, 保证 GenAI 系\n统始终处于管控之下。 虽然领先企业在这一方面表现突出, 但仍有\n进 步 空 间 :来 自 AI高 绩 效 企 业 的 受 访 者 中,有 1/4表示所在企业会全\n面监控所有系统, 并已配备即时预警机制, 而其他企业中 , 仅 12%能\n够做到这一点。\n人工智能相关人才需求已发生变化,人\n工智能技术或将给劳动力带来巨大影响\n我们的最新调研结果表明, 企业为支持人工智能目标而需要的人才\n岗位已发生变化 (见图 6)。过 去 一 年 ,应 用 人 工 智 能 技 术 的 企 业 招\n募最多的岗位是数据工程师、 机器学习工程师和 AI数 据 科 学 家 ,这\n些 都 是 上 一 次 调 研 中 受 访 者 普 遍 提 及 的 岗 位 。不 过 ,招 募 AI相关软\n件工程师 (去年最热门的招聘岗位) 的受访企业占比大大缩小, 比例\n由上一次调 研的 39% 降至 28% 。随 着 GenAI 技 术 的 应 用 ,对 相 关 技\n能的需求也在增加, 提示工程等新兴领域的岗位悄然兴起, 采用人\n工 智 能 技 术 的 企 业中, 7%的受 访者表示 在 过去 一年里招募了提示\n工程领域的人才。\n52\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n表表示示其其所所在在组组织织面面临临人人工工智智能能相相关关岗岗位位招招聘聘难难题题的的受受访访者者占占比比(%)1图图6:人人工工智智能能相相关关岗岗位位招招聘聘仍仍然然很很难难,,不不过过受受访访者者反反映映\n许许多多岗岗位位的的招招聘聘难难度度在在2022年年后后有有所所下下降降。。\n20 40 60\n机器学习工程师\nAI数据科学家\n转译员\nAI产品负��人或经理\n数据架构师\n提示工程师2\n软件工程师\n数据工程师\n设计专家\n数据可视化专家难度较低 难度较高\n0 80 100\n2022 2023\n1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术、且过去12个月招聘相\n关岗位的受访者。未展示回复“简单” 、“不简单也不难”或“不知道”的受访者。\n2. 2022年未询问受访者。\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行\n研 究 结 果 还 显 示 ,招 募 人 工 智 能 相 关 人 才 依 然 很 难 ,不 过 ,过 去 一\n年 的 情 况 多 少 有 所 好 转 ,这 与 2022 年底到 2023 年上半年科技公司的\n裁 员 潮 可 能 有 关 。同 时 ,反 映 很 难 招 到 AI数据科学家、 数据工程师和\n数据可视化专家的受访企业较上一次调查有所减少 , 而机器学习工\n程师和 AI产品负责人的招募工作难度仍然较大, 与去年基本一致。\n受 访 者 预 测 ,未 来 3年, 人工智能技术将重塑许多工作岗位 (见图\n7) 。 整体而言, 受访者预计会有更多 员工转换技能, 而非离职。 已应\n用AI企业的近 4成 受 访 者 预 计 ,企 业 将 有 超 过 20% 的成员经历技 能\n重 塑 ,而 8%的受访者认为组织规模将缩减 20% 以上。\n具体到各职能部门可能受到的 GenAI 冲击, 服务运营是唯一一个大\n多 数 受 访 者 均 认 为 员 工 数 会 减 少 的 职 能 部 门( 见 图 8)。这 与 我 们 近\n期 的 研 究 成 果 基 本 一 致 ,即 虽 然 GenAI 技术会进一步提高我们所估\n算 的 可 自 动 化 工 作 内 容 的 占 比(由 50% 升至 60%~70% ),但 这 并 不\n代表相关岗位的全部工作可以完全实现自动化。\n53\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n图图7:受受访访者者预预计计人人工工智智能能将将对对企企业业的的员员工工队队伍伍有有重重大大影影响响\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行注:由于四舍五入,各项数据加总后不一定等于 100%\n1. 仅对表示其所在企业已至少在一个职能采纳AI 技术的受访者提问,受访者人数 = 913对对未未来来3年年应应用用人人工工智智能能技技术术对对企企业业员员工工队队伍伍所所产产生生影影响响的的预预期期,,\n受访者占比( %)1\n员工数量变化 将重塑技能的员工占比\n8102512\n8\n303\n4不知道\n增加20%以上\n增加11%~20%\n增加3%~10%\n变化很小或没有变化\n(变化幅度不超过2% )\n减少3%~10%\n减少11%~20%\n减少20%以上201718388\n≤5%6-10%11-20%>20%不知道\n图图8:服服务务运运营营是是唯唯一一一一个个大大多多数数受受访访者者都都认认为为会会因因生生成成\n式式AI而而缩缩减减规规模模的的职职能能部部门门。。\n30 35 20 15\n31 37 20 12\n37 28 25 10\n39 33 17 12\n40 33 12 15\n41 30 17 11\n45 32 14 9\n54 23 12 10未未来来3年年生生成成式式AI对对员员工工数数量量的的影影响响,,按按业业务务职职能能划划分分,,\n受访者占比( %)1\n下降 变化很小或没有变化 增加 不知道\n注:由于四舍五入,各项数据加总后不一定等于 100%\n1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行产品和 /或服务开发\n风险\n战略与企业资金管理融\n营销与销售\n制造\nHR\n供应链管理\n服务运营\n54\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\nAI领 先 公 司 重 塑 员 工 技 能 的 力 度 预 计 将 超 过 其 他 企 业( 见 图 9)。在\n表示所在企业未来 3年会重塑 30% 以上员工技能的受访者中 , 来自\nAI领先公司的受访者人数 是其他企业的 3倍。\n图图9:来来自自AI领领先先公公司司的的受受访访者者所所预预计计的的企企业业重重塑塑员员工工技技\n能能的的力力度度大大于于其其他他公公司司。。\n资料来源:麦肯锡全球人工智能调查的1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者\n2. 表示其组织2022年至少有20% 的息税前利润源自AI 应用的受访者。来自AI 领先企业的受访\n者人数 = 50;所有其他受访者人数 = 863预预计计应应用用人人工工智智能能后后公公司司未未来来3年年需需要要重重塑塑技技能能的的员员工工比比例例,,\n受访者占比( %)1\n来自AI领先公司\n的受访者2所有其他受\n访者\n11-20%21-30%>30%\n≤10%73\n9\n10\n89\n3821\n1814不知道\n\n55\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡评论\nLareina Yee \n麦肯锡全球资深董事合伙人; 麦肯锡技术委员会主席\nGenAI 技术初试锋芒, 企业就已经在预见该技术将对人\n才 队 伍 产 生 的 巨 大 影 响 ,包 括 开 放 新 的 工 作 机 会 ,改 变 工\n作方式, 乃至引入提示工程等全新的岗位类型。 GenAI 技\n术可用于辅助几乎所有工作岗位, 这既是它的优势, 也是\n它最大的挑战。\n传统 AI技术虽然重要, 但影响到的员工范围较小, 仅针对\n在机器学习、 数据科学或机器人领域拥有深厚技能积累\n的 人 才,这 一 点 与 GenAI 技 术 存 在 显 著 差 异 。传 统 AI技\n术 人 才 的 专 业 化 程 度 较 高 ,因 此 在 市 场 中 总 是 一 才 难 求 。\n我们的调研结果也凸显出相关岗位的招聘难度。 而反观\nGenAI 技术, 虽然开发大型语言模型、 训练生成式模型等\n工作, 对从业者技能的要求依然很高, 但几乎人 人 都可\n以使用这一技术, 用户不需要任何数据科学专业背景或\n机器学习专业知识, 就能有效地利用 GenAI 技术完成工\n作。 这有些像是从主机电脑到个人 电脑的发展, 前者 只\n有技术专家才能操作, 而个人电脑人人皆可掌握。 这是一\n次颠覆性转变, 技术成了人人可用的强大工具。\n以GenAI 为工具的观点在我们的调查中也有所体现。 大\n多 数 情 况 下,企 业 都 将 GenAI 技术看作是强化人工工作\n的 工 具 ,而 非 人 工 的 替 代 品 。目 前 ,我 们 看 到 很 多 公 司 都\n在不断探索 GenAI 技 术 ,重 点 关 注 最 有 可 能 有 效 提 升 营\n收 或 生 产 效 率 的 实 用 领 域 ,如 利 用 GenAI 工具更新遗留\n代码, 或缩短科学研究和探索的周期。 上述列举的种种\n只是 GenAI 技术的冰山一角, 预计未 来 相关应用的落地\n速 度会显 著提升。\n\n56\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n图图10:不不足足1/3的的受受访访者者表表示示,,所所在在企企业业已已经经1个个以以上上职职能能\n部部门门采采用用人人工工智智能能技技术术——该该数数字字在在2021年年后后几几乎乎没没有有\n变变化化。。\n资料来源:麦肯锡全球人工智能调查的 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. In 2021, n = 1843; in 2022, n = 1492; in 2023, n = 168456\n5055\n312731\n1417 16\n6 69\n24 31个或以上\n职能部门2个或以上\n职能部门3个或以上\n职能部门4个或以上\n职能部门5个或以上\n职能部门受受访访者者所所在在组组织织应应用用人人工工智智能能技技术术的的业业务务部部门门数数,,受受访访者者占占比比(%)1\n2021 2022 2023 2021 2022 2023 2021 2022 2023 2021 2022 2023 2021 2022 2023虽然GenAI技 术 备 受 瞩目,但 普及 率 和\n影响范围依然有限\n虽然 GenAI 工具的应用正在快速普及, 但调研数据表明, 企业整体\n的AI技术普及率并未因为这些新工具而显著提升 (见图 10)。采 用\n人 工 智 能 技 术 的 公 司 比 例 依 然 止 步 不 前 ,目 前 为 止 , 55% 的受访企\n业表示已采用相关技术。 表示所在企业已在 1个以上职能部门采用\n人工智能技术的受访者比例不足 1/3,这 表 明 AI应用范围依然较为\n有限。 根据受访者的回答, 应用人工智能技术最多的职能部门是产\n品和服务开发及服务运营, 这与此前 4次 调 研 的 结 果 一 致 。仅 23%\n的受访者称, 去年息税前利润中有至少 5%来自人工智能技术的应\n用, 比例与上一次调查基本 相同, 表明价值挖掘潜力依然较大。\n57\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n麦肯锡评论\nMichael Chui \n麦肯锡全球研究院董事合伙人\n我们总在强调 GenAI 技术的重要性——当然, 有鉴于该\n技术的革命性潜力 , 如此强调并不过分——但这次调研\n结果提醒我们, 在更广阔的人工智能领域, 还有更多价\n值等待挖掘。 事实上, 部分研究成果表明, 非生成式 AI的\n潜在价值有可能甚至比 GenAI 更 大 。在 提 升 预 测 准 确 率 、\n优化物流网络 、 生成下一次购物推 荐等领域 应用更广泛\n的AI技 术 ,有 望 为 企 业 创 造 更 多 价 值 。\n尽管受访者反馈的整体人工智能普及率稳定维持在 55%\n左 右 ,但 有 超 过 2/3的受访者表示自 己所在公司已计划加\n大对人工智能领域的投资力度。 我们不断看到 AI领域的\n佼佼者着手构建基础、 培养能力、 为价值创造铺路。 这\n件 事 可 以 这 样 理 解 ,在 挖 掘 人 工 智 能 价 值 潜 力 方 面 ,“ 富\n者 愈 富 ” 此 言 不 虚 。企 业 对 GenAI 技术的浓 厚兴 趣能否成\n为推动人工智能广泛普及的契机, 让我们拭目以待吧。\n超过2/3的受访者预测 \n未来3年所在组织将加大对 \n人工智能领域的投资力度。\n58\n麦肯锡中国金融业 CEO季刊 2023年秋季刊\n图图11:企企业业继继续续在在采采用用人人工工智智能能技技术术的的职职能能部部门门看看到到长长期期\n效效益益。。\n资料来源:麦肯锡全球人工智能调查, 1684名受访者涵盖组织各个层级,2023 年4月11日至\n21日进行1. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者。不展示回答\n“成本上涨”、“无变化”、“不适用”或“不知道”的受访者。\n2. 该问题仅针对表明自己所在组织某一职能领域已采用人工智能技术的受访者。不展示回答\n“营收下降”、“无变化”、“不适用”或“不知道”的受访者2022年年AI技技术术应应用用的的降降本本成成效效,,受访者占比(% )1\n2022年年AI用用例例落落地地后后营营收收增增加加,,受访者占比(% )24\n14\n4\n4\n5\n8\n7\n9\n410\n41\n11\n9\n13\n12\n5\n24\n1026\n26\n18\n26\n34\n19\n28人力资源\n制造\n供应链管理风险营销与销售55\n服务运营研发、产品或产品开发\n战略与企业资金管理\n所有职能的平均值40\n3141\n44\n54\n31\n33\n42≥20% 10-19% <10%\n9\n16\n8\n12\n13\n10\n10\n3\n634\n16\n19\n25\n16\n14\n16\n23\n1817\n34\n38\n24\n35\n33\n32\n30\n35风险人力资源\n服务运营61制造\n营销与销售\n研发、产品或产品开发\n供应链管理58 战略与企业资金管理\n所有职能的平均值60\n66\n6465\n57\n56\n59>10% 6-10% ≤5%\n59\n2023年 人 工 智 能 发 展 现 状 :生 成 式 AI的突破之年\n企业继续在采用人工智能技术的业务领域中看到长期效益, 并计\n划在未来加大相关领域的投资力度 (见图 11)。多 数 受 访 者 表 示 ,人\n工智能技术在相关业务部门的应用带来了营收增长。 超过 2/3的受\n访 者 预 测 ,未 来 3年 ,所 在 企 业 将 增 加 在 人 工 智 能 领 域 的 投 入 。\n本次研究相关信息\n本次调研于 2023 年4月11日至 21日 在 线 上 开 展 ,共 收 到 1684\n份问卷回复, 全面覆盖各地区、 行业、 公司规模、 专业职能和\n工 作 年 限 。其 中, 913名受访者表示所在公司至少已在 1个职能\n部门采用 AI技术, 并被问及有关其组织中人工智能应用的问\n题。 为针对回复率差异 做出调整, 我们根据受访者国家对全球\nGDP 的 贡献值 对数据 进 行了加 权 处 理 。\n1 我 们 将 人 工 智 能 高 绩 效 企 业 定 义 为 ,至 少 20% 的息税前利润源自人工智能应用的企业 (根据受访者\n提 供 数 据 )。\n2 《The economic potential of generative AI :The next productivity frontier 》 , 麦肯锡, 2023 年6月14\n日。\nMichael Chui 是麦肯锡全球研究院董事合伙人, 常驻湾区分公司; \nLareina Yee 是麦肯锡全球资深董事合伙人, 常驻湾区分公司; \nBryce Hall 是麦肯锡全球资深董事合伙人、 QuantumBlack 全球负责人, 常驻芝加哥分公\n司; \nAlexander Sukharevsky 是麦肯锡全球资深董事合伙人、 QuantumBlack 全 球 负 责 人 ,常\n驻伦敦分公司。\n鸣谢 Shivani Gupta 、Abhisek Jena 、Begum Ortaoglu 、Barr Seitz 和张力对本次调研工作\n的贡献。\n麦肯锡公司 2023 年版 权 所有。\n",
|
34 |
+
"那么在语境中 S3 可能有一种幸灾乐祸的意思,而 war 3 则可能表达对战争的反对情绪。是吗。",
|
35 |
+
1.4
|
36 |
+
]
|
37 |
+
]
|
log.py
ADDED
@@ -0,0 +1,229 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import logging
|
4 |
+
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
|
5 |
+
import os
|
6 |
+
|
7 |
+
|
8 |
+
def setup_size_rotating(log_directory: str):
|
9 |
+
fmt = "%(asctime)s - %(name)s - %(levelname)s %(filename)s:%(lineno)d > %(message)s"
|
10 |
+
|
11 |
+
stream_handler = logging.StreamHandler()
|
12 |
+
stream_handler.setLevel(logging.INFO)
|
13 |
+
stream_handler.setFormatter(logging.Formatter(fmt))
|
14 |
+
|
15 |
+
# main
|
16 |
+
main_logger = logging.getLogger("main")
|
17 |
+
main_logger.addHandler(stream_handler)
|
18 |
+
main_info_file_handler = RotatingFileHandler(
|
19 |
+
filename=os.path.join(log_directory, "main.log"),
|
20 |
+
maxBytes=100*1024*1024, # 100MB
|
21 |
+
encoding="utf-8",
|
22 |
+
backupCount=2,
|
23 |
+
)
|
24 |
+
main_info_file_handler.setLevel(logging.INFO)
|
25 |
+
main_info_file_handler.setFormatter(logging.Formatter(fmt))
|
26 |
+
main_logger.addHandler(main_info_file_handler)
|
27 |
+
|
28 |
+
# http
|
29 |
+
http_logger = logging.getLogger("http")
|
30 |
+
http_file_handler = RotatingFileHandler(
|
31 |
+
filename=os.path.join(log_directory, "http.log"),
|
32 |
+
maxBytes=100*1024*1024, # 100MB
|
33 |
+
encoding="utf-8",
|
34 |
+
backupCount=2,
|
35 |
+
)
|
36 |
+
http_file_handler.setLevel(logging.DEBUG)
|
37 |
+
http_file_handler.setFormatter(logging.Formatter(fmt))
|
38 |
+
http_logger.addHandler(http_file_handler)
|
39 |
+
|
40 |
+
# api
|
41 |
+
api_logger = logging.getLogger("api")
|
42 |
+
api_file_handler = RotatingFileHandler(
|
43 |
+
filename=os.path.join(log_directory, "api.log"),
|
44 |
+
maxBytes=10*1024*1024, # 10MB
|
45 |
+
encoding="utf-8",
|
46 |
+
backupCount=2,
|
47 |
+
)
|
48 |
+
api_file_handler.setLevel(logging.DEBUG)
|
49 |
+
api_file_handler.setFormatter(logging.Formatter(fmt))
|
50 |
+
api_logger.addHandler(api_file_handler)
|
51 |
+
|
52 |
+
# toolbox
|
53 |
+
toolbox_logger = logging.getLogger("toolbox")
|
54 |
+
toolbox_logger.addHandler(stream_handler)
|
55 |
+
toolbox_file_handler = RotatingFileHandler(
|
56 |
+
filename=os.path.join(log_directory, "toolbox.log"),
|
57 |
+
maxBytes=10*1024*1024, # 10MB
|
58 |
+
encoding="utf-8",
|
59 |
+
backupCount=2,
|
60 |
+
)
|
61 |
+
toolbox_file_handler.setLevel(logging.DEBUG)
|
62 |
+
toolbox_file_handler.setFormatter(logging.Formatter(fmt))
|
63 |
+
toolbox_logger.addHandler(toolbox_file_handler)
|
64 |
+
|
65 |
+
# alarm
|
66 |
+
alarm_logger = logging.getLogger("alarm")
|
67 |
+
alarm_file_handler = RotatingFileHandler(
|
68 |
+
filename=os.path.join(log_directory, "alarm.log"),
|
69 |
+
maxBytes=1*1024*1024, # 1MB
|
70 |
+
encoding="utf-8",
|
71 |
+
backupCount=2,
|
72 |
+
)
|
73 |
+
alarm_file_handler.setLevel(logging.DEBUG)
|
74 |
+
alarm_file_handler.setFormatter(logging.Formatter(fmt))
|
75 |
+
alarm_logger.addHandler(alarm_file_handler)
|
76 |
+
|
77 |
+
debug_file_handler = RotatingFileHandler(
|
78 |
+
filename=os.path.join(log_directory, "debug.log"),
|
79 |
+
maxBytes=1*1024*1024, # 1MB
|
80 |
+
encoding="utf-8",
|
81 |
+
backupCount=2,
|
82 |
+
)
|
83 |
+
debug_file_handler.setLevel(logging.DEBUG)
|
84 |
+
debug_file_handler.setFormatter(logging.Formatter(fmt))
|
85 |
+
|
86 |
+
info_file_handler = RotatingFileHandler(
|
87 |
+
filename=os.path.join(log_directory, "info.log"),
|
88 |
+
maxBytes=1*1024*1024, # 1MB
|
89 |
+
encoding="utf-8",
|
90 |
+
backupCount=2,
|
91 |
+
)
|
92 |
+
info_file_handler.setLevel(logging.INFO)
|
93 |
+
info_file_handler.setFormatter(logging.Formatter(fmt))
|
94 |
+
|
95 |
+
error_file_handler = RotatingFileHandler(
|
96 |
+
filename=os.path.join(log_directory, "error.log"),
|
97 |
+
maxBytes=1*1024*1024, # 1MB
|
98 |
+
encoding="utf-8",
|
99 |
+
backupCount=2,
|
100 |
+
)
|
101 |
+
error_file_handler.setLevel(logging.ERROR)
|
102 |
+
error_file_handler.setFormatter(logging.Formatter(fmt))
|
103 |
+
|
104 |
+
logging.basicConfig(
|
105 |
+
level=logging.DEBUG,
|
106 |
+
datefmt="%a, %d %b %Y %H:%M:%S",
|
107 |
+
handlers=[
|
108 |
+
debug_file_handler,
|
109 |
+
info_file_handler,
|
110 |
+
error_file_handler,
|
111 |
+
]
|
112 |
+
)
|
113 |
+
|
114 |
+
|
115 |
+
def setup_time_rotating(log_directory: str):
|
116 |
+
fmt = "%(asctime)s - %(name)s - %(levelname)s %(filename)s:%(lineno)d > %(message)s"
|
117 |
+
|
118 |
+
stream_handler = logging.StreamHandler()
|
119 |
+
stream_handler.setLevel(logging.INFO)
|
120 |
+
stream_handler.setFormatter(logging.Formatter(fmt))
|
121 |
+
|
122 |
+
# main
|
123 |
+
main_logger = logging.getLogger("main")
|
124 |
+
main_logger.addHandler(stream_handler)
|
125 |
+
main_info_file_handler = TimedRotatingFileHandler(
|
126 |
+
filename=os.path.join(log_directory, "main.log"),
|
127 |
+
encoding="utf-8",
|
128 |
+
when="midnight",
|
129 |
+
interval=1,
|
130 |
+
backupCount=7
|
131 |
+
)
|
132 |
+
main_info_file_handler.setLevel(logging.INFO)
|
133 |
+
main_info_file_handler.setFormatter(logging.Formatter(fmt))
|
134 |
+
main_logger.addHandler(main_info_file_handler)
|
135 |
+
|
136 |
+
# http
|
137 |
+
http_logger = logging.getLogger("http")
|
138 |
+
http_file_handler = TimedRotatingFileHandler(
|
139 |
+
filename=os.path.join(log_directory, "http.log"),
|
140 |
+
encoding='utf-8',
|
141 |
+
when="midnight",
|
142 |
+
interval=1,
|
143 |
+
backupCount=7
|
144 |
+
)
|
145 |
+
http_file_handler.setLevel(logging.DEBUG)
|
146 |
+
http_file_handler.setFormatter(logging.Formatter(fmt))
|
147 |
+
http_logger.addHandler(http_file_handler)
|
148 |
+
|
149 |
+
# api
|
150 |
+
api_logger = logging.getLogger("api")
|
151 |
+
api_file_handler = TimedRotatingFileHandler(
|
152 |
+
filename=os.path.join(log_directory, "api.log"),
|
153 |
+
encoding='utf-8',
|
154 |
+
when="midnight",
|
155 |
+
interval=1,
|
156 |
+
backupCount=7
|
157 |
+
)
|
158 |
+
api_file_handler.setLevel(logging.DEBUG)
|
159 |
+
api_file_handler.setFormatter(logging.Formatter(fmt))
|
160 |
+
api_logger.addHandler(api_file_handler)
|
161 |
+
|
162 |
+
# toolbox
|
163 |
+
toolbox_logger = logging.getLogger("toolbox")
|
164 |
+
toolbox_file_handler = RotatingFileHandler(
|
165 |
+
filename=os.path.join(log_directory, "toolbox.log"),
|
166 |
+
maxBytes=10*1024*1024, # 10MB
|
167 |
+
encoding="utf-8",
|
168 |
+
backupCount=2,
|
169 |
+
)
|
170 |
+
toolbox_file_handler.setLevel(logging.DEBUG)
|
171 |
+
toolbox_file_handler.setFormatter(logging.Formatter(fmt))
|
172 |
+
toolbox_logger.addHandler(toolbox_file_handler)
|
173 |
+
|
174 |
+
# alarm
|
175 |
+
alarm_logger = logging.getLogger("alarm")
|
176 |
+
alarm_file_handler = TimedRotatingFileHandler(
|
177 |
+
filename=os.path.join(log_directory, "alarm.log"),
|
178 |
+
encoding="utf-8",
|
179 |
+
when="midnight",
|
180 |
+
interval=1,
|
181 |
+
backupCount=7
|
182 |
+
)
|
183 |
+
alarm_file_handler.setLevel(logging.DEBUG)
|
184 |
+
alarm_file_handler.setFormatter(logging.Formatter(fmt))
|
185 |
+
alarm_logger.addHandler(alarm_file_handler)
|
186 |
+
|
187 |
+
debug_file_handler = TimedRotatingFileHandler(
|
188 |
+
filename=os.path.join(log_directory, "debug.log"),
|
189 |
+
encoding="utf-8",
|
190 |
+
when="D",
|
191 |
+
interval=1,
|
192 |
+
backupCount=7
|
193 |
+
)
|
194 |
+
debug_file_handler.setLevel(logging.DEBUG)
|
195 |
+
debug_file_handler.setFormatter(logging.Formatter(fmt))
|
196 |
+
|
197 |
+
info_file_handler = TimedRotatingFileHandler(
|
198 |
+
filename=os.path.join(log_directory, "info.log"),
|
199 |
+
encoding="utf-8",
|
200 |
+
when="D",
|
201 |
+
interval=1,
|
202 |
+
backupCount=7
|
203 |
+
)
|
204 |
+
info_file_handler.setLevel(logging.INFO)
|
205 |
+
info_file_handler.setFormatter(logging.Formatter(fmt))
|
206 |
+
|
207 |
+
error_file_handler = TimedRotatingFileHandler(
|
208 |
+
filename=os.path.join(log_directory, "error.log"),
|
209 |
+
encoding="utf-8",
|
210 |
+
when="D",
|
211 |
+
interval=1,
|
212 |
+
backupCount=7
|
213 |
+
)
|
214 |
+
error_file_handler.setLevel(logging.ERROR)
|
215 |
+
error_file_handler.setFormatter(logging.Formatter(fmt))
|
216 |
+
|
217 |
+
logging.basicConfig(
|
218 |
+
level=logging.DEBUG,
|
219 |
+
datefmt="%a, %d %b %Y %H:%M:%S",
|
220 |
+
handlers=[
|
221 |
+
debug_file_handler,
|
222 |
+
info_file_handler,
|
223 |
+
error_file_handler,
|
224 |
+
]
|
225 |
+
)
|
226 |
+
|
227 |
+
|
228 |
+
if __name__ == "__main__":
|
229 |
+
pass
|