前言
近期忙于将AI的功能接入到公司的业务中,过程中也踩了很多坑,一一记录一下。以下的问题如果深入研究都可以作为一篇文章,但本文着重讲解决的方式。
1. 多端接入的方式
Web端(基于Angular)
关键:使用fetch
的方式获取结果,而流存在于body.getReader()
中
示例代码
try {
const serviceRes = await fetch(url, {
xxxxx
});
if (serviceRes.ok) {
const reader = serviceRes.body?.getReader();
if (reader) {
await this.readSSE(reader);
}
} else {
console.error("HTTP error:", serviceRes.statusText);
}
} catch (error) {
console.error("Fetch error:", error);
}
APP端(基于uniapp)
查阅了一定的资料,最终决定app端使用是市场上的插件,把插件跑通即可。就不提供示例代码
2.中断会话
业务场景
当用户觉得会话内容响应时间太长,或者想中断这次会话。
技术方案
关键:使用 AbortController
进行中断处理 , MDN相关说明,关键使用的是以下两个内容
- AbortController.signal
- AbortController.abort()
核心思想:将signal作为参数传入到fetch中,当我们执行中断方法controller.abort()
,它会通知使用了signal的异步请求以达到中断的效果。
示例代码
//发起AI请求
async changeAI({ question, sessionId }) {
const params = {
question,
sessionId: this.lastSessionId,
};
const url = 'xxxxxxx'
//注意只有通过fetch的方式才能拿到response.body下的stream
this.controller = new AbortController();
const signal = this.controller.signal;
try {
const serviceRes = await fetch(url, {
method,
headers,
body,
signal,
});
if (serviceRes.ok) {
const reader = serviceRes.body?.getReader();
if (reader) {
const sessionId = await this.readSSE(reader);
return sessionId;
}
} else {
console.error("HTTP error:", serviceRes.statusText);
}
} catch (error) {
console.error("Fetch error:", error);
}
}
//中断会话
stopStreaming() {
if (this.controller) {
this.controller.abort(); // 中止流
this.controller = null; // 重置 controller
}
}
3.滚动条自动触底
业务场景
每次进行发送对话,滚动条都需要沉底,要不然用户得发完一句话,还得自己拖动滚动条才能看到。
技术方案
核心思想:
- 首先判断当前滚动条是否处于底部,处于底部了就不需要自动滚动了
- 倘若不处于底部,则需要scrollTop重新设置
相关代码
画面的布局
<div class="ai-modal-container" >
<div class="ai-top-container">
</div>
<div #aiContainer class="ai-container">
<div #listContainer class="list-container">
<ng-container *ngFor="let item of questionList">
</ng-container>
</div>
</div>
<div class="ai-bottom-container" #bottomContainer>
</div>
</div>
结合图片(很尽力在画了)
可以看到aiContainer的高度其实是固定的,而listContainer的高度是
根据数据项
来决定的,如果数据达到一定量时,一定会大于aiContainer的高度的,这时就需要自动滚动了。
例如:图中您好4已经让listContainer>aiContainer了
相关js处理
//滚动处理
handleScollTop() {
const overScroll = this.overScrollHeight();
const scrollContentHeight = this.listContainer.nativeElement.clientHeight;
if (overScroll > 0) {
this.aiContainer.nativeElement.scrollTop = scrollContentHeight;
}
}
//判断滚动条是否处于底部
overScrollHeight() {
const bottomContentHeight = this.bottomContainer.nativeElement.clientHeight;
const scrollViewHeight =
this.aiContainer.nativeElement.clientHeight - bottomContentHeight;
const scrollContentHeight = this.listContainer.nativeElement.clientHeight;
return scrollContentHeight - scrollViewHeight;
}