Download app.py from aresspark/learn: direct link, hf CLI and curl.
- Browser
- Download file 12.3 kB
-
https://huggingface.co/spaces/aresspark/learn/resolve/main/app.py
- Command line
-
hf download hf://spaces/aresspark/learn/app.py
-
curl -L -o app.py https://huggingface.co/spaces/aresspark/learn/resolve/main/app.py
12.3 kB
| # !/usr/bin/env python3 | |
| """ | |
| ==== No Bugs in code, just some Random Unexpected FEATURES ==== | |
| ┌─────────────────────────────────────────────────────────────┐ | |
| │┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐│ | |
| ││Esc│!1 │@2 │#3 │$4 │%5 │^6 │&7 │*8 │(9 │)0 │_- │+= │|\ │`~ ││ | |
| │├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤│ | |
| ││ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{[ │}] │ BS ││ | |
| │├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤│ | |
| ││ Ctrl │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter ││ | |
| │├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┬───┤│ | |
| ││ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│Shift │Fn ││ | |
| │└─────┬──┴┬──┴──┬┴───┴───┴───┴───┴───┴──┬┴───┴┬──┴┬─────┴───┘│ | |
| │ │Fn │ Alt │ Space │ Alt │Win│ HHKB │ | |
| │ └───┴─────┴───────────────────────┴─────┴───┘ │ | |
| └─────────────────────────────────────────────────────────────┘ | |
| web端测试LLM效果。 | |
| Author: pankeyu | |
| Date: 2023/03/17 | |
| """ | |
| import os | |
| import re | |
| import time | |
| import json | |
| import datetime | |
| import torch | |
| import streamlit as st | |
| import pandas as pd | |
| from transformers import AutoTokenizer, AutoModel | |
| torch.set_default_tensor_type(torch.cuda.HalfTensor) | |
| st.set_page_config( | |
| page_title="LLM Playground", | |
| layout="wide" | |
| ) | |
| device = 'cuda:0' | |
| max_new_tokens = 300 | |
| model_path = "checkpoints/model_1000" | |
| LOG_PATH = 'log' | |
| DATASET_PATH = 'data' | |
| LOG_FILE = 'web_log.log' | |
| FEEDBACK_FILE = 'human_feedback.log' | |
| DATASET_FILE = 'dataset.jsonl' | |
| if not os.path.exists(DATASET_PATH): | |
| os.makedirs(DATASET_PATH) | |
| if not os.path.exists(LOG_PATH): | |
| os.makedirs(LOG_PATH) | |
| if not os.path.exists(os.path.join(DATASET_PATH, DATASET_FILE)): | |
| with open(os.path.join(DATASET_PATH, DATASET_FILE), 'w', encoding='utf8') as f: | |
| print('标注数据集已创建。') | |
| if 'model_out' not in st.session_state: | |
| st.session_state['model_out'] = '' | |
| st.session_state['used_time'] = 0.0 | |
| if 'model' not in st.session_state: | |
| with st.spinner('Loading Model...'): | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| model_path, | |
| trust_remote_code=True | |
| ) | |
| model = AutoModel.from_pretrained( | |
| model_path, | |
| trust_remote_code=True | |
| ).half().to(device) | |
| st.session_state['model'] = model | |
| st.session_state['tokenizer'] = tokenizer | |
| def start_evaluate_page(): | |
| """ | |
| 模型测试页面。 | |
| """ | |
| c1, c2 = st.columns([5, 5]) | |
| with c1: | |
| with st.expander('⚙️ Instruct 设定(Instruct Setting)', expanded=True): | |
| instruct = st.text_area( | |
| f'Instruct', | |
| value='你现在是一个很厉害的阅读理解器,严格按照人类指令进行回答。', | |
| height=250 | |
| ) | |
| with c2: | |
| with st.expander('💬 对话输入框', expanded=True): | |
| current_input = st.text_area( | |
| '当前用户输入', | |
| value='帮我提取出下面句子中所有的SPO,并输出为json,不要做多余的回复:\n\n《琅琊榜》是由山东影视传媒集团、山东影视制作有限公司、北京儒意欣欣影业投资有限公司、北京和颂天地影视文化有限公司、北京圣基影业有限公司、东阳正午阳光影视有限公司联合出品,由孔笙、李雪执导,胡歌、刘涛、王凯、黄维德、陈龙、吴磊、高鑫等主演的古装剧。', | |
| height=200 | |
| ) | |
| bt = st.button('Generate') | |
| if bt: | |
| start = time.time() | |
| with st.spinner('生成中...'): | |
| with torch.no_grad(): | |
| input_text = f"Instruction: {instruct}\n" | |
| input_text += f"Input: {current_input}\n" | |
| input_text += f"Answer:" | |
| batch = st.session_state['tokenizer'](input_text, return_tensors="pt") | |
| out = st.session_state['model'].generate( | |
| input_ids=batch["input_ids"].to(device), | |
| max_new_tokens=max_new_tokens, | |
| temperature=0 | |
| ) | |
| out_text = st.session_state['tokenizer'].decode(out[0]) | |
| answer = out_text.split('Answer: ')[-1] | |
| used_time = round(time.time() - start, 2) | |
| st.session_state['model_out'] = answer | |
| st.session_state['used_time'] = used_time | |
| with open(os.path.join(LOG_PATH, LOG_FILE), 'a', encoding='utf8') as f: | |
| log_dict = { | |
| 'time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), | |
| 'used_seconds': used_time, | |
| 'instruct': instruct, | |
| 'input': current_input, | |
| 'model_output': st.session_state['model_out'] | |
| } | |
| f.write(f'{json.dumps(log_dict, ensure_ascii=False)}\n') | |
| if st.session_state['model_out']: | |
| c1, c2 = st.columns([5, 5]) | |
| with c2: | |
| with st.expander(f"🤖 当前模型输出({st.session_state['used_time']}s)", expanded=True): | |
| answer = st.session_state['model_out'] | |
| if len(answer) < 200: | |
| height = 100 | |
| elif len(answer) < 500: | |
| height = 200 | |
| else: | |
| height = 300 | |
| st.text_area( | |
| '', | |
| value=f'{answer}', | |
| height=height | |
| ) | |
| human_feedback = st.radio( | |
| "模型生成结果是否正确 👇", | |
| ["🤓 不反馈", "😊 正确", "😡 错误"], | |
| key="visibility", | |
| horizontal=True | |
| ) | |
| if human_feedback in ["😡 错误", "😊 正确"]: | |
| if human_feedback == "😡 错误": | |
| error_feedback = st.text_area( | |
| '[error feedback]', | |
| placeholder='感谢您的反馈,请填写问题的正确答案以帮助模型改进 🥺' | |
| ) | |
| current_feedback = { | |
| 'instruct': instruct, | |
| 'input': current_input, | |
| 'model_output': st.session_state['model_out'], | |
| 'human_feedback': error_feedback, | |
| 'is_error': True | |
| } | |
| else: | |
| advice = st.text_area( | |
| '[advice feedback]', | |
| placeholder='请输入您的反馈...' | |
| ) | |
| current_feedback = { | |
| 'instruct': instruct, | |
| 'input': current_input, | |
| 'model_output': st.session_state['model_out'], | |
| 'human_feedback': advice, | |
| 'is_error': False | |
| } | |
| submit_button = st.button('提交') | |
| if submit_button: | |
| with open(os.path.join(LOG_PATH, FEEDBACK_FILE), 'a', encoding='utf8') as f: | |
| f.write(f'{json.dumps(current_feedback, ensure_ascii=False)}\n') | |
| st.success('感谢您的反馈~', icon="✅") | |
| with c1: | |
| with st.expander(f'💻 json 解析结果', expanded=True): | |
| st.markdown(answer) | |
| json_res = re.findall(r'```json(.*)```', answer.replace('\n', '')) | |
| if len(json_res): | |
| json_res = json_res[0] | |
| try: | |
| json_res = json.loads(json_res) | |
| st.write(json_res) | |
| except: | |
| pass | |
| def read_dataset_file(): | |
| """ | |
| 读取本地标注的数据集。 | |
| """ | |
| temp_dict = {} | |
| with open(os.path.join(DATASET_PATH, DATASET_FILE), 'r', encoding='utf8') as f: | |
| for line in f.readlines(): | |
| line = json.loads(line) | |
| for key, value in line.items(): | |
| if key not in temp_dict: | |
| temp_dict[key] = [] | |
| temp_dict[key].append(value) | |
| df = pd.DataFrame.from_dict(temp_dict) | |
| return df | |
| def start_label_page(): | |
| """ | |
| 数据集标注页面。 | |
| """ | |
| c1, c2 = st.columns([4, 6]) | |
| with c1: | |
| with st.expander(f'💻 标注界面', expanded=True): | |
| instruct = st.text_area( | |
| 'Human Instruct', | |
| value='你现在是一个很厉害的阅读理解器,严格按照人类指令进行回答。' | |
| ) | |
| inputs = st.text_area( | |
| 'Human Input', | |
| placeholder='输入人工构造问题,例如: 帮我抽取下面句子的SPO,用json格式返回...' | |
| ) | |
| answer = st.text_area( | |
| 'Human Output', | |
| placeholder='输入人工构造答案,例如:\n 好的,以下是抽取SPO的json信息:\n```json\n{\n"subject": "孙红雷", \n"predicate": "年龄", \n"object": "52岁"\n}\n```', | |
| height=500 | |
| ) | |
| save_button = st.button('Save') | |
| if save_button: | |
| with open(os.path.join(DATASET_PATH, DATASET_FILE), 'a', encoding='utf8') as f: | |
| context = f'Instruction: {instruct}\nInput: {inputs}\nAnswer: ' | |
| current_sample = { | |
| 'context': context, | |
| 'target': answer | |
| } | |
| f.write(json.dumps(current_sample, ensure_ascii=False) + '\n') | |
| st.success('数据已保存!', icon="✅") | |
| st.session_state['dataset_df'] = read_dataset_file() | |
| with c2: | |
| if 'dataset_df' not in st.session_state: | |
| st.session_state['dataset_df'] = read_dataset_file() | |
| with st.expander(f"📚 本地数据集(共 {len(st.session_state['dataset_df'])} 条)", expanded=True): | |
| st.dataframe(st.session_state['dataset_df'], height=820) | |
| refresh_button = st.button('刷新数据集') | |
| if refresh_button: | |
| st.session_state['dataset_df'] = read_dataset_file() | |
| def main(): | |
| """ | |
| 主函数流程。 | |
| """ | |
| logo = '[%E3%83%8E)](https://github.com/HarderThenHarder/transformers_tasks)' | |
| st.markdown(logo) | |
| evaluate_page, label_page = st.tabs(['evaluate_page', 'label_page']) | |
| with evaluate_page: | |
| start_evaluate_page() | |
| with label_page: | |
| start_label_page() | |
| if __name__ == '__main__': | |
| main() | |