CoolFace
Apppublic

DragonCard/ChuanhuChatGPT

sourceHugging Facemitupdated 4y agoView on Hugging Face
0likes
chat_func.py423 linesDownload Raw Back to root
1# -*- coding:utf-8 -*-2from __future__ import annotations3from typing import TYPE_CHECKING, List4 5import logging6import json7import os8import requests9 10from tqdm import tqdm11import colorama12from duckduckgo_search import ddg13 14from presets import *15from llama_func import *16from utils import *17 18# logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s")19 20if TYPE_CHECKING:21    from typing import TypedDict22 23    class DataframeData(TypedDict):24        headers: List[str]25        data: List[List[str | int | bool]]26 27 28initial_prompt = "You are a helpful assistant."29API_URL = "https://api.openai.com/v1/chat/completions"30HISTORY_DIR = "history"31TEMPLATES_DIR = "templates"32 33def get_response(34    openai_api_key, system_prompt, history, temperature, top_p, stream, selected_model35):36    headers = {37        "Content-Type": "application/json",38        "Authorization": f"Bearer {openai_api_key}",39    }40 41    history = [construct_system(system_prompt), *history]42 43    payload = {44        "model": selected_model,45        "messages": history,  # [{"role": "user", "content": f"{inputs}"}],46        "temperature": temperature,  # 1.0,47        "top_p": top_p,  # 1.0,48        "n": 1,49        "stream": stream,50        "presence_penalty": 0,51        "frequency_penalty": 0,52    }53    if stream:54        timeout = timeout_streaming55    else:56        timeout = timeout_all57 58    # 获取环境变量中的代理设置59    http_proxy = os.environ.get("HTTP_PROXY") or os.environ.get("http_proxy")60    https_proxy = os.environ.get("HTTPS_PROXY") or os.environ.get("https_proxy")61 62    # 如果存在代理设置,使用它们63    proxies = {}64    if http_proxy:65        logging.info(f"Using HTTP proxy: {http_proxy}")66        proxies["http"] = http_proxy67    if https_proxy:68        logging.info(f"Using HTTPS proxy: {https_proxy}")69        proxies["https"] = https_proxy70 71    # 如果有代理,使用代理发送请求,否则使用默认设置发送请求72    if proxies:73        response = requests.post(74            API_URL,75            headers=headers,76            json=payload,77            stream=True,78            timeout=timeout,79            proxies=proxies,80        )81    else:82        response = requests.post(83            API_URL,84            headers=headers,85            json=payload,86            stream=True,87            timeout=timeout,88        )89    return response90 91 92def stream_predict(93    openai_api_key,94    system_prompt,95    history,96    inputs,97    chatbot,98    all_token_counts,99    top_p,100    temperature,101    selected_model,102):103    def get_return_value():104        return chatbot, history, status_text, all_token_counts105 106    logging.info("实时回答模式")107    partial_words = ""108    counter = 0109    status_text = "开始实时传输回答……"110    history.append(construct_user(inputs))111    history.append(construct_assistant(""))112    chatbot.append((parse_text(inputs), ""))113    user_token_count = 0114    if len(all_token_counts) == 0:115        system_prompt_token_count = count_token(construct_system(system_prompt))116        user_token_count = (117            count_token(construct_user(inputs)) + system_prompt_token_count118        )119    else:120        user_token_count = count_token(construct_user(inputs))121    all_token_counts.append(user_token_count)122    logging.info(f"输入token计数: {user_token_count}")123    yield get_return_value()124    try:125        response = get_response(126            openai_api_key,127            system_prompt,128            history,129            temperature,130            top_p,131            True,132            selected_model,133        )134    except requests.exceptions.ConnectTimeout:135        status_text = (136            standard_error_msg + connection_timeout_prompt + error_retrieve_prompt137        )138        yield get_return_value()139        return140    except requests.exceptions.ReadTimeout:141        status_text = standard_error_msg + read_timeout_prompt + error_retrieve_prompt142        yield get_return_value()143        return144 145    yield get_return_value()146    error_json_str = ""147 148    for chunk in tqdm(response.iter_lines()):149        if counter == 0:150            counter += 1151            continue152        counter += 1153        # check whether each line is non-empty154        if chunk:155            chunk = chunk.decode()156            chunklength = len(chunk)157            try:158                chunk = json.loads(chunk[6:])159            except json.JSONDecodeError:160                logging.info(chunk)161                error_json_str += chunk162                status_text = f"JSON解析错误。请重置对话。收到的内容: {error_json_str}"163                yield get_return_value()164                continue165            # decode each line as response data is in bytes166            if chunklength > 6 and "delta" in chunk["choices"][0]:167                finish_reason = chunk["choices"][0]["finish_reason"]168                status_text = construct_token_message(169                    sum(all_token_counts), stream=True170                )171                if finish_reason == "stop":172                    yield get_return_value()173                    break174                try:175                    partial_words = (176                        partial_words + chunk["choices"][0]["delta"]["content"]177                    )178                except KeyError:179                    status_text = (180                        standard_error_msg181                        + "API回复中找不到内容。很可能是Token计数达到上限了。请重置对话。当前Token计数: "182                        + str(sum(all_token_counts))183                    )184                    yield get_return_value()185                    break186                history[-1] = construct_assistant(partial_words)187                chatbot[-1] = (parse_text(inputs), parse_text(partial_words))188                all_token_counts[-1] += 1189                yield get_return_value()190 191 192def predict_all(193    openai_api_key,194    system_prompt,195    history,196    inputs,197    chatbot,198    all_token_counts,199    top_p,200    temperature,201    selected_model,202):203    logging.info("一次性回答模式")204    history.append(construct_user(inputs))205    history.append(construct_assistant(""))206    chatbot.append((parse_text(inputs), ""))207    all_token_counts.append(count_token(construct_user(inputs)))208    try:209        response = get_response(210            openai_api_key,211            system_prompt,212            history,213            temperature,214            top_p,215            False,216            selected_model,217        )218    except requests.exceptions.ConnectTimeout:219        status_text = (220            standard_error_msg + connection_timeout_prompt + error_retrieve_prompt221        )222        return chatbot, history, status_text, all_token_counts223    except requests.exceptions.ProxyError:224        status_text = standard_error_msg + proxy_error_prompt + error_retrieve_prompt225        return chatbot, history, status_text, all_token_counts226    except requests.exceptions.SSLError:227        status_text = standard_error_msg + ssl_error_prompt + error_retrieve_prompt228        return chatbot, history, status_text, all_token_counts229    response = json.loads(response.text)230    content = response["choices"][0]["message"]["content"]231    history[-1] = construct_assistant(content)232    chatbot[-1] = (parse_text(inputs), parse_text(content))233    total_token_count = response["usage"]["total_tokens"]234    all_token_counts[-1] = total_token_count - sum(all_token_counts)235    status_text = construct_token_message(total_token_count)236    return chatbot, history, status_text, all_token_counts237 238 239def predict(240    openai_api_key,241    system_prompt,242    history,243    inputs,244    chatbot,245    all_token_counts,246    top_p,247    temperature,248    stream=False,249    selected_model=MODELS[0],250    use_websearch_checkbox=False,251    files = None,252    should_check_token_count=True,253):  # repetition_penalty, top_k254    logging.info("输入为:" + colorama.Fore.BLUE + f"{inputs}" + colorama.Style.RESET_ALL)255    if files:256        msg = "构建索引中……(这可能需要比较久的时间)"257        logging.info(msg)258        yield chatbot, history, msg, all_token_counts259        index = construct_index(openai_api_key, file_src=files)260        msg = "索引构建完成,获取回答中……"261        yield chatbot, history, msg, all_token_counts262        history, chatbot, status_text = chat_ai(openai_api_key, index, inputs, history, chatbot)263        yield chatbot, history, status_text, all_token_counts264        return265    if use_websearch_checkbox:266        results = ddg(inputs, max_results=3)267        web_results = []268        for idx, result in enumerate(results):269            logging.info(f"搜索结果{idx + 1}:{result}")270            web_results.append(f'[{idx+1}]"{result["body"]}"\nURL: {result["href"]}')271        web_results = "\n\n".join(web_results)272        inputs = (273            replace_today(WEBSEARCH_PTOMPT_TEMPLATE)274            .replace("{query}", inputs)275            .replace("{web_results}", web_results)276        )277    if len(openai_api_key) != 51:278        status_text = standard_error_msg + no_apikey_msg279        logging.info(status_text)280        chatbot.append((parse_text(inputs), ""))281        if len(history) == 0:282            history.append(construct_user(inputs))283            history.append("")284            all_token_counts.append(0)285        else:286            history[-2] = construct_user(inputs)287        yield chatbot, history, status_text, all_token_counts288        return289    if stream:290        yield chatbot, history, "开始生成回答……", all_token_counts291    if stream:292        logging.info("使用流式传输")293        iter = stream_predict(294            openai_api_key,295            system_prompt,296            history,297            inputs,298            chatbot,299            all_token_counts,300            top_p,301            temperature,302            selected_model,303        )304        for chatbot, history, status_text, all_token_counts in iter:305            yield chatbot, history, status_text, all_token_counts306    else:307        logging.info("不使用流式传输")308        chatbot, history, status_text, all_token_counts = predict_all(309            openai_api_key,310            system_prompt,311            history,312            inputs,313            chatbot,314            all_token_counts,315            top_p,316            temperature,317            selected_model,318        )319        yield chatbot, history, status_text, all_token_counts320    logging.info(f"传输完毕。当前token计数为{all_token_counts}")321    if len(history) > 1 and history[-1]["content"] != inputs:322        logging.info(323            "回答为:"324            + colorama.Fore.BLUE325            + f"{history[-1]['content']}"326            + colorama.Style.RESET_ALL327        )328    if stream:329        max_token = max_token_streaming330    else:331        max_token = max_token_all332    if sum(all_token_counts) > max_token and should_check_token_count:333        status_text = f"精简token中{all_token_counts}/{max_token}"334        logging.info(status_text)335        yield chatbot, history, status_text, all_token_counts336        iter = reduce_token_size(337            openai_api_key,338            system_prompt,339            history,340            chatbot,341            all_token_counts,342            top_p,343            temperature,344            stream=False,345            selected_model=selected_model,346            hidden=True,347        )348        for chatbot, history, status_text, all_token_counts in iter:349            status_text = f"Token 达到上限,已自动降低Token计数至 {status_text}"350            yield chatbot, history, status_text, all_token_counts351 352 353def retry(354    openai_api_key,355    system_prompt,356    history,357    chatbot,358    token_count,359    top_p,360    temperature,361    stream=False,362    selected_model=MODELS[0],363):364    logging.info("重试中……")365    if len(history) == 0:366        yield chatbot, history, f"{standard_error_msg}上下文是空的", token_count367        return368    history.pop()369    inputs = history.pop()["content"]370    token_count.pop()371    iter = predict(372        openai_api_key,373        system_prompt,374        history,375        inputs,376        chatbot,377        token_count,378        top_p,379        temperature,380        stream=stream,381        selected_model=selected_model,382    )383    logging.info("重试完毕")384    for x in iter:385        yield x386 387 388def reduce_token_size(389    openai_api_key,390    system_prompt,391    history,392    chatbot,393    token_count,394    top_p,395    temperature,396    stream=False,397    selected_model=MODELS[0],398    hidden=False,399):400    logging.info("开始减少token数量……")401    iter = predict(402        openai_api_key,403        system_prompt,404        history,405        summarize_prompt,406        chatbot,407        token_count,408        top_p,409        temperature,410        stream=stream,411        selected_model=selected_model,412        should_check_token_count=False,413    )414    logging.info(f"chatbot: {chatbot}")415    for chatbot, history, status_text, previous_token_count in iter:416        history = history[-2:]417        token_count = previous_token_count[-1:]418        if hidden:419            chatbot.pop()420        yield chatbot, history, construct_token_message(421            sum(token_count), stream=stream422        ), token_count423    logging.info("减少token数量完毕")