()
| 149 | |
| 150 | |
| 151 | def main(): |
| 152 | """""" |
| 153 | set_env(input_panel_fixed=False, output_animation=False) |
| 154 | put_markdown(""" |
| 155 | # ChatGPT |
| 156 | A ChatGPT client implemented with PyWebIO. [Source Code](https://github.com/pywebio/PyWebIO/blob/dev/demos/chatgpt.py) |
| 157 | TIPS: refresh page to open a new chat. |
| 158 | """) |
| 159 | put_select('model', ['gpt-3.5-turbo', 'gpt-4'], label='Model') |
| 160 | |
| 161 | openai_config = get_openai_config() |
| 162 | client = OpenAI(api_key=openai_config['api_key'], base_url=openai_config['api_base']) |
| 163 | |
| 164 | bot = ChatGPT(client=client, model=pin.model) |
| 165 | pin_on_change('model', lambda v: bot.set_model(v)) |
| 166 | while True: |
| 167 | form = input_group('', [ |
| 168 | input(name='msg', placeholder='Ask ChatGPT'), |
| 169 | actions(name='cmd', buttons=['Send', 'Multi-line Input', 'Save Chat']) |
| 170 | ]) |
| 171 | if form['cmd'] == 'Multi-line Input': |
| 172 | form['msg'] = textarea(value=form['msg']) |
| 173 | elif form['cmd'] == 'Save Chat': |
| 174 | messages = [ |
| 175 | msg['content'] if msg['role'] == 'user' else f"> {msg['content']}" |
| 176 | for msg in bot.messages() |
| 177 | ] |
| 178 | download(f"chatgpt_{time.strftime('%Y%m%d%H%M%S')}.md", |
| 179 | '\n\n'.join(messages).encode('utf8')) |
| 180 | continue |
| 181 | |
| 182 | user_msg = form['msg'] |
| 183 | if not user_msg: |
| 184 | continue |
| 185 | |
| 186 | put_info(put_text(user_msg, inline=True)) |
| 187 | |
| 188 | with use_scope(f'reply-{int(time.time())}'): |
| 189 | put_loading('grow', 'info') |
| 190 | try: |
| 191 | reply_chunks = bot.ask_stream(user_msg) |
| 192 | except Exception as e: |
| 193 | popup('ChatGPT Error', put_error(e)) |
| 194 | continue |
| 195 | finally: |
| 196 | clear() # clear loading |
| 197 | for chunk in reply_chunks: |
| 198 | put_text(chunk, inline=True) |
| 199 | clear() # clear above text |
| 200 | put_markdown(reply_chunks.result()) |
| 201 | |
| 202 | if bot.latest_finish_reason() == 'length': |
| 203 | put_error('Incomplete model output due to max_tokens parameter or token limit.') |
| 204 | elif bot.latest_finish_reason() == 'content_filter': |
| 205 | put_warning("Omitted content due to a flag from OpanAI's content filters.") |
| 206 | |
| 207 | |
| 208 | if __name__ == '__main__': |
nothing calls this directly
no test coverage detected
searching dependent graphs…