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><aborder-b border-slate border-none hover:border-dashedhref="https://wwji.lanzouf.com/iVoeB0o7wrxe" target="_blank">安卓端下载<span px-1>|</span></a><aborder-b border-slate border-none hover:border-dashedhref="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: HTMLTextAreaElementconst [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.valueif (!inputValue) {return}// @ts-ignoreif (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.bodyif (!data) {throw new Error('No data')}const reader = data.getReader()const decoder = new TextDecoder('utf-8')let done = falsewhile (!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><SystemRoleSettingscanEdit={() => messageList().length === 0}systemRoleEditing={systemRoleEditing}setSystemRoleEditing={setSystemRoleEditing}currentSystemRoleSettings={currentSystemRoleSettings}setCurrentSystemRoleSettings={setCurrentSystemRoleSettings}/><Index each={messageList()}>{(message, index) => (<MessageItemrole={message().role}message={message().content}showRetry={() => (message().role === 'assistant' && index === messageList().length - 1)}onRetry={retryLastFetch}/>)}</Index>{currentAssistantMessage() && (<MessageItemrole="assistant"message={currentAssistantMessage}/>)}<Showwhen={!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()}><textarearef={inputRef!}disabled={systemRoleEditing()}onKeyDown={handleKeydown}placeholder="问些问题吧..."autocomplete="off"autofocusonInput={() => {inputRef.style.height = 'auto';inputRef.style.height = inputRef.scrollHeight + 'px';}}rows="1"w-fullpx-3 py-3min-h-12max-h-36rounded-smbg-slatebg-op-15resize-nonefocus:bg-op-20focus:ring-0focus:outline-noneplaceholder:op-50dark="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>)
}