首先假定你们了解并正常使用 Github,不然建议先了解后再做此配置
0. 目的
- 可以使用原生的 openai 提供的 GPT-4o 和 GPT-4o mini 模型
- 具体次数可参考官方使用限制,免费用户每天可使用一定数量,4o 模型一天约 50 次调用,4o-mini 每天约 150 次调用
- 一点对接 Github Models 的 Azure 提供模型的设计思路,方便让 AI 为自己编写代码,供前端小白参考
1. 资格申请
Github
- 首先你要有一个 Github 账号,如果没有,请先申请
- Github Model 申请 github.com/marketplace…,步骤如下图所示
- 通过之后,可见图片3,可点其中一个模型 OpenAI GTP-4o
- 进入之后,点 Get Started → 按要求创建 Github Token
2. 如何使用
之前有用 nodejs 写一个本地化的启动脚本,考虑到对一些人来说不实用,就改用在 uTools 发布插件了,比较纯净。
通过 uTools
- 打开插件应用市场,搜索《HI AI》下载即可
- 在搜索栏输入 HI 或 AI,打开此工具即可
- uTools 工具简介可参考《从自制OCR到效率神器:uTools如何改变我的工作流》
3. 说在后面
这套页面本身是全程使用 AI 来搭建的,全程自己的编码量小于 30%,如有兴趣。希望 AI 能给你们工作生活带来帮助。
4. 灵感来源
5. 开发思路
【注:以下开始,都是在从 AI 编码方面讲技术思路,有兴趣可以看看】
模块划分
按自己常用的各类 AI 模型的 web 页面,自己把功能划分为如下几块
- TOKEN 设置功能
- 会话管理
- 聊天窗口
- 发送窗口
- 辅助功能(导出等)
API 设计
由于本地启动供他人使用会比较麻烦,故做成 uTools 工具的一个插件使用,使用 uTools 提供的 nodejs 能力,和 uTools 提供的本地数据库
- uTools DB 提供如下:
- GITHUB_TOKEN 的存储
- 会话列表(不涉及网络传输,为了数据简单处理,消息直接存会话里面)
- 方法设计
- githubToken()、获取、设置 githubToken
- session()、获取、设置 session
- queryAnswer()、获取 AI 的答复
6. 开发设计
主进程 / 客户端(uTools)
- 数据库格式
// token
utools.db.put({
_id: 'tokens',
githubToken: 'string',
})
// sessions
utools.db.put({
_id: 'sessions',
sessions: {
1726928423680 :{ // 会话ID
id: 'number', // Date().now
name: 'string',
messages: [{
role: 'user', // system, user, assistant
model: 'gpt-4o', // gpt-4o, gpt-4o-mini
message: 'string',
steam: false, // 是否流式输出
}],
},
},
})
- 和渲染进程交互
window.utools = {
// 复制
copyText: text => utools.copyText(text),
// 默认浏览器打开链接
shellOpenExternal: url => utools.shellOpenExternal(text),
// 操作数据库
db: utools.db,
queryAnswer: openai.queryAnswer, // 对接 Azure 提供的 api
}
渲染进程(Web)
- TOKEN 设置功能
- 支持设置、修改
- 会话管理
- 支持会话的增、删、改
- 按 id(时间)排序
- 聊天窗口
- 支持三种对话显示,会话 propmt,问,AI 回答
- 支持 markdown 展示
- 支持展示图片
- 考虑 code 过长的换行处理
- 支持点击链接跳转默认浏览器(uTools 内默认不支持)
- 发送窗口
- 可以选择 AI 回答的模型,默认 gpt-4o-mini
- Shift + Enter 发送
- 辅助功能
- 导出 markdown 格式到电脑
编码
先这样写、再那样、最后这样,代码就写好了,在前端工程师的眼里,页面样式转成代码,不就像切图仔切图一样流畅。
…
开个玩笑,这个项目主题是什么,怎么丝滑使用 AI,代码肯定不能全自己写了。
选项目框架
首先打开老朋友 Cursor 编辑器。把项目基座建好,这里我们使用 svelte,简单丝滑。
关于怎么使用 Cursor 写代码,这里不过多介绍,仅展示两组,B 站上本身很多介绍视频推荐大家去学习,这里仅让大家了解有这样一个东西,希望 AI 给大家编程带来更多的帮助,感谢大家阅读~
- 开始编写 propmt,我选的模型是 claude-3.5-sonnet 第一次尝试,按自己想法写,先让 AI 写整体框架,不涉及太细的东西
我需要你帮忙写一个页面,页面细节如下,我提几点要求,结构清晰,样式要尽量好看
1. 有一个初始页面,这个页面内容有
1.1 加一个确认按钮,确认成功调用 createGithubToken() 方法,暂先把这个 token 保存在 localstorage 里面
1.2 每次进入页面先检查有没有这个token,没有就展示设置页,有的话就先不展示这个初始页,直接进入正常页面
1.3 在正常页面,可以点击修改TOKEN 重新进入到这个初始页面,并会在确定旁边多一个取消按钮,点击回到正常页面
2. 正常页面
2.1 如果有 token,则直接进入正常页面
2.2 首先页面分为左右两个区域,左边区域宽度在200px左右,右侧自适应,左侧需要有一个按钮,可以展开和收缩
2.3 左侧上方有一个修改 GITHUB_TOKEN 的按钮,点击之后就回到首次进入的初始页面。有取消按钮,可以回到正常页面。
2.4 左侧的接下来需要有会话列表(sessions),会话列表显示会话的名字(name),这个鼠标悬浮到上面需要有 hover 效果,hover时右边出现两个小icon,可以修改会话名称(name),还有一个是删除会话的功能
2.5 右侧上面是主体模块,是消息列表,是选中的其中一个会话里面的聊天信息,和通常的聊天软件一样,自己说的话在右边展示,AI说的话在左边展示,会话都要在气泡里面,让样式好看一点,可以参照微信或iMessage
2.6 右侧下面是一个发送框,需要有两个元素,一个 textarea,一个发送按钮
- AI 帮忙把页面写出来了,并有如下回复,但目前的样式,很简陋,并且有一些别的问题,只能让 AI 一步一步去修复
好的,我来帮您设计这个页面。以下是一个基本的 Svelte 组件实现,包含了您描述的主要功能和布局:
# svelte:renderer/src/routes/+page.svelte
<script>
import { onMount } from 'svelte';
import { fade, slide } from 'svelte/transition';
let token = '';
let showInitialPage = true;
let sessions = [];
let selectedSession = null;
let messages = [];
let newMessage = '';
let showLeftPanel = true;
onMount(() => {
token = localStorage.getItem('github_token');
if (token) {
showInitialPage = false;
}
});
function createGithubToken() {
// 调用 createGithubToken() 方法
token = 'new_token'; // 假设这是返回的 token
localStorage.setItem('github_token', token);
showInitialPage = false;
}
function modifyToken() {
showInitialPage = true;
}
function cancelModifyToken() {
showInitialPage = false;
}
function toggleLeftPanel() {
showLeftPanel = !showLeftPanel;
}
// 其他功能函数...
</script>
<main>
{#if showInitialPage}
<div class="initial-page" transition:fade>
<h2>设置 GitHub Token</h2>
<input type="text" bind:value={token} placeholder="输入你的 GitHub Token">
<button on:click={createGithubToken}>确认</button>
{#if !showInitialPage}
<button on:click={cancelModifyToken}>取消</button>
{/if}
</div>
{:else}
<div class="main-page">
<div class="left-panel" class:hidden={!showLeftPanel} transition:slide={{duration: 300}}>
<button on:click={modifyToken}>修改 GITHUB_TOKEN</button>
<button on:click={toggleLeftPanel}>收起/展开</button>
<div class="sessions-list">
<!-- 会话列表 -->
</div>
</div>
<div class="right-panel">
<div class="messages-container">
<!-- 消息列表 -->
</div>
<div class="input-area">
<textarea bind:value={newMessage} placeholder="输入消息..."></textarea>
<button>发送</button>
</div>
</div>
</div>
{/if}
</main>
<style>
main {
width: 100%;
height: 100vh;
display: flex;
}
.initial-page {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.main-page {
display: flex;
width: 100%;
}
.left-panel {
width: 200px;
border-right: 1px solid #ccc;
transition: width 0.3s;
}
.left-panel.hidden {
width: 0;
overflow: hidden;
}
.right-panel {
flex: 1;
display: flex;
flex-direction: column;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.input-area {
display: flex;
padding: 10px;
}
.input-area textarea {
flex: 1;
margin-right: 10px;
}
/* 添加更多样式... */
</style>
这个基本结构实现了您描述的主要功能:
1. 初始页面和正常页面的切换
2. GitHub Token 的设置和存储
3. 左右分栏布局,左侧可收缩
4. 修改 Token 的功能
5. 消息列表区域和输入区域的基本布局
您需要进一步完善以下部分:
1. 实现会话列表的渲染和交互
2. 添加会话的编辑和删除功能
3. 实现消息列表的渲染,区分自己和 AI 的消息
4. 添加发送消息的功能
5. 优化样式,使其更美观
建议您逐步实现这些功能,并根据需要调整样式。如果您需要某个特定部分的详细实现,请告诉我,我会为您提供更具体的代码。
- 先修复几个明显问题,我提给它
首先先解决第几个问题,
问题1:从初始页面到正常页面切换过程很丑,会有线动来动去,需要去掉这个过程或者让他更淡化美观一点。
问题2:在我侧边栏收起了之后,我没办法展开,需要调整一下收起展开按钮位置,这个最好能用svg图标,好看一点
- AI回复,并且建议修改代码,我这也直接接受它的建议(因为我并不想自己写)
好的,我理解您的问题。让我们来解决这两个问题。
1. 优化页面切换动画
2. 调整侧边栏收起/展开按钮的位置和样式
以下是修改后的代码:
# svelte:renderer/src/routes/+page.svelte
<script>
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
// ... 其他变量保持不变
let showLeftPanel = true;
onMount(() => {
token = localStorage.getItem('github_token');
if (token) {
showInitialPage = false;
}
});
// ... 其他函数保持不变
function toggleLeftPanel() {
showLeftPanel = !showLeftPanel;
}
</script>
<main>
{#if showInitialPage}
<div class="initial-page" transition:fade={{duration: 300}}>
<h2>设置 GitHub Token</h2>
<input type="text" bind:value={token} placeholder="输入你的 GitHub Token">
<button on:click={createGithubToken}>确认</button>
{#if !showInitialPage}
<button on:click={cancelModifyToken}>取消</button>
{/if}
</div>
{:else}
<div class="main-page" transition:fade={{duration: 300}}>
<div class="left-panel" class:hidden={!showLeftPanel}>
<button on:click={modifyToken}>修改 GITHUB_TOKEN</button>
<div class="sessions-list">
<!-- 会话列表 -->
</div>
</div>
<div class="toggle-button" on:click={toggleLeftPanel}>
<svg viewBox="0 0 24 24" width="24" height="24">
<path d={showLeftPanel ? "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" : "M10.59 6L12 7.41 8.83 12 12 16.59 10.59 18l-6-6z"} />
</svg>
</div>
<div class="right-panel">
<div class="messages-container">
<!-- 消息列表 -->
</div>
<div class="input-area">
<textarea bind:value={newMessage} placeholder="输入消息..."></textarea>
<button>发送</button>
</div>
</div>
</div>
{/if}
</main>
<style>
main {
width: 100%;
height: 100vh;
display: flex;
}
.initial-page, .main-page {
width: 100%;
height: 100%;
}
.initial-page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.main-page {
display: flex;
position: relative;
}
.left-panel {
width: 200px;
border-right: 1px solid #ccc;
transition: width 0.3s, margin-left 0.3s;
overflow: hidden;
}
.left-panel.hidden {
width: 0;
margin-left: -200px;
}
.toggle-button {
position: absolute;
left: 200px;
top: 50%;
transform: translateY(-50%);
background-color: #f0f0f0;
border: 1px solid #ccc;
border-left: none;
padding: 10px 5px;
cursor: pointer;
transition: left 0.3s;
z-index: 10;
}
.left-panel.hidden + .toggle-button {
left: 0;
}
.right-panel {
flex: 1;
display: flex;
flex-direction: column;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.input-area {
display: flex;
padding: 10px;
}
.input-area textarea {
flex: 1;
margin-right: 10px;
}
/* 添加更多样式... */
</style>
这些修改解决了您提到的两个问题:
1. 页面切换动画:我们只使用了 `fade` 过渡效果,并将持续时间设置为 300 毫秒。这样可以使过渡更加平滑和淡化。
2. 侧边栏收起/展开按钮:
- 添加了一个新的 `toggle-button` 元素,它始终可见。
- 使用 SVG 图标来表示展开/收起状态。
- 按钮位置会随着侧边栏的状态而改变。
这些更改应该能够改善用户体验,使页面切换更加流畅,并且在侧边栏收起时仍然可以轻松地展开它。
如果您还有其他需要调整或改进的地方,请告诉我,我会继续帮您优化代码。