AI学习记录 -使用react开发一个网页,对接chatgpt接口,附带一些英语的学习prompt

实现了如下功能(使用react实现,原创)

实现功能:

1、对接gpt35模型问答,并实现了流式传输(在java端)

2、在实际使用中,我们的问答历史会经常分享给他人,所以下图的 copy all 按钮,可以copy成一个json然后通过社交软件发送给别人,别人就可以轻松应用你的问答历史。

3、选择文件,在我们预想当中,我们可能会经常遇到向文档提问(当时还不知道embedding的知识哈哈哈),通过拆分文档,一段段跟gpt提问,当前段落是否和用户内容相关,相关就回答段落问题(段落拆分通过java实现)

4、我们需要经常保存我们的聊天记录,特别是在调试我们的prompt的时候,所以加了一个缓存功能,可以随时提取缓存记录来提问。

5、利用这个分享的时候,设计了很多便利我去学习英语的prompt,避免老是手打提示词

role.js
json 复制代码
export default {
    "专业的英语翻译家": (text = "示例") => {
        return "现在你充当我专业的翻译家。当我输入中文,你就翻译成英文。当我输入英文,你就翻译成中文。请翻译:" + text
    },
    "文章截断翻译": (text = "示例") => {
        return "因为我是中国的软件开发工程师,我要面试美国的软件开发岗位,所以我要学习英语,我要你充当我的翻译家," +
            "所以我给一些中文的软件知识给你帮我翻译,但是你不能直译,因为中文说出来的知识,英语的表达有不一样,所" +
            "以请你理解我的中文知识,按照自己的理解用英语表达出来,所以我给你一段文字,首先你要将文章拆分成一句一句,理解每" +
            "一句的意思,然后用英语将你理解的意思输出。输出格式为一句中文,输出一个回车符,下一行输出你的英文理解。并且每一句末尾都" +
            "给生僻词单独翻译。文章内容为:"" + text + """
    },
    "给出5个英语句子对应的词汇": (text = "示例") => {
        return "我给你一个英文单词,请你用这个英文单词造出5个英文句子,句子要求是计算机互联网相关知识" +
            "(包括但不限于前端专业细节知识,react专业细节知识,vue专业细节知识,js专业细节知识,管理系统的功能专业细节知识," +
            "http网络相关专业细节知识),并附带中文翻译。最后还要给出他的衍生词汇," +
            "给出他的发音以及词汇类型。单词为:" + text
    },
    "给你一个中文词汇,你给我说出英语一般用什么句式去表达": (text = "示例") => {
        return "我给你一个中文词汇,你给我说出英语一般用什么句式去表达。" +
            "例如:中文意思:确保一些东西是有效的,英语一般表达为:ensure that somethings is valid。" +
            "这个(ensure that ... is valid)就是英语的常规表达句式。" +
            "例如:允许轻松自定义表单验证,,英语一般表达为:ensure that somethings is valid。" +
            "这个(allows for ... 。" +
            "中文词汇为:" + text
    },
    "面试中怎么表达这个中文意思": (text = "示例") => {
        return "在美国的it开发工程师英语面试当中,怎么表达:" + text + ", 请用三种或者三种以上不同的句式表达"
    },
    "在英语中有多少英文表达这个中文意思": (text = "示例") => {
        return "在英语中有多少英文表达这个中文意思,请列举出来,中文为:" + text
    },
    "假设你是一个从小就在美国长大的人": (text = "示例") => {
        return "假设你是一个从小就在美国长大的人,你已经30岁,在互联网公司工作8年,请你使用简洁的口语帮我将中文翻译成英文,重点是简洁,简洁,你自己听得懂就好。中文为:" + text
    }
}
index.js
javascript 复制代码
import React, { useState, useCallback, useRef } from 'react';
import './index.css';
import { useEffect } from 'react';
import axios from 'axios';
import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter";
import { vscDarkPlus, coyWithoutShadows, darcula } from 'react-syntax-highlighter/dist/esm/styles/prism';
// 设置高亮的语言
import { jsx, javascript } from "react-syntax-highlighter/dist/esm/languages/prism";
import ReactMarkdown from 'react-markdown';
import ClipboardJS from 'clipboard';
import { Drawer, Input, message, Select } from 'antd';
import roles from "./roles";

