<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css">
<div id="content_views" class="markdown_views prism-dracula">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p><img src="https://img-blog.csdnimg.cn/f871a32b84934e86977b03a249b0c63d.gif" alt="请添加图片描述"></p>
一、需求背景
学英语,最大的痛苦莫过于背单词!
不知道你平时都是用什么方式在背单词呢?硬啃单词书?字典?还是说各类的背单词APP来回跳转?
不可否认的是,单词一两遍完全记不住,没有个三四五六七八遍,都很难在考场的卷子上认出他!
所以,这次我们来做一个通关英语四六级的背单词神器,让他能够基于艾宾浩斯遗忘规律来辅助我们高效背单词。
这个项目也是AIGC
的一个方向性的探索,我们基于LLM的能力,进一部封装。相比于专栏中的前几个项目是直接基于OpenAI接口的直接生成,这次我们需要对模型进行数据的填喂。同时制定好相应的语料生成规则,让他能够根据我们的语料信息生成到我们的答案内容。
所以在本项目中,我们使用到的技术包括:语料Embedding技术
,Prompt微调技术、``Fine Tune技术
,正是通过这三种技术能力的加持,由此颠覆以往的机械式背单词!打造一款更加完美的背单词程序!
二、项目原理及架构
2.1 实现原理
(1)语料的准备
想要有好的单词记忆效果,我们的单词语料必须准备得足够完整!这里我们选用了GitHUB中开源词典数据项目。其中包含了四六级、考研、雅思托福等。这里我们主要针对英语四六级准备,所以这里使用四六级的词汇书就足够了!将其下载,然后导入到数据库中。
(2)制定LLM模型背单词规则
背过单词的都知道,人的记忆功能都是符合记忆曲线的,同样地我们冶可以将这种记忆规则迁移到我们程序中!其中最重要的就是构建好相应的Prompt来满足单词记忆的规则效果!
- 先对LLM进行记忆规则的自定义!
- 再对LLM输入背单词进行词义混淆内容的设定!
(3)记忆已经学会的单词
为了让程序记住我们已经背诵过了的单词,就要让LLM
具备记忆功能。在传统的web应用开发过程中,说到数据存储,第一时间我们考虑得更多得除了关系型数据库以及中间件缓存数据库!这是由于业务得特性所决定得!我们在web应用中,数据是规整的!是结构化的。所以用传统的关系型数据库完全可以满足系统的检索需求!
但是,这次我们面对的是大语言模型,而且我们的数据是完全基于文本语料的,可以说不是完全地结构化以及关系型的数据!这个时候我们结合时下大火的向量数据库Milvus
来进行数据的存储和检索!也就是传说中的Embedding技术
【该技术的核心原理:将文本内容通过数学运算,将其转化为向量。然后基于向量间的相似度运算来进行内容的匹配!从而检索出当前内容的最高相似度数据
】
Milvus 是一款开源的特征向量相似度搜索引擎,具有使用方便、实用可靠、易于扩展、稳定高效和搜索迅速等特点,在全球范围内被上百家组织和机构所采用。Milvus 已经被广泛应用于多个领域,其中包括图像处理、机器视觉、自然语言处理、语音识别、推荐系统以及新药发现等。
Milvus
学习教程大全:
2.2 技术架构
2.3 技术栈
模块 | 语言及框架 | 涉及的技术要点 |
---|---|---|
小程序前端 | 基于VUE 2.0语法 +Uni-app跨平台开发框架 | Http接口通信、Flex布局方式、uView样式库的使用、JSON数据解析、定时器的使用 |
小程序接口服务端 | Python + Flask WEB框架 | rest接口的开发、 ChatGPT API接口的数据对接 、 前后端websocket实时通信 |
2.4 数据交互原理
三、项目功能的实现
3.1 ChatGPT API的接入
要接入ChatGPT API,需要按照以下步骤进行操作:
- 注册一个账号并登录到OpenAI的官网:https://openai.com/
- 在Dashboard页面上,创建一个API密钥。在“API Keys”选项卡下,点击“Generate New Key”按钮。将生成的密钥保存好,以备后续使用。
- 选择所需的API服务,例如“Completion” API,以使用OpenAI的文本生成功能。
使用Python
调用ChatGPT API
实现代码如下:
- 方法一:使用
request
库
import requests
import json
# 构建API请求
url = “https://api.openai.com/v1/engines/davinci-codex/completions”
headers = {
“Content-Type”: “application/json”,
“Authorization”: “Bearer YOUR_API_KEY”}
data = {
“prompt”: “Hello, my name is”,
“max_tokens”: 5
}
# 发送API请求
response = requests.post(url, headers=headers, data=json.dumps(data))
# 解析API响应
response_data = json.loads(response.text)
generated_text = response_data[“choices”][0][“text”]
print(generated_text)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 方式二:使用
openAI库
from flask import Flask, request
import openai
app = Flask(name)
openai.api_key = “YOUR_API_KEY_HERE”
@app.route(“/”)
def home():
return “Hello, World!”
@app.route(“/chat”, methods=[“POST”])
def chat():
data = request.json
response = openai.Completion.create(
engine=“davinci”,
prompt=data[“message”],
max_tokens=60
)
return response.choices[0].text
if name == “main”:
app.run()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
3.2 小程序端设计与实现
首页 | 学习页 |
---|---|
学习统计页 | |
– | – |
3.3 Milvus数据库的接入
- JAVA SDK工具类接入
- FLAT:FLAT适用于希望在小规模、百万级数据集上获得完全准确和精确搜索结果的场景。
- IVF_FLAT:IVF_FLAT是一种基于量化的索引,适用于追求查询准确度和速度之间的理想平衡的场景。
- IVF_SQ8:IVF_SQ8是一种基于量化的索引,适用于那些资源非常有限且需要显著减少磁盘、CPU和GPU内存消耗的场景。
- IVF_PQ:IVF_PQ是一种基于量化的索引,适用于那些即使付出准确度代价也要追求高查询速度的场景。
- HNSW:HNSW是一种基于图的索引,适用于对搜索效率有高要求的场景。
- ANNOY:ANNOY是一种基于树的索引,适用于追求高召回率的场景。
- RAFT: 基于GPU的一种索引
3.4 小程序单词学习功能实现
<!--pages/learning/learning.wxml-->
<view class=“bgWrapper bg-linear-{ {colorType}}”></view>
<view class=“topline” wx:if=“{
{!learnDone}}”>
<view class=“progress”>{
{learnedNum}} / {
{learnNum}}</view>
</view>
<view class=“wordWrapper” bindtap=“playVoice” wx:if=“{
{!learnDone}}”>
<view class=“word word-color-{
{colorType}}” wx:if=“{
{ wordMode == 0 }}”>{
{wordDetail.word}}</view>
<view class=“repeatTime” wx:if=“{
{ wordMode == 0 }}”>
<view class=“times first {
{ thisWordRepeatTime>=1? ‘bg-color-light-’+colorType : ‘bg’ }}”
wx:if=“{
{ repeatTimes>1 }}”></view>
<view class=“times {
{ thisWordRepeatTime>=2? ‘bg-color-light-’+colorType : ‘bg’ }}”
wx:if=“{
{ repeatTimes>=2 }}”></view>
<view class=“times {
{ thisWordRepeatTime>=3? ‘bg-color-light-’+colorType : ‘bg’ }}”
wx:if=“{
{ repeatTimes>=3 }}”></view>
<view class=“times {
{ thisWordRepeatTime4? ‘bg-color-light-’+colorType : ‘bg’ }}“
wx:if=”{
{ repeatTimes4 }}”></view>
</view>
<view class=“pron” wx:if=“{
{ wordMode == 0 && wordDetail.phonetic.length > 0 }}”>/ {
{wordDetail.phonetic}} / <text
class=“voice iconfont icon-sound”></text></view>
<view class=“timing” wx:if=“{
{ wordMode == 1 }}” catchtap=“{
{ isBtnActive? ‘showWord’:‘’ }}”>
<mpProgress class=“progress” config=“{
{wordTimingConfig}}” reset=“{
{wordTimingReset}}”
isStop=“{
{wordTimingStop}}” percentage=“{
{100}}” bindtimingOut=“timingOut” data-type=“word”></mpProgress>
<!-- <button class=“resetbtn” type=“primary” bindtap=“resetCanvasFunc”>reset</button> -->
</view>
<view class=“timing” wx:if=“{
{ wordMode == 2 }}”>
<view class=“model”></view>
<view class=“model phonetic”></view>
</view>
</view>
<view class=“content” wx:if=“{
{!learnDone}}”>
<view class=“chooseCorrect” wx:if=“{
{ contentMode == 0 }}”>
<view class=“choice {
{choiceBgList[index]}}” wx:for=“{
{choiceOrder}}” wx:key=“index” hover-class=“wasTaped”
data-index=“{
{index}}” bindtap=“{
{ isBtnActive? ‘checkChoice’:‘’ }}”>
<view class=“pos”>{
{wrongTransWordList[item].translation.pos}}</view>
<view class=“meaning”> {
{wrongTransWordList[item].translation.meaning}}</view>
</view>
</view>
<view class=“translationWrapper” wx:if=“{
{ contentMode == 1 }}”>
<view class=“transRow” wx:for=“{
{wordDetail.shortTrans}}” wx:key=“index”>
<view class=“pos” wx:if=“{
{ item.pos != ‘’ }}”>{
{item.pos}}</view>
<view class=“meaning {
{ item.more? ‘moreBtn’:‘’ }}” bindtap=“{
{ item.more? ‘toDetail’:‘’ }}”
hover-class=“{
{ item.more? ‘tapedText’:‘’ }}”>{
{item.meaning}}
</view>
</view>
</view>
<view class=“timing” wx:if=“{
{ contentMode == 2 }}” bindtap=“{
{ isBtnActive? ‘showTrans’:‘’ }}”>
<mpProgress class=“progress” config=“{
{contentTimingConfig}}” reset=“{
{contentTimingReset}}”
isStop=“{
{contentTimingStop}}” percentage=“{
{100}}” bindtimingOut=“timingOut” data-type=“content”>
</mpProgress>
<!-- <button class=“resetbtn” type=“primary” bindtap=“resetCanvasFunc”>reset</button> -->
</view>
<view class=“timing” wx:if=“{
{ contentMode == 3 }}” bindtap=“{
{ isBtnActive? ‘showTrans’:‘’ }}”>
<view class=“model”></view>
<view class=“model”></view>
<view class=“model”></view>
</view>
</view>
<view class=“control” wx:if=“{
{!learnDone}}”>
<view class=“btn answerBtn” wx:if=“{
{ controlMode == 0 }}” hover-class=“wasTaped”
bindtap=“{
{ isBtnActive? ‘showAnswer’:‘’ }}”>
<view class=“text”>答案</view>
<view class=“decorate”></view>
</view>
<view class=“knowWrapper” wx:if=“{
{ controlMode == 1 }}”>
<view class=“btn knowBtn left” hover-class=“wasTaped” bindtap=“{
{ isBtnActive? ‘setAsKnown’:‘’ }}”>
<view class=“text word-color-{
{colorType}}”>认识</view>
<view class=“decorate bg-color-light-{
{colorType}}”></view>
</view>
<view class=“btn knowBtn” hover-class=“wasTaped” bindtap=“{
{ isBtnActive? ‘setAsUnknown’:‘’ }}”>
<view class=“text notknowtext”>不认识</view>
<view class=“decorate dforNotKnow”></view>
</view>
</view>
<view class=“knowWrapper” wx:if=“{
{ controlMode == 2 }}”>
<view class=“btn knowBtn left” hover-class=“wasTaped” bindtap=“{
{ isBtnActive? ‘toNextWord’:‘’ }}”>
<view class=“text word-color-{
{colorType}}”>下一个</view>
<view class=“decorate bg-color-light-{
{colorType}}”></view>
</view>
<view class=“btn knowBtn” hover-class=“wasTaped” bindtap=“{
{ isBtnActive? ‘changeToUnknown’:‘’ }}”>
<view class=“text notknowtext”>记错了</view>
<view class=“decorate dforNotKnow”></view>
</view>
</view>
<view class=“btn nextBtn” wx:if=“{
{ controlMode == 3 }}” hover-class=“wasTaped”
bindtap=“{
{ isBtnActive? ‘toNextWord’:‘’ }}”>
<view class=“text word-color-{
{colorType}}”>下一个</view>
<view class=“decorate bg-color-light-{
{colorType}}”></view>
</view>
<view class=“bottomMenu”>
<!-- <view class=“left”>单词详情</view>
<view class=“left”>跳过此轮</view>
<view class=“left”>设为已掌握</view>
<view class=“left last”>加入生词本</view> -->
<view class=“bottomBtn iconfont icon-getDetail” hover-class=“wasTaped-bottom” bindtap=“toDetail”></view>
<view class=“bottomBtn iconfont icon-skip” hover-class=“wasTaped-bottom” data-type=“skip”
bindtap=“{
{ isBtnActive? ‘skip’:‘’ }}”></view>
<view class=“bottomBtn iconfont icon-learned” hover-class=“wasTaped-bottom” data-type=“master”
bindtap=“{
{ isBtnActive? ‘skip’:‘’ }}”></view>
<view class=“bottomBtn iconfont icon-addToNB-{
{isInNotebook?‘yes’:‘no’}}”
hover-class=“wasTaped-bottom{
{isInNotebook?‘1’:‘’}}” bindtap=“toggleAddToNB”></view>
</view>
</view>
<view class=“doneWrapper” wx:if=“{
{learnDone}}”>
<view class=“text word-color-{
{colorType}}”>本组单词学习已完成</view>
<view class=“btn back” hover-class=“wasTaped” bindtap=“goBack”>完成学习</view>
<view class=“btn continue bg-color-light-{
{colorType}}” hover-class=“wasTaped” bindtap=“reInit”>继续学习</view>
</view>
<!-- <view class=“test”>
<button class=“showInfo” data-name=“wordLearningRecord” bindtap=“showInfo”>l-Record</button>
<button class=“showInfo” data-name=“control” bindtap=“showInfo”>control</button>
<button class=“showInfo” data-name=“settings” bindtap=“showInfo”>settings</button>
</view> -->
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
四、推荐阅读
🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :