大数跨境
0
0

《AI打工摸鱼笔记》Streamlit + AnythingLLM

《AI打工摸鱼笔记》Streamlit + AnythingLLM 数翼
2024-07-31
0
导读:本文使用 Streamlit 工具配合 AnythingLLM 和 LM Studio 搭建的本地知识库, 上传 Excel 技术需求文件,从知识库获取信息自动回答(RAG),实时显示 LLM 输出,
本文使用 Streamlit 工具配合 AnythingLLM 和 LM Studio 搭建的本地知识库, 上传 Excel 技术需求文件,从知识库获取信息自动回答(RAG),实时显示 LLM 输出,同时展示当前工作进度。

书接上文,今天继续完成自动填写技术调研表的下篇,高级版本的 AI 助理员工的实现。

  • • 背景需求和设计思路(上篇)

  • • Anything LLM 使用(上篇)

  • • 基础版AI员工(LM Studio + Anything LLM + 知识库)(上篇)

  • • 高级版AI员工(Streamlit 程序)「下篇」

我们现在看下最终的效果:

最终的运行效果

前提

首先我们要把 LM Studio 以及 AnythingLLM 运行和配置好,具体内容可以参考上一篇文章。

Streamlit

Streamlit 是我们的老朋友了,是现在构建 AI 应用程序 UI 的最佳选择之一。

关于 Streamlit 的介绍和使用可以参考之前的文章:

  • • todo

安装

如果还没有安装,我们使用 pip 安装一下 Streamlit。

pip install streamlit  

标题

首先给应用程序增加,标题我们可以使用 st.title 方法,

import streamlit as st

st.set_page_config(layout="wide") # 设置页面宽度
st.title("RAG Excel")
显示标题

为了美观,我们使用图片来做标题:

import streamlit as st

st.set_page_config(layout="wide")

h1, h2 = st.columns([3,1])
with h1:
    st.image('./assets/shuyi-llm-1.png', width=480)
with h2:
    st.image('./assets/shuyi-llm-2.png', width=100)
程序标题

AnythingLLM API 密钥

接下来为了调用 Anything LLM 来实现 RAG,需要获取 AnythingLLM 接口调用的密钥。

打开 Anything LLM 设置,选择「API密钥」,然后点击「生成」:

生成密钥

复制生成的密钥。

生成的密钥

我们可以在程序中把 密钥记录下来,

api_key = '6DDGHVK-C9Q44NT-NGMVN8H-QG3086Y'

但是更好的方式是在程序上让用户可以自己设置密钥,这样密钥变化的时候就不用修改程序,也降低了密钥泄露的风险。

我们使用一个密码框,来记录密钥,提供一个默认值,也可让用户更改:

apikey = st.text_input('API KEY'type='password', value=api_key)

效果如下:

兼容 OpenAI 的聊天接口

兼容 OpenAPI

我们知道 AnythingLLM 提供了兼容 OpenAI 的接口。

查看文档,可以看到其接口调用示例。

所需要的三个信息,除了 API Key,还有两个没确认:

  • • API Key

  • • 模型名称

  • • URL

BaseURL

如果是本机运行,兼容 OpenAI 接口的 BaseURL 是 : http://localhost:3001/api/v1/openai , 我们再程序中指定一下:

openai_base_url = "http://localhost:3001/api/v1/openai"

获取模型(工作区)

AnythingLLM 的工作区就是 OpenAI 接口要传的模型,有两种方法可以获取。

AnythingLLM 管理 API

AnythingLLM 提供了一整套管理接口,能在 UI 上做的任何事情,也能通过接口完成。

AnythingLLM 接口

当然也包含列出工作区的接口:

工作区列表接口

我们通过 requests 模块发起请求来获取工作区列表:

url = 'http://127.0.0.1:3001/api/v1/workspaces'
headers = {
    'accept''application/json',
    'Authorization''Bearer ' + apikey
}

# 发送GET请求
response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()
    workspaces = {}
    for workspace in data['workspaces']:
        workspaces[workspace['slug']] = workspace['name']