const { Search } = Input;
const { TextArea } = Input;
const { Option } = Select;

function clearLocalStorage() {
  localStorage.setItem("LOCALDATA", "[]");
}

// 封装localStorage的get方法
function getLocalStorage() {
  let arrStr = localStorage.getItem("LOCALDATA");
  if (arrStr) {
    let arr = JSON.parse(arrStr);
    return arr;
  } else {
    return [];
  }
}

const them = {
  dark: vscDarkPlus,
  light: coyWithoutShadows
};
const ENDTEXT = "__END__";

let comments = [];
let streaming = false

export default function App1() {
  const [question, setQuestion] = useState("");
  const [roleType, setRoleType] = useState("");
  const [frontPrompts, setFrontPrompts] = useState("");

  const list_container_id = useRef(null);
  const currentTexts = useRef("");
  const [count, setCount] = useState(0);
  const [messageApi, contextHolder] = message.useMessage();
  const [open, setOpen] = useState(false);
  const [openMoreFunction, setOpenMoreFunction] = useState(false);

  const [jsonData, setJsonData] = useState("{}");
  const key = 'copy';
  const postStreamList = async (callback) => {
    let requestList = [];
    comments.map((item) => {
      if (item.type === "chatgpt-url") {
        if (item.contents[0]) {
          requestList.push({ "role": "user", "content": item.contents[0].hiddenQuestion });
          requestList.push({ "role": "assistant", "content": item.contents[0].hiddenContent });
        }
      } else {
        requestList.push({ "role": "user", "content": item.name });
        if (item.contents[0] && item.contents[0].text) {
          requestList.push({ "role": "assistant", "content": item.contents[0].text });
        }
      }
    })

    const requestOptions = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        "Authorization": "Bearer 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"
      },
      body: JSON.stringify({
        "model": "gpt-3.5-turbo",
        "messages": requestList
      })
    };
    let count = 0;
    const streamResponse = await fetch('/chat', requestOptions);
    // const streamResponse = await fetch('/search/api/dev/stream', requestOptions);
    const reader = streamResponse.body.getReader();
    let errText = "";
    const read = () => {
      return reader.read().then(({ done, value }) => {
        count++;
        if (done) {
          console.log("victor react reviced: end");
          callback(ENDTEXT);
          return;
        }

        const textDecoder = new TextDecoder();
        // console.log("返回的数据:", textDecoder.decode(value));
        let text = "";
        const strArr = (errText + textDecoder.decode(value)).split("data: ");
        console.log("解析字符", textDecoder.decode(value))
        if (strArr) {
          for (let i = 0; i < strArr.length; i++) {
            let json = {};
            if (strArr[i] && strArr[i] !== "[DONE]") {
              try {
                json = JSON.parse(strArr[i]);
                if (json.choices.length && json.choices[0].delta.content) {
                  text = text + json.choices[0].delta.content;
                }
                errText = "";
              } catch (e) {
                console.log("出错", strArr[i])
                errText = strArr[i];
              }

            }
          }
          callback(text);
        }
        return read();
      });
    }

    read();
  }

  const postStreamListAudio = async (erjinzhi) => {
    const requestOptions = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        "model": "gpt-3.5-turbo",
        "messages": [{ "role": "assistant", "content": erjinzhi }]
      })
    };
    let count = 0;
    const streamResponse = await fetch('/chat', requestOptions);
    // const streamResponse = await fetch('/search/api/dev/stream', requestOptions);
    const reader = streamResponse.body.getReader();
    let errText = "";
    const read = () => {
      return reader.read().then(({ done, value }) => {
        count++;
        if (done) {
          console.log("victor react reviced: end");
          return;
        }

        const textDecoder = new TextDecoder();
        // console.log("返回的数据:", textDecoder.decode(value));
        let text = "";
        const strArr = (errText + textDecoder.decode(value)).split("data: ");
        console.log("解析字符", textDecoder.decode(value))
        if (strArr) {
          for (let i = 0; i < strArr.length; i++) {
            let json = {};
            if (strArr[i] && strArr[i] !== "[DONE]") {
              try {
                json = JSON.parse(strArr[i]);
                if (json.choices.length && json.choices[0].delta.content) {
                  text = text + json.choices[0].delta.content;
                }
                errText = "";
              } catch (e) {
                console.log("出错", strArr[i])
                errText = strArr[i];
              }

            }
          }
          console.log(text);
        }
        return read();
      });
    }
    read();
  }

  const addLocalStorage = (dataArr) => {
    var now = new Date();
    var year = now.getFullYear(); //获取完整的年份(4位,1970-????)
    var month = now.getMonth() + 1; //获取当前月份(0-11,0代表1月)
    var date = now.getDate(); //获取当前日(1-31)
    var hour = now.getHours(); //获取当前小时数(0-23)
    var minute = now.getMinutes(); //获取当前分钟数(0-59)
    var second = now.getSeconds(); //获取当前秒数(0-59)
    var timestamp = year + "-" + (month < 10 ? "0" + month : month) + "-" + (date < 10 ? "0" + date : date) + " " + (hour < 10 ? "0" + hour : hour) + ":" + (minute < 10 ? "0" + minute : minute) + ":" + (second < 10 ? "0" + second : second);
    try {
      let arrStr = localStorage.getItem("LOCALDATA");
      if (arrStr) {
        let arr = JSON.parse(arrStr);
        arr.push({
          time: timestamp,
          dataArr: dataArr
        });
        localStorage.setItem("LOCALDATA", JSON.stringify(arr));
      } else {
        let arr = [];
        arr.push({
          time: timestamp,
          dataArr: dataArr
        });
        localStorage.setItem("LOCALDATA", JSON.stringify(arr));
      }
      messageApi.open({
        key,
        type: 'success',
        content: '缓存成功',
        duration: 1
      });
    } catch (err) {
      console.error('localStorage set error: ', err);
    }
  }

  const addComment = async (e) => {
    if (question.trim() === '') {
      alert('请输入问题');
      return;
    }
    setQuestion('');
    let index = comments.length;
    comments.push({
      id: Math.random(),
      role: 'user',
      type: "chatgpt",
      name: question,
      contents: []
    });
    setCount(count + 1);
    setTimeout(async () => {
      let responseList = await getList();
      if (responseList[0].type === "chatgpt-url") {
        comments[index].type = "chatgpt-url";
      }
      comments[index].contents = responseList;
      setQuestion('');
      setCount(0);
    }, 0);
  }

  const getList = (question) => {
    let requestList = [];
    comments.map((item) => {
      if (item.type === "chatgpt-url") {
        if (item.contents[0]) {
          requestList.push({ "role": "user", "content": item.contents[0].hiddenQuestion });
          requestList.push({ "role": "assistant", "content": item.contents[0].hiddenContent });
        }
      } else {
        requestList.push({ "role": "user", "content": item.name });
        if (item.contents[0]) {
          requestList.push({ "role": "assistant", "content": item.contents[0].text });
        }
      }
    })
    return new Promise((resolve) => {
      axios.post('/search/send', {
        frequency_penalty: 0,
        max_tokens: 2048,
        model: "text-davinci-003",
        presence_penalty: 0,
        message: requestList,
        temperature: 0.5,
        top_p: 1
      }).then((response) => {

        if (Array.isArray(response.data.choices)) {
          // console.log('请求成功', response);
          let arr = response.data.choices.map((item) => {
            if (item.message.type === "chatgpt-url") {
              return {
                type: item.message.type,
                index: item.index,
                text: "我已经对这个链接学习完成,你可以向我提问关于这个链接的内容",
                hiddenQuestion: item.message.question,
                hiddenContent: item.message.content
              }
            } else {
              return {
                type: item.type,
                index: item.index,
                text: item.message.content
              }
            }
          })
          resolve(arr);
        } else {
          alert('程序错误');
        }
        // 请求成功
      }).catch((error) => {
        // 请求失败,
        console.log(error);
      });
    })
  }

  const scrollBottom = () => {
    if (!list_container_id.current) {
      return;
    }
    setTimeout(() => {
      list_container_id.current.scrollTop = list_container_id.current.scrollHeight
    }, 0);
  }

  const updateScroll = useCallback(() => {
    scrollBottom()
  })

  const addStreamComment = async ({
    question1 = "",
    isCreate = false,
    isContinue = false
  }) => {
    if (question.trim() === '' && !question1 && isContinue === false) {
      alert('请输入问题');
      return;
    }
    streaming = true;
    setQuestion('');
    let index = 0;
    // 修改不需要新数据, 创建就需要push新item
    if (isCreate || comments.length === 0) {
      console.log("走创建")
      index = comments.length;
      let questionText = question1 || question;
      if (roles[roleType]) {
        questionText = roles[roleType](question1 || question)
      }
      comments.push({
        id: Math.random(),
        role: 'user',
        type: "chatgpt",
        name: questionText,
        edit: false,
        contents: [{ index: Math.random(), text: "", edit: false }]
      });
    } else if (isContinue === true) {
      console.log("走继续")
      index = comments.length - 1;
      comments[index] = {
        ...comments[index],
        id: Math.random(),
        role: 'user',
        type: "chatgpt",
        edit: false
      };
    } else {
      console.log("走编辑")
      index = comments.length - 1;
      comments[index] = {
        id: Math.random(),
        role: 'user',
        type: "chatgpt",
        name: question1 || question,
        edit: false,
        contents: [{ index: Math.random(), text: "", edit: false }]
      };
    }
    setCount(count + 1);
    let str = comments[index].contents[0].text;
    const callback = (text) => {
      if (text === ENDTEXT) {
        streaming = false;
        setCount(1);
        return;
      }
      str = str + text;
      comments[index].contents[0].text = str;
      setQuestion('');
      setCount((count) => count + 1);
    }
    postStreamList(callback);
  }

  const copy = (index) => {
    const clipboard = new ClipboardJS("#copyBtn" + index);
    clipboard.on('success', () => {
      messageApi.open({
        key,
        type: 'success',
        content: '复制成功',
        duration: 1
      });
    });
  }
  useEffect(() => {
    const clipboard = new ClipboardJS("#copyBtnAll");
    clipboard.on('success', () => {
      messageApi.open({
        key,
        type: 'success',
        content: '复制成功',
        duration: 1
      });
    });
    comments.map((item, index) => {
      const clipboard = new ClipboardJS("#copyBtn" + index);
      clipboard.on('success', () => {
        messageApi.open({
          key,
          type: 'success',
          content: '复制成功',
          duration: 2
        });
      });
    })
  })
  console.log("comments", comments)
  const renderList = () => {
    return comments.length === 0 ?
      (<div style={{ flex: 1 }}>
        <div className='no-comment'>暂无问题,快去提问吧~</div>
      </div>)
      : (
        <div
          ref={(el) => {
            list_container_id.current = el;
          }}
          style={{ flex: 1 }}
          className="list_container"
        >
          <ul style={{ color: 'white' }}>
            {comments.map((item, index) => (
              <li key={item.id} style={{ color: 'white' }}>
                {
                  item.name ? (
                    <div className='quiz'>
                      <div className='response' style={{ marginLeft: 8 }}>
                        <div className='action_btn'>
                          <div>提问:</div>
                          <div className="copy_button" id={"copyBtn" + index} data-clipboard-text={item.name} onClick={(e) => copy(index)}>copy</div>
                          {comments.length === index + 1 ? (
                            <div
                              className="copy_button"
                              onClick={() => {
                                if (item.edit === false) {
                                  item.edit = true;
                                  setCount(count + 1);
                                } else {
                                  addStreamComment({
                                    question1: item.name,
                                    isCreate: false,
                                    isContinue: false
                                  });
                                }
                              }}>{!item.edit ? "edit" : "submit"}</div>
                          ) : null}
                          <div
                            className="copy_button"
                            onClick={() => {
                              comments.splice(index, 1);
                              setCount(count + 1);
                            }}>delete</div>

                        </div>
                        {
                          !item.edit ? <p>{item.name}</p> : (
                            <div className="">
                              <TextArea
                                rows={4}
                                defaultValue={item.name}
                                onChange={(e) => {
                                  item.name = e.target.value;
                                }}
                              />
                            </div>
                          )
                        }
                      </div>
                    </div>
                  ) : null
                }
                {
                  item.contents.length ? (
                    <>
                      <div
                        className='answer'>
                        <div style={{ marginLeft: 8, marginBottom: 10 }} >
                          <div className='action_btn'>
                            <div>回答:</div>
                            <div className="copy_button" id={"copyBtn" + index} data-clipboard-text={item.contents[0].text} onClick={(e) => copy(index)}>copy</div>
                          </div>
                          <pre style={{ width: "100%" }}><OmsSyntaxHighlight textContent={item.contents[0].text} language={"javascript"} darkMode /></pre></div>
                      </div>
                      <div>{currentTexts.current}</div>
                    </>
                  ) : <div>
                    <div style={{ display: 'flex', justifyContent: 'center', backgroundColor: 'black' }}><div className='heike'  >chatgpt</div></div>
                    <div className='answer2'>思考中...</div>
                  </div>
                }
              </li>
            ))
            }
          </ul >
        </div >
      )
  }
  const handleForm = (e) => {
    setQuestion(e.target.value)
  }

  const handleSelectChange = (value) => {
    setFrontPrompts(value);
    setRoleType(value);
  };

  useEffect(() => {
    scrollBottom()
  })

  const overWriteData = (jsonData) => {
    let jsonData1 = JSON.parse(jsonData);
    // console.log("jsonData1", jsonData1)
    comments = [];
    jsonData1.map((item, index) => {
      if (index % 2 === 0) {
        comments.push({
          id: Math.random(),
          role: 'user',
          type: "chatgpt",
          name: item.content,
          edit: false,
          contents: [{
            index: Math.random(),
            edit: false,
            text: jsonData1[index + 1].content
          }]
        })
        // console.log(comments)
        setCount(count + 1)
      }
    })
  }

  const handleLocalDataChange = (value) => {
    overWriteData(value);
  };

  useEffect(() => {
    const mp3File = document.getElementById('mp3-file');

    mp3File.addEventListener('change', () => {
      const file = mp3File.files[0];
      const reader = new FileReader();

      reader.addEventListener('loadend', () => {
        const byteArray = new Uint8Array(reader.result);
        // 将byteArray上传至服务器
        console.log(byteArray)
        postStreamListAudio(byteArray);
      });

      reader.readAsArrayBuffer(file);
    });
  }, [])

  const renderHeader = () => {
    return (
      <div className='header_button'>
        <div
          className="copy_all_button"
          style={{ color: "white" }}
          onClick={() => {
            let tmp = [];
            comments.map((item) => {
              tmp.push({
                role: 'user',
                content: item.name,
              })
              tmp.push({
                role: 'assistant',
                content: item.contents[0].text
              })
            })
            setJsonData(JSON.stringify(tmp));
            setOpen(true);
          }}>
          copy all
        </div>
        <input type="file" id="mp3-file"></input>
        <div
          className="copy_all_button"
          onClick={() => {
            setOpenMoreFunction(true);
          }}
          style={{ color: "white" }}
        >
          更多功能
        </div>
      </div>
    )
  }

  const renderDrawerCopyBtnAll = () => {
    return (
      <Drawer
        title={
          <div style={{ display: 'flex' }}>
            <div
              className='copy_button'
              id={"copyBtnAll"}
              data-clipboard-text={jsonData}
              onClick={(e) => {
                const clipboard = new ClipboardJS("#copyBtnAll");
                clipboard.on('success', () => {
                  messageApi.open({
                    key,
                    type: 'success',
                    content: '复制成功',
                    duration: 2
                  });
                });
              }}>copy</div>
            <div className='copy_button' onClick={() => {
              try {
                overWriteData(jsonData);
                setOpen(false);
              } catch (e) {
                messageApi.open({
                  key,
                  type: 'error',
                  content: 'json格式出错',
                  duration: 2
                });
              }
            }}>
              执行json
            </div>
            <div className='copy_button' onClick={() => {
              try {
                addLocalStorage(jsonData);
              } catch (e) {
                messageApi.open({
                  key,
                  type: 'error',
                  content: 'json格式出错',
                  duration: 2
                });
              }
            }}>
              缓存
            </div>
          </div>
        }
        placement={"bottom"}
        open={open}
        size='small'
        onClose={() => {
          setOpen(false)
        }}
      >
        <TextArea
          rows={4}
          value={jsonData}
          onChange={(e) => {
            setJsonData(e.target.value);
          }}
        />
      </Drawer>
    )
  }

  const renderDrawerMoreFunction = () => {
    return (
      <Drawer
        title={"更多功能"}
        placement={"bottom"}
        open={openMoreFunction}
        size='small'
        onClose={() => {
          setOpenMoreFunction(false)
        }}
      >
        <div>
          {
            !streaming ? (
              <button
                className="copy_all_button"
                onClick={() => {
                  comments = [];
                  setCount(0);
                }}>clear</button>
            ) : null
          }
          {
            <button
              className="copy_all_button"
              onClick={() => {
                clearLocalStorage();
                setCount(10);
              }}>clearStorage</button>
          }
          <div>
            <span>角色:</span>
            <Select
              style={{ width: '100%' }}
              defaultValue="origin"
              onChange={handleSelectChange}
              options={[
                { value: 'origin', label: 'origin' },
                ...Object.keys(roles).map((role) => ({ value: role, label: role }))
              ]}
            />
          </div>
          <div>
            <span>缓存:</span>
            <Select
              style={{ width: '100%' }}
              onChange={handleLocalDataChange}
            >
              {
                getLocalStorage().length ? getLocalStorage().map((item) => {
                  return <Option value={item.dataArr} key={Math.random()}>{item.time}</Option>
                }) : <Option value={"0"} key="无">无</Option>
              }
            </Select>
          </div>
        </div>
      </Drawer>
    )
  }

  const renderFrontPrompts = () => {
    if (frontPrompts && roles[frontPrompts]) {
      return <div className='frontPrompts'>前置指令:{roles[frontPrompts]()}</div>;
    } else {
      return null;
    }
  }

  const renderQuestion = () => {
    return (
      <div className='input_style'>
        <TextArea
          className='input_quertion'
          type="text"
          placeholder="请输入问题"
          value={question}
          name="question"
          onChange={handleForm}
          autoSize={{ minRows: 1, maxRows: 5 }}
        />
        <div style={{ width: '1vw' }}></div>
        <button onClick={() => {
          addStreamComment({
            isContinue: true,
            isCreate: false,
            question1: ""
          });
        }} className="confirm_button" >继续</button>
        <div style={{ width: '1vw' }}></div>
        <button onClick={() => {
          const pattern = /(http|https):\/\/([\w.]+\/?)\S*/;
          addStreamComment({ isCreate: true, isContinue: false, question1: "" });
        }} className="confirm_button" >提问</button>
      </div>
    )
  }

  return (
    <div className='app_container'>
      {renderHeader()}
      {renderFrontPrompts()}
      {renderList()}
      {contextHolder}
      {renderQuestion()}
      {renderDrawerCopyBtnAll()}
      {renderDrawerMoreFunction()}
    </div>
  )

}

