草庐IT

基于python实现openai可结合上下文的问答,含html在线版

dapenson 2024-01-01 原文

本文使用 OpenAI GPT(Generative Pre-Training)聊天机器人模型,实现可自动回复提问的聊天功能。

代码解释

首先,我们导入相关的库,例如 openaiPathtime 等。

接下来,为了使模型可以正常工作,我们需要设置 openaiapi_key ,以及一些初始变量,如 text, turns, last_result,用来记录聊天记录。

之后,我们定义了一个函数 chatgpt,目的是为了接收用户输入的问题,并返回 GPT 模型生成的回答。函数中,除了指定使用 davinci-003 模型外,我们还设置了 temperaturemax_tokensfrequency_penaltypresence_penalty 等参数,用来控制结果的随机性和字数,以达到最佳的回答效果。

最后,在 if __name__ == '__main__': 下,我们初始化两个列表,用来存放用户输入的问题和 GPT 模型自动生成的回答,然后在 while 循环中,接收用户输入的问题,并调用 chatgpt 函数,最后将问题和回答分别存储到对应的列表中,最终将内容保存到文件中。

代码使用说明

  • 使用该代码,你需要先申请 OpenAI 的api_key,并将其输入到代码中,然后运行该程序,
  • 输入你的问题,即可获得 GPT 模型的回答;
  • 若输入exit则直接退出当前对话;
  • 程序结束时,会将问答的内容记录到文件中,以便下次查看。

ini配置文件

在目录下创建config.ini文件,内容如下

[openai]

ai_account_key = sk-AsqirFnBSHKvalmEe1AnT3BlbkFJe2rX0xxxxxxxxxxx

对话模式代码

点击查看代码
import openai
from pathlib import Path
import time
import configparser

ANSI_COLOR_GREEN = "\x1b[32m"
ANSI_COLOR_RESET = "\x1b[0m"


# 从ini文件中读取api_key
config = configparser.ConfigParser()
config.read('config.ini')
openai.api_key = config['openai']['ai_account_key']


text = ""  # 设置一个字符串变量
turns = []  # 设置一个列表变量,turn指对话时的话轮
last_result = ""


def chatgpt(question):
    global text
    global turns
    global last_result

    prompt = text + "\nHuman: " + question

    try:
        response = openai.Completion.create(
            model="text-davinci-003",  # 这里我们使用的是davinci-003的模型,准确度更高。
            prompt=prompt,  # 你输入的问题
            temperature=0.9,  # 控制结果的随机性,如果希望结果更有创意可以尝试 0.9,或者希望有固定结果可以尝试 0.0
            max_tokens=2048,  # 这里限制的是回答的长度,你可以可以限制字数,如:写一个300字作文等。
            top_p=1,
            # [控制字符的重复度] -2.0 ~ 2.0 之间的数字,正值会根据新 tokens 在文本中的现有频率对其进行惩罚,从而降低模型逐字重复同一行的可能性
            frequency_penalty=0,
            # [控制主题的重复度] -2.0 ~ 2.0 之间的数字,正值会根据到目前为止是否出现在文本中来惩罚新 tokens,从而增加模型谈论新主题的可能性
            presence_penalty=0
        )

        result = response["choices"][0]["text"].strip()
        last_result = result
        turns += [question] + [result]  # 只有这样迭代才能连续提问理解上下文

        if len(turns) <= 10:  # 为了防止超过字数限制程序会爆掉,所以提交的话轮语境为10次。
            text = " ".join(turns)
        else:
            text = " ".join(turns[-10:])

        return result
    except Exception as exc:  # 捕获异常后打印出来
        print(exc)


if __name__ == '__main__':

    # 将问题和回复记录下来,待结束后保存到文件中
    question_list = []
    answer_list = []
    while True:
        question = input(ANSI_COLOR_GREEN +
                         "\n请输入问题,若输入exit退出\n" + ANSI_COLOR_RESET)
        question_list.append(question)
        if question == "exit":
            break
        answer = chatgpt(question)
        answer_list.append(answer)
        print("AI: " + answer)
    # 保存到文件中
    timestamp = time.strftime("%Y%m%d-%H%M-%S", time.localtime())
    file_name = 'output/chat ' + timestamp + '.md'
    f = Path(file_name)
    f.parent.mkdir(parents=True, exist_ok=True)
    with open(file_name, "w", encoding="utf-8") as f:
        for q, a in zip(question_list, answer_list):
            f.write(f"question: {q}\nanswer: {a}\n\n")
    print(ANSI_COLOR_GREEN + "对话内容已保存到文件中: " + file_name + ANSI_COLOR_RESET)


单问答模式代码

点击查看代码
import openai
from pathlib import Path
import time
import configparser


ANSI_COLOR_GREEN    = "\x1b[32m"
ANSI_COLOR_RESET    = "\x1b[0m"



def get_ai_answer(prompt, save=True):
    # 去除字符串前后的空白符
    prompt = prompt.strip()
    # 发起请求
    if len(prompt) != 0:
        print(f'已发起请求,问题描述{len(prompt)}个长度,请稍等...')
        # 从ini文件中读取api_key
        config = configparser.ConfigParser()
        config.read('config.ini')
        openai.api_key = config['openai']['ai_account_key']
        # Get my answer
        response = openai.Completion.create(
            prompt=prompt,
            model="text-davinci-003",
            temperature=0.9,
            max_tokens=2048,  #返回结果的长度
            top_p=1,
            frequency_penalty=0.0,
            presence_penalty=0.0)

        # Print my answer
        # print(response)
        answer = response["choices"][0]["text"].strip()
        print(answer)

        # 将内容写到以时间戳为名的md文件
        if save:
            timestamp = time.strftime("%Y%m%d-%H%M-%S", time.localtime())
            file_name = 'output/' + timestamp + '.md'
            f = Path(file_name)
            f.parent.mkdir(parents=True, exist_ok=True)
            text = f'# Q\n{prompt}\n# A\n{answer}\n'
            f.write_text(text, encoding='utf-8')
            print(ANSI_COLOR_GREEN  +"对话内容已保存到文件中: " + file_name + ANSI_COLOR_RESET)
        return answer


if __name__ == '__main__':
    prompt = '''
你今年几岁了
    '''
    get_ai_answer(prompt)


gitee在线版

此外,我用html写了一个可直接对话的openai gpt3在线版,用该页面需要提前自备openai的apikey。

项目源码https://gitee.com/x223222981/chat-gpt.js

有关基于python实现openai可结合上下文的问答,含html在线版的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  7. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  8. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

    我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

  9. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  10. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

随机推荐