工作区列表接口返回了关于工作区很详细的信息:

获取工作区接口返回

使用 OpenAI API 获取模型

OpenAI 的 API 有一个 models 接口来返回模型列表,Anything LLM 也支持了这个接口:

获取模型结果

Python 程序调用也很简单:

client = OpenAI(
    api_key=api_key,
    base_url=openai_base_url,
)
client.models.list()

接口返回符合 OpenAI API 的规范:

获取模型接口返回结果

界面选择模型(工作区)

我们在程序上提供一个用下拉列表选择模型的功能。

model = st.selectbox("Workspaces", workspaces.keys(), format_func=lambda x: workspaces[x])

调整一下UI,把 API 和模型两个控件放到一行:

col1, col2 = st.columns(2)
apikey = col1.text_input('API KEY'type='password', value=api_key)
获取工作区并下拉显示

文件上传

然后我们创建一个文件上传按钮。

uploaded_file = st.file_uploader("上传 Excel 文件"type="xlsx")

文件上传成功显示文件内容,显示的时候预留一部分区域给未来的 LLM 输出实时显示。

划分出「文件内容」和「LLM实时输出」的显示区域。

col_grid, col_reply = st.columns([21])
area_grid = col_grid.empty()
area_reply = col_reply.empty()

当文件上传的时候,显示文件内容:

if uploaded_file is not None:
    df = get_df()
    area_grid.data_editor(df, use_container_width=True)

看看效果:

上传文件、显示文件内容

RAG 调用

RAG 的调用也很简单,我们先写一个 Chat 函数:

def chat(model_select, prompt):
    print(prompt)
    chat_completion = client.chat.completions.create(
        messages=[
            {
                "role""user",
                "content": prompt,
            }
        ],
        model=model_select,
        temperature=0.7,
        stream=True,
    )
    for completion in chat_completion:
        print(completion.choices[0].delta.content)
        yield completion.choices[0].delta.content

然后增加一个 「RAG」 的按钮:

rag = st.button('RAG', use_container_width=Truetype='primary')

点击按钮的时候遍历数据,如果有描述那么针对描述做应答问答的生成, 同时在 LLM 应答区域实时输出 LLM & RAG 应答结果。

if rag:
    for idx, row in df.iterrows():
        condition = row[name_desc]
        if condition and type(condition) == str:
            print('>>>', condition)

            reply = ''
            for xx in chat(model, condition):
                reply = reply + xx
                area_reply.success(reply)
            df.loc[idx, name_reply] = reply
            processed.append(idx)

            area_grid.dataframe(use_container_width=True, data=df)
实时显示 LLM 回复内容

文件保存

为了避免 LLM 失败等异常,每次成功回答我们都保存一次文件:

df.to_excel(uploaded_file.name.replace('.xlsx''_reply.xlsx'), index=False)

回答过程中搞得文件可能是这样的:

生成的EXCEL文件

显示进度

功能实现了,不过由于整个文档的时间很长,我们看不到当前生成到哪条了,生成之后的结果也不能在界面上很方便地看到。

我们做一些优化,显示一下文档的进度:

  • • 当前正在处理的行用黄色背景表示

  • • 已经处理成功的行用绿色背景表示

使用 df.style.apply 方法来实现:

def row_bg(row):
    index = row.name
    if index == idx:
        return ['background-color: #ffffb8'] * len(row)
    elif index in processed:
        return ['background-color: #d9f7be'] * len(row)
    else:
        return [''] * len(row)


area_grid.dataframe(
    df.style.apply(
        row_bg, subset=(processed + [idx], slice(None),),
        axis=1
    ),
    use_container_width=True,
)

运行的效果如下:

最终的运行效果

最后看一个完整的视频吧:

最终的运行效果
相关文章阅读

--- END ---


【声明】内容源于网络
0
0
数翼
专注 AIGC 人工智能知识传播和实践
内容 228
粉丝 0
数翼 专注 AIGC 人工智能知识传播和实践
总阅读124
粉丝0
内容228