const OmsSyntaxHighlight = (props) => {
  const { textContent, darkMode, language = 'txt' } = props;
  const [value, setValue] = useState(textContent);
  if (typeof darkMode === 'undefined') {
    them.light = darcula;
  }
  if (typeof darkMode === 'boolean') {
    them.light = coyWithoutShadows;
  }
  useEffect(() => {
    SyntaxHighlighter.registerLanguage("jsx", jsx);
    SyntaxHighlighter.registerLanguage("javascript", javascript);
    SyntaxHighlighter.registerLanguage("js", javascript);
  }, []);
  return (
    <ReactMarkdown source={value} escapeHtml={false} language={language}>{textContent}</ReactMarkdown>
  );
};
css文件
css 复制代码
body,
html {
  margin: 0;
}

ul,
li,
p {
  padding: 0;
  margin: 0;
  list-style: none
}

h3 {
  margin-bottom: 0;
}

.input_quertion {
  width: 50vw;
  height: 50px;
  border-radius: 10px;
  border: 1px solid black;
}

pre {
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  white-space: -pre-wrap;
  white-space: -o-pre-wrap;
  word-wrap: break-word;
}

.copy_button {
  line-height: 35px;
  margin-right: 4px;
  border: 1px solid royalblue;
}

.copy_all_button {
  line-height: 44px;
  margin-right: 4px;
  border: 1px solid royalblue;
}

