赞
踩
ChatGPT最近很火爆大家都知道吧,今天废话不多说 直接给大家带来一个ChatGPT中文版的源码
先对整体进行一个介绍,这套源码界面很有科技感,其次是功能方面有专门的指令输入框,让你可以舒舒服服的玩转你手中的prompts
其次有黑夜和白天两个模式以及回到顶部功能
下面废话不多说 直接上代码
由于代码太多 我直接放前端页面的代码
代码是基于nodejs写的
下面是header文件
--- import Logo from './Logo.astro' import Themetoggle from './Themetoggle.astro' --- <header> <div class="flex justify-between"> <Logo /> <Themetoggle /> </div> <div class="flex items-center mt-2"> <span class="text-2xl text-slate font-extrabold mr-1">CTGPT.</span> <span class="text-2xl text-transparent font-extrabold bg-clip-text bg-gradient-to-r from-sky-400 to-emerald-600">CN</span> </div> <p mt-1 text-slate op-60>基于 OpenAI API (gpt-3.5-turbo)开发.</p> </header>
下面是footer文件
<footer> <p mt-8 text-xs op-30> <br> <a border-b border-slate border-none hover:border-dashed href="https://wwji.lanzouf.com/iVoeB0o7wrxe" target="_blank" > 安卓端下载 <span px-1>|</span> </a> <a border-b border-slate border-none hover:border-dashed href="https://wwji.lanzouf.com/iYlRb0o7wryf" target="_blank" > 苹果端下载(safari打开安装需要去设置描述文件安装) </a> </p> <script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script> <script>LA.init({id:"Jzntbyt4gmLpmsXz",ck:"Jzntbyt4gmLpmsXz"})</script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?5aff25b20308b19618d1ea0a4797216b"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> </p> </footer>
下面是问题框代码
import type { ChatMessage } from '@/types' import { createSignal, Index, Show } from 'solid-js' import IconClear from './icons/Clear' import MessageItem from './MessageItem' import SystemRoleSettings from './SystemRoleSettings' import _ from 'lodash' import { generateSignature } from '@/utils/auth' export default () => { let inputRef: HTMLTextAreaElement const [currentSystemRoleSettings, setCurrentSystemRoleSettings] = createSignal('') const [systemRoleEditing, setSystemRoleEditing] = createSignal(false) const [messageList, setMessageList] = createSignal<ChatMessage[]>([]) const [currentAssistantMessage, setCurrentAssistantMessage] = createSignal('') const [loading, setLoading] = createSignal(false) const [controller, setController] = createSignal<AbortController>(null) const handleButtonClick = async () => { const inputValue = inputRef.value if (!inputValue) { return } // @ts-ignore if (window?.umami) umami.trackEvent('chat_generate') inputRef.value = '' setMessageList([ ...messageList(), { role: 'user', content: inputValue, }, ]) requestWithLatestMessage() } const throttle =_.throttle(function(){ window.scrollTo({top: document.body.scrollHeight, behavior: 'smooth'}) }, 300, { leading: true, trailing: false }) const requestWithLatestMessage = async () => { setLoading(true) setCurrentAssistantMessage('') const storagePassword = localStorage.getItem('pass') try { const controller = new AbortController() setController(controller) const requestMessageList = [...messageList()] if (currentSystemRoleSettings()) { requestMessageList.unshift({ role: 'system', content: currentSystemRoleSettings(), }) } const timestamp = Date.now() const response = await fetch('/api/generate', { method: 'POST', body: JSON.stringify({ messages: requestMessageList, time: timestamp, pass: storagePassword, sign: await generateSignature({ t: timestamp, m: requestMessageList?.[requestMessageList.length - 1]?.content || '', }), }), signal: controller.signal, }) if (!response.ok) { throw new Error(response.statusText) } const data = response.body if (!data) { throw new Error('No data') } const reader = data.getReader() const decoder = new TextDecoder('utf-8') let done = false while (!done) { const { value, done: readerDone } = await reader.read() if (value) { let char = decoder.decode(value) if (char === '\n' && currentAssistantMessage().endsWith('\n')) { continue } if (char) { setCurrentAssistantMessage(currentAssistantMessage() + char) } throttle() } done = readerDone } } catch (e) { console.error(e) setLoading(false) setController(null) return } archiveCurrentMessage() } const archiveCurrentMessage = () => { if (currentAssistantMessage()) { setMessageList([ ...messageList(), { role: 'assistant', content: currentAssistantMessage(), }, ]) setCurrentAssistantMessage('') setLoading(false) setController(null) inputRef.focus() } } const clear = () => { inputRef.value = '' inputRef.style.height = 'auto'; setMessageList([]) setCurrentAssistantMessage('') setCurrentSystemRoleSettings('') } const stopStreamFetch = () => { if (controller()) { controller().abort() archiveCurrentMessage() } } const retryLastFetch = () => { if (messageList().length > 0) { const lastMessage = messageList()[messageList().length - 1] console.log(lastMessage) if (lastMessage.role === 'assistant') { setMessageList(messageList().slice(0, -1)) requestWithLatestMessage() } } } const handleKeydown = (e: KeyboardEvent) => { if (e.isComposing || e.shiftKey) { return } if (e.key === 'Enter') { handleButtonClick() } } return ( <div my-6> <SystemRoleSettings canEdit={() => messageList().length === 0} systemRoleEditing={systemRoleEditing} setSystemRoleEditing={setSystemRoleEditing} currentSystemRoleSettings={currentSystemRoleSettings} setCurrentSystemRoleSettings={setCurrentSystemRoleSettings} /> <Index each={messageList()}> {(message, index) => ( <MessageItem role={message().role} message={message().content} showRetry={() => (message().role === 'assistant' && index === messageList().length - 1)} onRetry={retryLastFetch} /> )} </Index> {currentAssistantMessage() && ( <MessageItem role="assistant" message={currentAssistantMessage} /> )} <Show when={!loading()} fallback={() => ( <div class="h-12 my-4 flex gap-4 items-center justify-center bg-slate bg-op-15 rounded-sm"> <span>AI正在思考中...</span> <div class="px-2 py-0.5 border border-slate rounded-md text-sm op-70 cursor-pointer hover:bg-slate/10" onClick={stopStreamFetch}>停止</div> </div> )} > <div class="my-4 flex items-center gap-2 transition-opacity" class:op-50={systemRoleEditing()}> <textarea ref={inputRef!} disabled={systemRoleEditing()} onKeyDown={handleKeydown} placeholder="问些问题吧..." autocomplete="off" autofocus onInput={() => { inputRef.style.height = 'auto'; inputRef.style.height = inputRef.scrollHeight + 'px'; }} rows="1" w-full px-3 py-3 min-h-12 max-h-36 rounded-sm bg-slate bg-op-15 resize-none focus:bg-op-20 focus:ring-0 focus:outline-none placeholder:op-50 dark="placeholder:op-30" scroll-pa-8px /> <button onClick={handleButtonClick} disabled={systemRoleEditing()} h-12 px-4 py-2 bg-slate bg-op-15 hover:bg-op-20 rounded-sm> Send </button> <button title="Clear" onClick={clear} disabled={systemRoleEditing()} h-12 px-4 py-2 bg-slate bg-op-15 hover:bg-op-20 rounded-sm> <IconClear /> </button> </div> </Show> </div> ) }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。