Aye10032
commited on
Commit
·
529e208
1
Parent(s):
02fb4e4
update
Browse files- .gitignore +1 -0
- .streamlit/config.toml +6 -0
- App.py +23 -0
- README.md +1 -1
- pages/Reference.py +196 -0
- pages/Reformat.py +65 -0
- pages/TextToImage.py +92 -0
- pages/Translate.py +137 -0
- requirements.txt +6 -0
- ui/Component.py +13 -0
- utils/Decorator.py +41 -0
- utils/__init__.py +0 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
/config.yaml
|
.streamlit/config.toml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[browser]
|
2 |
+
gatherUsageStats = false
|
3 |
+
|
4 |
+
[client]
|
5 |
+
showSidebarNavigation = false
|
6 |
+
toolbarMode = "auto"
|
App.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
3 |
+
from ui.Component import side_bar_links
|
4 |
+
|
5 |
+
st.set_page_config(
|
6 |
+
page_title='工具箱',
|
7 |
+
page_icon='🔨',
|
8 |
+
)
|
9 |
+
|
10 |
+
with st.sidebar:
|
11 |
+
side_bar_links()
|
12 |
+
|
13 |
+
st.markdown("""
|
14 |
+
# 自用小工具
|
15 |
+
|
16 |
+
## 文本格式化
|
17 |
+
|
18 |
+
将PDF中直接复制的文本中的换行符去除,并将引用转化为markdown格式。
|
19 |
+
|
20 |
+
## 引用文献生成
|
21 |
+
|
22 |
+
处理PUBMED的NLM格式的引用文献,并转化为yaml格式,方便存储在markdown文件中
|
23 |
+
""")
|
README.md
CHANGED
@@ -5,7 +5,7 @@ colorFrom: red
|
|
5 |
colorTo: yellow
|
6 |
sdk: streamlit
|
7 |
sdk_version: 1.34.0
|
8 |
-
app_file:
|
9 |
pinned: false
|
10 |
license: gpl-3.0
|
11 |
---
|
|
|
5 |
colorTo: yellow
|
6 |
sdk: streamlit
|
7 |
sdk_version: 1.34.0
|
8 |
+
app_file: App.py
|
9 |
pinned: false
|
10 |
license: gpl-3.0
|
11 |
---
|
pages/Reference.py
ADDED
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import random
|
2 |
+
from typing import Dict, Any
|
3 |
+
|
4 |
+
import requests
|
5 |
+
import streamlit as st
|
6 |
+
import yaml
|
7 |
+
from loguru import logger
|
8 |
+
|
9 |
+
from ui.Component import side_bar_links
|
10 |
+
from bs4 import BeautifulSoup
|
11 |
+
|
12 |
+
from utils.Decorator import retry
|
13 |
+
|
14 |
+
st.set_page_config(
|
15 |
+
page_title='工具箱',
|
16 |
+
page_icon='🔨',
|
17 |
+
layout='wide',
|
18 |
+
)
|
19 |
+
|
20 |
+
with st.sidebar:
|
21 |
+
side_bar_links()
|
22 |
+
|
23 |
+
|
24 |
+
def add():
|
25 |
+
ref_list: list = st.session_state.get('reference_list')
|
26 |
+
|
27 |
+
_data = {
|
28 |
+
'title': st.session_state.get('title'),
|
29 |
+
'pmid': st.session_state.get('pmid').replace('PMID:', '').replace(' ', ''),
|
30 |
+
'pmc': st.session_state.get('pmc').replace('PMCID:', '').replace(' ', ''),
|
31 |
+
'doi': st.session_state.get('doi').replace('DOI:', '').replace(' ', ''),
|
32 |
+
}
|
33 |
+
if _data in ref_list:
|
34 |
+
st.toast('already exist')
|
35 |
+
else:
|
36 |
+
ref_list.append(_data)
|
37 |
+
st.session_state.reference_list = ref_list
|
38 |
+
yaml_str = yaml.dump(ref_list)
|
39 |
+
st.session_state.reference_text = yaml_str
|
40 |
+
|
41 |
+
st.session_state['title'] = ''
|
42 |
+
st.session_state['pmid'] = ''
|
43 |
+
st.session_state['pmc'] = ''
|
44 |
+
st.session_state['doi'] = ''
|
45 |
+
|
46 |
+
|
47 |
+
def reset():
|
48 |
+
st.session_state.reference_list = []
|
49 |
+
st.session_state.reference_text = ''
|
50 |
+
|
51 |
+
|
52 |
+
# def anal_ml():
|
53 |
+
# nlm_str: str = st.session_state.get('nlm_text')
|
54 |
+
# nlm_list = nlm_str.split('.', 4)
|
55 |
+
# title = nlm_list[1]
|
56 |
+
# id_list = nlm_list[-1].split('; ')
|
57 |
+
# if len(id_list) > 1:
|
58 |
+
# pmc = id_list[-1]
|
59 |
+
# else:
|
60 |
+
# pmc = ''
|
61 |
+
# base_list = id_list[0].split('. ')
|
62 |
+
# doi = base_list[0]
|
63 |
+
# pmid = base_list[1]
|
64 |
+
#
|
65 |
+
# _data = {
|
66 |
+
# 'title': title[1:] if title.startswith(' ') else title,
|
67 |
+
# 'pmid': pmid.replace('PMID:', '').replace(' ', ''),
|
68 |
+
# 'pmc': pmc.replace('PMCID:', '').replace(' ', '').replace('.', ''),
|
69 |
+
# 'doi': doi.replace('doi:', '').replace(' ', ''),
|
70 |
+
# }
|
71 |
+
#
|
72 |
+
# ref_list: list = st.session_state.get('reference_list')
|
73 |
+
#
|
74 |
+
# if _data in ref_list:
|
75 |
+
# st.toast('already exist')
|
76 |
+
# else:
|
77 |
+
# ref_list.append(_data)
|
78 |
+
# st.session_state.reference_list = ref_list
|
79 |
+
# yaml_str = yaml.dump(ref_list)
|
80 |
+
# st.session_state.reference_text = yaml_str
|
81 |
+
#
|
82 |
+
# st.session_state['nlm_text'] = ''
|
83 |
+
|
84 |
+
|
85 |
+
def get_data():
|
86 |
+
term: str = st.session_state.get('term_text')
|
87 |
+
term = term.replace('\r', ' ').replace('\n', '')
|
88 |
+
_data = __get_info(term)
|
89 |
+
|
90 |
+
ref_list: list = st.session_state.get('reference_list')
|
91 |
+
|
92 |
+
if _data in ref_list:
|
93 |
+
st.toast('already exist')
|
94 |
+
else:
|
95 |
+
ref_list.append(_data)
|
96 |
+
st.session_state.reference_list = ref_list
|
97 |
+
yaml_str = yaml.dump(ref_list, width=999)
|
98 |
+
st.session_state.reference_text = yaml_str
|
99 |
+
|
100 |
+
st.session_state['term_text'] = ''
|
101 |
+
|
102 |
+
|
103 |
+
@retry(delay=random.uniform(2.0, 5.0))
|
104 |
+
def __get_info(pmid: str) -> Dict[str, Any]:
|
105 |
+
url = f'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id={pmid}&retmode=xml'
|
106 |
+
|
107 |
+
headers = {
|
108 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
109 |
+
}
|
110 |
+
|
111 |
+
response = requests.request("GET", url, headers=headers, timeout=10)
|
112 |
+
|
113 |
+
if response.status_code == 200:
|
114 |
+
soup = BeautifulSoup(response.text, 'xml')
|
115 |
+
|
116 |
+
title = soup.find('Article').find('ArticleTitle').text if soup.find('Article') else None
|
117 |
+
|
118 |
+
doi_block = soup.find('ArticleIdList').find('ArticleId', {'IdType': 'doi'})
|
119 |
+
if doi_block:
|
120 |
+
doi = doi_block.text
|
121 |
+
else:
|
122 |
+
doi = ''
|
123 |
+
logger.warning('DOI not found')
|
124 |
+
|
125 |
+
pmc_block = soup.find('ArticleIdList').find('ArticleId', {'IdType': 'pmc'})
|
126 |
+
if pmc_block:
|
127 |
+
pmc = pmc_block.text.replace('PMC', '')
|
128 |
+
else:
|
129 |
+
pmc = ''
|
130 |
+
|
131 |
+
return {
|
132 |
+
'title': title,
|
133 |
+
'pmid': pmid,
|
134 |
+
'pmc': pmc,
|
135 |
+
'doi': doi
|
136 |
+
}
|
137 |
+
|
138 |
+
|
139 |
+
def del_item():
|
140 |
+
index: int = st.session_state.get('delete_id')
|
141 |
+
ref_list: list = st.session_state.get('reference_list')
|
142 |
+
|
143 |
+
ref_list.pop(index)
|
144 |
+
|
145 |
+
yaml_str = yaml.dump(ref_list, width=999)
|
146 |
+
st.session_state.reference_text = yaml_str
|
147 |
+
st.session_state.reference_list = ref_list
|
148 |
+
|
149 |
+
|
150 |
+
st.title("引用格式化")
|
151 |
+
|
152 |
+
col1, col2 = st.columns([1, 1], gap="medium")
|
153 |
+
|
154 |
+
if 'reference_list' not in st.session_state:
|
155 |
+
st.session_state.reference_list = []
|
156 |
+
|
157 |
+
if 'reference_text' not in st.session_state:
|
158 |
+
st.session_state.reference_text = ''
|
159 |
+
|
160 |
+
with col1:
|
161 |
+
with st.expander('manual'):
|
162 |
+
st.text_input('title', key='title')
|
163 |
+
|
164 |
+
col1_1, col1_2 = st.columns([1, 1], gap="small")
|
165 |
+
col1_1.text_input('pmid', key='pmid')
|
166 |
+
col1_2.text_input('pmc', key='pmc')
|
167 |
+
|
168 |
+
st.text_input('doi', key='doi')
|
169 |
+
|
170 |
+
col2_1, col2_2 = st.columns([1, 1], gap="small")
|
171 |
+
col2_1.button('add', use_container_width=True, type='primary', on_click=add)
|
172 |
+
col2_2.button('reset', use_container_width=True, on_click=reset)
|
173 |
+
|
174 |
+
st.text_input('Search', key='term_text')
|
175 |
+
st.button('add', use_container_width=True, on_click=get_data)
|
176 |
+
|
177 |
+
if len(st.session_state.get('reference_list')) > 0:
|
178 |
+
st.divider()
|
179 |
+
|
180 |
+
st.write('共有', len(st.session_state.get('reference_list')), '条引用')
|
181 |
+
|
182 |
+
col3_1, col3_2 = st.columns([2, 1], gap='small')
|
183 |
+
col3_1.number_input(
|
184 |
+
'id',
|
185 |
+
min_value=0,
|
186 |
+
max_value=len(st.session_state.get('reference_list')) - 1,
|
187 |
+
key='delete_id',
|
188 |
+
label_visibility='collapsed'
|
189 |
+
)
|
190 |
+
col3_2.button('delete', type='primary', on_click=del_item)
|
191 |
+
|
192 |
+
with col2:
|
193 |
+
with st.container(height=486, border=True):
|
194 |
+
st.write(st.session_state.get('reference_list'))
|
195 |
+
|
196 |
+
st.code(st.session_state.get('reference_text'), language='yaml')
|
pages/Reformat.py
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import re
|
2 |
+
|
3 |
+
import streamlit as st
|
4 |
+
|
5 |
+
from ui.Component import side_bar_links
|
6 |
+
|
7 |
+
st.set_page_config(
|
8 |
+
page_title='工具箱',
|
9 |
+
page_icon='🔨',
|
10 |
+
layout='wide',
|
11 |
+
)
|
12 |
+
|
13 |
+
with st.sidebar:
|
14 |
+
side_bar_links()
|
15 |
+
|
16 |
+
st.title("格式化工具")
|
17 |
+
|
18 |
+
|
19 |
+
def re_format(origin_str: str) -> str:
|
20 |
+
new_str = origin_str.replace('\r', '').replace('\n', '')
|
21 |
+
|
22 |
+
matches = re.findall(r'\[\s*\d+(?:,\s*\d+)*]', new_str)
|
23 |
+
|
24 |
+
for match in matches:
|
25 |
+
match_str: str = match
|
26 |
+
new_ref = ''.join([
|
27 |
+
f"[^{ind.replace(' ', '')}]"
|
28 |
+
for ind in match_str.replace('[', '').replace(']', '').split(',')
|
29 |
+
])
|
30 |
+
new_str = new_str.replace(match, new_ref)
|
31 |
+
|
32 |
+
matches = re.findall(r'\[\s*\d+(?:-\s*\d+)*]', new_str)
|
33 |
+
|
34 |
+
for match in matches:
|
35 |
+
match_str: str = match
|
36 |
+
match_str = match_str.replace('[', '').replace(']', '')
|
37 |
+
a = int(match_str.split('-')[0].strip())
|
38 |
+
b = int(match_str.split('-')[-1].strip())
|
39 |
+
|
40 |
+
new_ref = ''.join([
|
41 |
+
f'[^{i}]'
|
42 |
+
for i in range(a, b + 1)
|
43 |
+
])
|
44 |
+
new_str = new_str.replace(match, new_ref)
|
45 |
+
|
46 |
+
return new_str
|
47 |
+
|
48 |
+
|
49 |
+
col1, col2 = st.columns([1, 1], gap="medium")
|
50 |
+
|
51 |
+
if 'markdown_text' not in st.session_state:
|
52 |
+
st.session_state.markdown_text = ''
|
53 |
+
|
54 |
+
with col1.container(height=520, border=True):
|
55 |
+
st.markdown(st.session_state.markdown_text)
|
56 |
+
|
57 |
+
with col2:
|
58 |
+
st.code(st.session_state.markdown_text, language='markdown')
|
59 |
+
|
60 |
+
if prompt := st.chat_input():
|
61 |
+
response = re_format(prompt)
|
62 |
+
|
63 |
+
st.session_state.markdown_text = response
|
64 |
+
|
65 |
+
st.rerun()
|
pages/TextToImage.py
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
import requests
|
4 |
+
import urllib3
|
5 |
+
|
6 |
+
import streamlit as st
|
7 |
+
from loguru import logger
|
8 |
+
|
9 |
+
from ui.Component import side_bar_links
|
10 |
+
|
11 |
+
st.set_page_config(
|
12 |
+
page_title='工具箱',
|
13 |
+
page_icon='🔨',
|
14 |
+
layout='wide',
|
15 |
+
)
|
16 |
+
|
17 |
+
with st.sidebar:
|
18 |
+
side_bar_links()
|
19 |
+
|
20 |
+
st.text_input('Api_key', type='password', key='api_key')
|
21 |
+
|
22 |
+
st.title('CogView 文生图')
|
23 |
+
|
24 |
+
|
25 |
+
def generate_image_url(prompt: str) -> str:
|
26 |
+
from zhipuai import ZhipuAI
|
27 |
+
|
28 |
+
api = st.session_state.get('api_key')
|
29 |
+
if api != '':
|
30 |
+
client = ZhipuAI(api_key=api) # 请填写您自己的APIKey
|
31 |
+
|
32 |
+
response = client.images.generations(
|
33 |
+
model="cogview-3",
|
34 |
+
prompt=prompt,
|
35 |
+
)
|
36 |
+
|
37 |
+
return response.data[0].url
|
38 |
+
else:
|
39 |
+
st.error('请先输入API!')
|
40 |
+
|
41 |
+
|
42 |
+
def download_img(img_url: str) -> str:
|
43 |
+
r = requests.get(img_url, stream=True)
|
44 |
+
if r.status_code == 200:
|
45 |
+
filename = img_url.split('/')[-1]
|
46 |
+
filepath = f'/home/aye/Service/MyTools/image/{filename}'
|
47 |
+
open(filepath, 'wb').write(r.content)
|
48 |
+
del r
|
49 |
+
return filepath
|
50 |
+
else:
|
51 |
+
st.error('download fail')
|
52 |
+
|
53 |
+
|
54 |
+
if 'filepath' not in st.session_state:
|
55 |
+
st.session_state['filepath'] = ''
|
56 |
+
|
57 |
+
if os.path.exists(st.session_state.get('filepath')):
|
58 |
+
with st.chat_message('user'):
|
59 |
+
st.write(st.session_state.get('image_prompt'))
|
60 |
+
with st.chat_message('ai'):
|
61 |
+
path: str = st.session_state.get('filepath')
|
62 |
+
st.image(path)
|
63 |
+
with open(path, "rb") as file:
|
64 |
+
btn = st.download_button(
|
65 |
+
label="下载",
|
66 |
+
data=file,
|
67 |
+
file_name=path.split('/')[-1],
|
68 |
+
mime="image/png"
|
69 |
+
)
|
70 |
+
|
71 |
+
if image_prompt := st.chat_input(key='image_prompt'):
|
72 |
+
with st.chat_message('user'):
|
73 |
+
logger.info(image_prompt)
|
74 |
+
st.write(image_prompt)
|
75 |
+
|
76 |
+
with st.spinner('正在生成图片...'):
|
77 |
+
url = generate_image_url(image_prompt)
|
78 |
+
logger.info(url)
|
79 |
+
|
80 |
+
with st.spinner('正在下载图片...'):
|
81 |
+
path = download_img(url)
|
82 |
+
st.session_state['filepath'] = path
|
83 |
+
|
84 |
+
with st.chat_message('ai'):
|
85 |
+
st.image(path)
|
86 |
+
with open(path, "rb") as file:
|
87 |
+
btn = st.download_button(
|
88 |
+
label="下载",
|
89 |
+
data=file,
|
90 |
+
file_name=url.split('/')[-1],
|
91 |
+
mime="image/png"
|
92 |
+
)
|
pages/Translate.py
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
import httpx
|
4 |
+
import streamlit as st
|
5 |
+
import yaml
|
6 |
+
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
|
7 |
+
from langchain_core.prompts import ChatPromptTemplate
|
8 |
+
from langchain_openai import ChatOpenAI
|
9 |
+
from loguru import logger
|
10 |
+
|
11 |
+
from ui.Component import side_bar_links
|
12 |
+
|
13 |
+
st.set_page_config(
|
14 |
+
page_title='工具箱',
|
15 |
+
page_icon='🔨',
|
16 |
+
layout='wide',
|
17 |
+
)
|
18 |
+
|
19 |
+
st.title("一键生成翻译总结")
|
20 |
+
|
21 |
+
with st.sidebar:
|
22 |
+
side_bar_links()
|
23 |
+
|
24 |
+
st.toggle('去除换行', key='trans_reformat')
|
25 |
+
st.toggle('总结', key='trans_conclusion')
|
26 |
+
|
27 |
+
st.toggle('输出格式', key='trans_text_mode')
|
28 |
+
if st.session_state.get('trans_text_mode'):
|
29 |
+
st.caption('markdown')
|
30 |
+
else:
|
31 |
+
st.caption('latex')
|
32 |
+
|
33 |
+
|
34 |
+
def get_translate_and_conclude(question: str, step: int):
|
35 |
+
if step == 0:
|
36 |
+
_prompt = ChatPromptTemplate.from_messages(
|
37 |
+
[
|
38 |
+
SystemMessage("You are an AI academic assistant and should answer user questions rigorously."),
|
39 |
+
("human",
|
40 |
+
"你将收到一个论文的片段。首先,将这段文本以学术风格**翻译为中文**,不要漏句。对于所有的特殊符号和latex代码,请保持原样不要改变。"
|
41 |
+
"对于文中一些显得与上下文突兀的数字,很大可能是引用文献,请使用latex语法将它们表示为一个上标,并使用美元符号包围,如$^2$。这是你要翻译的文献片段:\n{question}"),
|
42 |
+
]
|
43 |
+
)
|
44 |
+
elif step == 1:
|
45 |
+
_prompt = ChatPromptTemplate.from_messages(
|
46 |
+
[
|
47 |
+
SystemMessage(content="You are an AI academic assistant and should answer user questions rigorously."),
|
48 |
+
HumanMessage(
|
49 |
+
content=f"""首先,将这段文本**翻译为中文**,不要漏句。对于所有的特殊符号和latex代码,请保持原样不要改变:
|
50 |
+
{st.session_state.translate_messages[-3]}"""
|
51 |
+
),
|
52 |
+
AIMessage(content=str(st.session_state.translate_messages[-2])),
|
53 |
+
HumanMessage(content=question),
|
54 |
+
]
|
55 |
+
)
|
56 |
+
else:
|
57 |
+
raise Exception("Wrong step value")
|
58 |
+
|
59 |
+
|
60 |
+
llm = ChatOpenAI(
|
61 |
+
model_name="gpt-3.5-turbo",
|
62 |
+
temperature=0,
|
63 |
+
openai_api_key=st.secrets['gpt_key'],
|
64 |
+
streaming=True
|
65 |
+
)
|
66 |
+
|
67 |
+
chain = _prompt | llm
|
68 |
+
|
69 |
+
if step == 0:
|
70 |
+
llm_result = chain.stream({"question": question})
|
71 |
+
else:
|
72 |
+
llm_result = chain.stream({"question": question})
|
73 |
+
|
74 |
+
return llm_result
|
75 |
+
|
76 |
+
|
77 |
+
col1, col2 = st.columns([1, 1], gap="medium")
|
78 |
+
|
79 |
+
if 'translate_messages' not in st.session_state:
|
80 |
+
st.session_state.translate_messages = []
|
81 |
+
|
82 |
+
if 'markdown_text' not in st.session_state:
|
83 |
+
st.session_state.markdown_text = ''
|
84 |
+
|
85 |
+
chat_container = col1.container(height=610, border=False)
|
86 |
+
|
87 |
+
with chat_container:
|
88 |
+
for message in st.session_state.translate_messages:
|
89 |
+
icon = 'logo.png' if message['role'] != 'user' else None
|
90 |
+
with st.chat_message(message['role']):
|
91 |
+
st.markdown(message['content'])
|
92 |
+
|
93 |
+
with col2:
|
94 |
+
if st.session_state.markdown_text != '':
|
95 |
+
with st.container(height=520, border=True):
|
96 |
+
st.markdown(st.session_state.markdown_text)
|
97 |
+
if st.session_state.get('trans_text_mode'):
|
98 |
+
st.code(st.session_state.markdown_text, language='markdown')
|
99 |
+
else:
|
100 |
+
st.code(st.session_state.markdown_text, language='latex')
|
101 |
+
|
102 |
+
if prompt := st.chat_input():
|
103 |
+
st.session_state.translate_messages = []
|
104 |
+
if st.session_state.get('trans_reformat'):
|
105 |
+
prompt = prompt.replace("\n", " ").replace("\r", "")
|
106 |
+
|
107 |
+
logger.info(f'[translate]: {prompt}')
|
108 |
+
prompt = prompt.replace('$', r'\$')
|
109 |
+
|
110 |
+
chat_container.chat_message("human").write(prompt)
|
111 |
+
st.session_state.translate_messages.append({'role': 'user', 'content': prompt})
|
112 |
+
|
113 |
+
response = get_translate_and_conclude(prompt, 0)
|
114 |
+
translate_result = chat_container.chat_message("ai").write_stream(response)
|
115 |
+
st.session_state.translate_messages.append({'role': 'assistant', 'content': translate_result})
|
116 |
+
|
117 |
+
if st.session_state.get('trans_conclusion'):
|
118 |
+
query = "接下来,请用两到四句话总结一下这段文本的内容"
|
119 |
+
chat_container.chat_message("human").write(query)
|
120 |
+
st.session_state.translate_messages.append({'role': 'user', 'content': query})
|
121 |
+
|
122 |
+
response = get_translate_and_conclude(query, 1)
|
123 |
+
conclusion_result = chat_container.chat_message("ai").write_stream(response)
|
124 |
+
logger.info(f"(conclude): {conclusion_result}")
|
125 |
+
st.session_state.translate_messages.append({'role': 'assistant', 'content': conclusion_result})
|
126 |
+
|
127 |
+
if st.session_state.get('trans_text_mode'):
|
128 |
+
markdown_text = f"""{prompt}\t\r\n{translate_result}\t\r\n> {conclusion_result}"""
|
129 |
+
else:
|
130 |
+
markdown_text = f"""{prompt}\n\n{translate_result}\n\n\\tbox{{ {conclusion_result} }}"""
|
131 |
+
markdown_text = markdown_text.replace('%', r'\%')
|
132 |
+
st.session_state.markdown_text = markdown_text
|
133 |
+
else:
|
134 |
+
markdown_text = f"""{prompt}\t\r\n{translate_result}"""
|
135 |
+
st.session_state.markdown_text = markdown_text
|
136 |
+
|
137 |
+
st.rerun()
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
loguru
|
2 |
+
bs4
|
3 |
+
PyYAML
|
4 |
+
langchain
|
5 |
+
langchain_openai
|
6 |
+
lxml
|
ui/Component.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
3 |
+
|
4 |
+
def side_bar_links():
|
5 |
+
st.header('工具箱')
|
6 |
+
|
7 |
+
st.page_link('App.py', label='Home', icon='🏠')
|
8 |
+
st.page_link('pages/Reformat.py', label='文本格式化', icon='📖')
|
9 |
+
st.page_link('pages/Reference.py', label='引用文献生成', icon='📙')
|
10 |
+
st.page_link('pages/Translate.py', label='翻译总结工具', icon='🌐')
|
11 |
+
st.page_link('pages/TextToImage.py', label='文生图', icon='🎨')
|
12 |
+
|
13 |
+
st.divider()
|
utils/Decorator.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
from functools import wraps
|
3 |
+
from typing import Callable, Any
|
4 |
+
from loguru import logger
|
5 |
+
|
6 |
+
|
7 |
+
def retry(retries: int = 3, delay: float = 1) -> Callable:
|
8 |
+
"""
|
9 |
+
为函数提供重试逻辑的装饰器。
|
10 |
+
|
11 |
+
参数:
|
12 |
+
retries (int): 最大重试次数,默认为3。
|
13 |
+
delay (float): 两次重试之间的延迟时间(秒),默认为1。
|
14 |
+
|
15 |
+
返回:
|
16 |
+
Callable: 被装饰的函数。
|
17 |
+
|
18 |
+
异常:
|
19 |
+
ValueError: 如果retries小于1或delay小于等于0,则抛出此异常。
|
20 |
+
"""
|
21 |
+
if retries < 1 or delay <= 0:
|
22 |
+
raise ValueError('Wrong param')
|
23 |
+
|
24 |
+
def decorator(func: Callable) -> Callable:
|
25 |
+
@wraps(func)
|
26 |
+
def wrapper(*args, **kwargs) -> Any:
|
27 |
+
for i in range(1, retries + 1):
|
28 |
+
try:
|
29 |
+
return func(*args, **kwargs)
|
30 |
+
except Exception as e:
|
31 |
+
if i == retries:
|
32 |
+
logger.error(f'Error: {repr(e)}.')
|
33 |
+
logger.error(f'"{func.__name__}()" failed after {retries} retries.')
|
34 |
+
break
|
35 |
+
else:
|
36 |
+
logger.debug(f'Error: {repr(e)} -> Retrying...')
|
37 |
+
time.sleep(delay)
|
38 |
+
|
39 |
+
return wrapper
|
40 |
+
|
41 |
+
return decorator
|
utils/__init__.py
ADDED
File without changes
|