.content {
  width: 280px;
  margin: 5px;
  border: 1px solid black;
}

.quickButton {
  width: 70px;
  border-radius: 10px;
  background-color: #03b96b;
  border: 0;
  height: 30px;
  color: white;
  position: absolute;
  right: 10px;
}

.no-comment {
  text-align: center;
  padding: 20px;
  color: white;
  background-color: rgb(53, 54, 65);
}


.frontPrompts {
  text-align: left;
  padding: 8px 46px;
  color: white;
  font-size: 12px;
  background-color: rgb(53, 54, 65);
  border-bottom: 1px solid black;
}

.app_container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: rgb(53, 54, 65);
}

.confirm_button {
  width: 26vw;
  border-radius: 10px;
  background-color: #03b96b;
  border: 0;
  height: 50px;
  color: white;
  box-shadow: 7px 6px 28px 1px rgba(0, 0, 0, 0.24);
  cursor: pointer;
  outline: none;
  transition: 0.2s all;
}

.list_container {
  overflow: auto;
  flex: 1;
}

.qiu {
  width: 15%;
  height: 15%;
}

.chatGPTImg {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  width: 300px;
  height: 300px;
  z-index: 999;
}

.response {
  overflow-wrap: break-word;
  word-break: normal;
  white-space: normal;
  flex: 1;
}

.header_button {
  width: 100%;
  height: 67px;
  display: flex;
  align-items: center;
  bottom: 0;
  padding: 10px 40px 10px;
  border-bottom: 1px solid;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0) 100%);
  box-shadow: 0px -5px 10px rgba(0, 0, 0, 0.3);
}


.input_style {
  width: 100%;
  display: flex;
  bottom: 0;
  padding: 1%;
  align-items: end;
}

.action_btn {
  display: flex;
  align-items: flex-start;
  color: white;
}

.quiz {
  display: flex;
  align-items: flex-start;
  padding: 10px 40px 10px;
  color: white;
  line-height: 41px;
  background-color: rgb(53, 54, 65);
}

.quiz_avatar {
  width: 40px;
  height: 40px;
}

.answer {
  display: flex;
  background-color: #3b3d53;
  color: white;
  height: auto;
  line-height: 35px;
  padding: 20px 40px;
  overflow: auto;
  white-space: normal;
  word-break: break-all;
}

.answer2 {
  text-align: center;
  padding-top: 40px;
}

.confirm_button:active {
  transform: scale(0.98);
  background-color: blue;
  box-shadow: 3px 2px 22px 1px rgba(0, 0, 0, 0.24);
}
相关推荐
北京搜维尔科技有限公司20 分钟前
搜维尔科技:【应用】Xsens在荷兰车辆管理局人体工程学评估中的应用
人工智能·安全
@小博的博客22 分钟前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
说私域24 分钟前
基于开源 AI 智能名片 S2B2C 商城小程序的视频号交易小程序优化研究
人工智能·小程序·零售
YRr YRr24 分钟前
深度学习:Transformer Decoder详解
人工智能·深度学习·transformer
知来者逆29 分钟前
研究大语言模型在心理保健智能顾问的有效性和挑战
人工智能·神经网络·机器学习·语言模型·自然语言处理
云起无垠38 分钟前
技术分享 | 大语言模型赋能软件测试:开启智能软件安全新时代
人工智能·安全·语言模型
老艾的AI世界1 小时前
新一代AI换脸更自然,DeepLiveCam下载介绍(可直播)
图像处理·人工智能·深度学习·神经网络·目标检测·机器学习·ai换脸·视频换脸·直播换脸·图片换脸
南宫生1 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx