Compare commits
273 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f4e62ad5b | ||
|
|
2123569598 | ||
|
|
3ecff4bce7 | ||
|
|
4cd8d0e97c | ||
|
|
200f9fb481 | ||
|
|
1ab62ad339 | ||
|
|
7cb8b96ed5 | ||
|
|
b9827529aa | ||
|
|
8ca9e8ff28 | ||
|
|
ede538bfe2 | ||
|
|
2c146aff74 | ||
|
|
703d0f6aa7 | ||
|
|
8e2515f768 | ||
|
|
d9323ea3f6 | ||
|
|
24faba561b | ||
|
|
cbc28d7296 | ||
|
|
f9beb142c8 | ||
|
|
781b782f73 | ||
|
|
160f0b8af4 | ||
|
|
26672ffeda | ||
|
|
0078cdc724 | ||
|
|
9c0820c94a | ||
|
|
cf049511cf | ||
|
|
c52e89d92a | ||
|
|
2c7feae7bb | ||
|
|
52f2a2a046 | ||
|
|
9bf0612e3d | ||
|
|
7da7636abc | ||
|
|
326a9652aa | ||
|
|
b6e1f208e9 | ||
|
|
4815a6c92e | ||
|
|
448e79576c | ||
|
|
3902f6d235 | ||
|
|
72a6878287 | ||
|
|
5eb37ea2e3 | ||
|
|
f29ab1e67f | ||
|
|
341ee9db44 | ||
|
|
2f2221ca47 | ||
|
|
6d128f24f0 | ||
|
|
8721aad18d | ||
|
|
13377191e7 | ||
|
|
110b5694da | ||
|
|
da1c1a225c | ||
|
|
5eb025d9dc | ||
|
|
6003d8dd83 | ||
|
|
b0f5fb2d3e | ||
|
|
6dd066ca72 | ||
|
|
c0dafb95cc | ||
|
|
487235259e | ||
|
|
a592b1cd3f | ||
|
|
6011bac07f | ||
|
|
ae9f4d208e | ||
|
|
78290d360f | ||
|
|
966c582a2a | ||
|
|
bfb76faadb | ||
|
|
40263dd403 | ||
|
|
825e4976ae | ||
|
|
253d4b9b9a | ||
|
|
07b7c966ed | ||
|
|
d78b14721c | ||
|
|
5ad4d520dd | ||
|
|
d879e86cab | ||
|
|
cd54eeb137 | ||
|
|
021d635af0 | ||
|
|
f40d415f07 | ||
|
|
7198654611 | ||
|
|
818f87b5e4 | ||
|
|
c6d91c3e3d | ||
|
|
5c74a28de9 | ||
|
|
e48f4a24c9 | ||
|
|
279fe9c659 | ||
|
|
bab93690fc | ||
|
|
54bed50713 | ||
|
|
caf502d141 | ||
|
|
76e82a9b8f | ||
|
|
574ea4f4d5 | ||
|
|
cf1c853b19 | ||
|
|
fb8fbe96e4 | ||
|
|
7c89f88513 | ||
|
|
1fa714ee71 | ||
|
|
b2fabe211b | ||
|
|
d5edb08b24 | ||
|
|
051c599bb5 | ||
|
|
cd13aee97d | ||
|
|
8146279bbe | ||
|
|
c49c6923a1 | ||
|
|
041e964b30 | ||
|
|
f75ae3ea5f | ||
|
|
0522a42ab7 | ||
|
|
5460b93ba2 | ||
|
|
ab650253d1 | ||
|
|
670131c886 | ||
|
|
2756996125 | ||
|
|
f04a2bfcc7 | ||
|
|
9c5aa5bf2f | ||
|
|
36956520ea | ||
|
|
4f67f4a841 | ||
|
|
e042a76f11 | ||
|
|
13628c5f9a | ||
|
|
5afbae56fc | ||
|
|
2504ea3393 | ||
|
|
07906751c1 | ||
|
|
b7a249f46a | ||
|
|
cbfbbe5e6b | ||
|
|
845adfbc0b | ||
|
|
53ff5040e2 | ||
|
|
77914386b0 | ||
|
|
03edc3e501 | ||
|
|
3f70a0d18c | ||
|
|
b0708c7a8d | ||
|
|
887cf95db7 | ||
|
|
b39b585867 | ||
|
|
042a70c09a | ||
|
|
ffbfcd41f2 | ||
|
|
22ee1a0c97 | ||
|
|
4157201c2c | ||
|
|
6eab501baf | ||
|
|
268bb68122 | ||
|
|
4f5824e964 | ||
|
|
25f5f103c1 | ||
|
|
0c465faf8b | ||
|
|
c94938bc83 | ||
|
|
147b4c0688 | ||
|
|
e1e8b0f056 | ||
|
|
38bc4050ac | ||
|
|
ae31e6dd8b | ||
|
|
e1f125be4e | ||
|
|
597ca146d0 | ||
|
|
9c525b7fa5 | ||
|
|
a5e758bf82 | ||
|
|
370dbfef37 | ||
|
|
1c3b928223 | ||
|
|
454d82b2e4 | ||
|
|
ee6a28b565 | ||
|
|
f50400a204 | ||
|
|
852ca5f849 | ||
|
|
f9a5ae99ee | ||
|
|
7248163b07 | ||
|
|
60d5f7d439 | ||
|
|
088a27df27 | ||
|
|
481d1c4b3a | ||
|
|
6df6ed2920 | ||
|
|
57c73b1424 | ||
|
|
c9c867664e | ||
|
|
65a2ccdc64 | ||
|
|
31631e56ca | ||
|
|
56d32a9908 | ||
|
|
1adff316e5 | ||
|
|
c50e988f5a | ||
|
|
85771825ba | ||
|
|
54e5b41647 | ||
|
|
17803cb7c1 | ||
|
|
64378837ef | ||
|
|
b6d2bc71ce | ||
|
|
fb6c84bc57 | ||
|
|
80c26e4a24 | ||
|
|
eeba2e2665 | ||
|
|
c0968fb581 | ||
|
|
8483c0bc96 | ||
|
|
6b61d917a1 | ||
|
|
8ac255fc55 | ||
|
|
56c2a70a74 | ||
|
|
71deed93df | ||
|
|
3057c29e47 | ||
|
|
554d6b4820 | ||
|
|
e5b4bb41d8 | ||
|
|
0cf65d5933 | ||
|
|
8c2019f8b9 | ||
|
|
4a77880ee1 | ||
|
|
dc07cba1d4 | ||
|
|
b058e1906f | ||
|
|
2ab944996e | ||
|
|
e5acf3d2e6 | ||
|
|
1b5efecc89 | ||
|
|
b2ea386f60 | ||
|
|
d83de508cc | ||
|
|
0a4dfe58a4 | ||
|
|
2c92cd00ae | ||
|
|
67ae61d567 | ||
|
|
cb3822651b | ||
|
|
241690d593 | ||
|
|
f28cd59557 | ||
|
|
991e824bcd | ||
|
|
f031ebc19e | ||
|
|
ebda1056e5 | ||
|
|
0a37fe93b8 | ||
|
|
6df4554c8b | ||
|
|
3e959e5b0f | ||
|
|
e55f8cf7a9 | ||
|
|
c5985ae5be | ||
|
|
3333007e13 | ||
|
|
ff91508d8b | ||
|
|
4ac510ff4a | ||
|
|
269090ea66 | ||
|
|
75ff268e88 | ||
|
|
e615932e7e | ||
|
|
a5b52e1bd1 | ||
|
|
29ef5dda64 | ||
|
|
03eb5e9d2e | ||
|
|
4f07384c66 | ||
|
|
3da68b5ce3 | ||
|
|
b653c25fbc | ||
|
|
e7bba6bd0a | ||
|
|
b5064813af | ||
|
|
01bac077bc | ||
|
|
448c99f969 | ||
|
|
6f85119f03 | ||
|
|
440307fa94 | ||
|
|
17e8bc072b | ||
|
|
67034669a9 | ||
|
|
3d66899b0f | ||
|
|
ce29d14f46 | ||
|
|
50aeb24582 | ||
|
|
fc75c4513a | ||
|
|
aeb7a7e93f | ||
|
|
61bc815540 | ||
|
|
7d4a6b5edf | ||
|
|
3c33ca7b89 | ||
|
|
f1ae95c8ca | ||
|
|
719e2713ed | ||
|
|
349de9b955 | ||
|
|
e6c376fba0 | ||
|
|
c179230ce0 | ||
|
|
3b28f40c6a | ||
|
|
5cccd5e7aa | ||
|
|
af38f75b29 | ||
|
|
a8f94dd595 | ||
|
|
1f3a32ebaf | ||
|
|
9ff7bef2c2 | ||
|
|
2e1442a5c1 | ||
|
|
4e5bc8b399 | ||
|
|
4e69033d33 | ||
|
|
778d2d906a | ||
|
|
d77f778e0d | ||
|
|
129c765a74 | ||
|
|
5891f94c88 | ||
|
|
60510ff2f0 | ||
|
|
c1a32d9f1a | ||
|
|
fdea406101 | ||
|
|
bba4754994 | ||
|
|
9fdeb475e9 | ||
|
|
a870076051 | ||
|
|
7e01e82470 | ||
|
|
7e8391eb55 | ||
|
|
332e1ccfaa | ||
|
|
e7410e40df | ||
|
|
1cbad32b6e | ||
|
|
f45d6ab49c | ||
|
|
9c5b81cb2b | ||
|
|
472a97a616 | ||
|
|
c8fef3380c | ||
|
|
db008c1af8 | ||
|
|
2604c9e761 | ||
|
|
95c09981a6 | ||
|
|
db1c1e2ee4 | ||
|
|
2e9319846e | ||
|
|
7b70776810 | ||
|
|
fdd6eb5f6d | ||
|
|
bcbeb9d8ac | ||
|
|
ad0b133ac8 | ||
|
|
4c2fda7200 | ||
|
|
d1f94c2846 | ||
|
|
1fac51fe35 | ||
|
|
6547005073 | ||
|
|
5fe933fa44 | ||
|
|
67b7c99d03 | ||
|
|
cf65f44eb6 | ||
|
|
7d2de47bcf | ||
|
|
dcb76984bc | ||
|
|
023cb22da7 | ||
|
|
2d0615aede | ||
|
|
643cc6c5be | ||
|
|
12113be6ec |
19
.dockerignore
Normal file
@ -0,0 +1,19 @@
|
||||
.idea
|
||||
# Langchain-Chatchat
|
||||
docs
|
||||
.github
|
||||
tests
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
.gitignore
|
||||
.gitmodules
|
||||
README.md
|
||||
README_en.md
|
||||
README_ja.md
|
||||
LICENSE
|
||||
requirements_api.txt
|
||||
requirements_lite.txt
|
||||
requirements_webui.txt
|
||||
# bge-large-zh-v1.5
|
||||
bge-large-zh-v1.5/README.md
|
||||
# chatglm3-6b
|
||||
155
.github/workflows/docker-build.yaml
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
name: docker-build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'README_en.md'
|
||||
- 'README_ja.md'
|
||||
env:
|
||||
TZ: Asia/Shanghai
|
||||
jobs:
|
||||
docker-build:
|
||||
runs-on: ubuntu-latest
|
||||
# if: github.event.pull_request.merged == true
|
||||
steps:
|
||||
- name: Optimize Disk Space
|
||||
uses: hugoalh/disk-space-optimizer-ghaction@v0.8.0
|
||||
with:
|
||||
operate_sudo: "True"
|
||||
general_include: ".+"
|
||||
general_exclude: |-
|
||||
^GCC$
|
||||
^G\+\+$
|
||||
Clang
|
||||
LLVM
|
||||
docker_include: ".+"
|
||||
docker_prune: "True"
|
||||
docker_clean: "True"
|
||||
apt_prune: "True"
|
||||
apt_clean: "True"
|
||||
homebrew_prune: "True"
|
||||
homebrew_clean: "True"
|
||||
npm_prune: "True"
|
||||
npm_clean: "True"
|
||||
os_swap: "True"
|
||||
- name: Remove Unnecessary Tools And Files
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
run: |
|
||||
sudo apt-get remove -y '^dotnet-.*' '^llvm-.*' 'php.*' azure-cli google-chrome-stable firefox powershell mono-devel
|
||||
sudo apt-get autoremove --purge -y
|
||||
sudo find /var/log -name "*.gz" -type f -delete
|
||||
sudo rm -rf /var/cache/apt/archives
|
||||
sudo rm -rf /tmp/*
|
||||
sudo rm -rf /etc/apt/sources.list.d/* /usr/share/dotnet /usr/local/lib/android /opt/ghc /etc/mysql /etc/php
|
||||
sudo -E apt-get -y purge azure-cli* docker* ghc* zulu* hhvm* llvm* firefox* google* dotnet* aspnetcore* powershell* openjdk* adoptopenjdk* mysql* php* mongodb* moby* snap* || true
|
||||
sudo rm -rf /etc/apt/sources.list.d/* /usr/local/lib/android /opt/ghc /usr/share/dotnet /usr/local/graalvm /usr/local/.ghcup \
|
||||
/usr/local/share/powershell /usr/local/share/chromium /usr/local/lib/node_modules
|
||||
sudo rm -rf /etc/apt/sources.list.d/* /usr/share/dotnet /usr/local/lib/android /opt/ghc /etc/mysql /etc/php
|
||||
sudo -E apt-get -y purge azure-cli* docker* ghc* zulu* hhvm* llvm* firefox* google* dotnet* aspnetcore* powershell* openjdk* adoptopenjdk* mysql* php* mongodb* moby* snap* || true
|
||||
sudo -E apt-get -qq update
|
||||
sudo -E apt-get -qq install libfuse-dev $(curl -fsSL git.io/depends-ubuntu-2204)
|
||||
sudo -E apt-get -qq autoremove --purge
|
||||
sudo -E apt-get -qq clean
|
||||
sudo apt-get clean
|
||||
rm -rf /opt/hostedtoolcache
|
||||
sudo timedatectl set-timezone "$TZ"
|
||||
- name: Free Up Disk Space
|
||||
uses: easimon/maximize-build-space@master
|
||||
with:
|
||||
root-reserve-mb: 62464 # 给 / 预留 61GiB 空间( docker 预留)
|
||||
swap-size-mb: 1
|
||||
remove-dotnet: 'true'
|
||||
remove-android: 'true'
|
||||
remove-haskell: 'true'
|
||||
remove-codeql: 'true'
|
||||
remove-docker-images: 'true'
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Get Latest Release
|
||||
id: get_version
|
||||
run: |
|
||||
VERSION=$(curl --silent "https://api.github.com/repos/${{ github.repository }}/releases/latest" | jq -r .tag_name)
|
||||
echo "RELEASE_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||
- name: Set Image Tag
|
||||
id: imageTag
|
||||
run: echo "::set-output name=image_tag::$RELEASE_VERSION-$(date +%Y%m%d)-$(git rev-parse --short HEAD)"
|
||||
- name: Set Up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set Up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Clone Model
|
||||
run: |
|
||||
sudo mkdir -p $GITHUB_WORKSPACE/bge-large-zh-v1.5
|
||||
cd $GITHUB_WORKSPACE/bge-large-zh-v1.5
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/.gitattributes &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/config.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/config_sentence_transformers.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/modules.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/pytorch_model.bin &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/sentence_bert_config.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/special_tokens_map.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/tokenizer.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/tokenizer_config.json &> /dev/null
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/vocab.txt &> /dev/null
|
||||
sudo mkdir -p $GITHUB_WORKSPACE/bge-large-zh-v1.5/1_Pooling
|
||||
cd $GITHUB_WORKSPACE/bge-large-zh-v1.5/1_Pooling
|
||||
sudo wget https://huggingface.co/BAAI/bge-large-zh-v1.5/resolve/main/1_Pooling/config.json &> /dev/null
|
||||
sudo mkdir -p $GITHUB_WORKSPACE/chatglm3-6b
|
||||
cd $GITHUB_WORKSPACE/chatglm3-6b
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/config.json &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/configuration_chatglm.py &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00001-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00002-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00003-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00004-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00005-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00006-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model-00007-of-00007.safetensors &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/model.safetensors.index.json &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/modeling_chatglm.py &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/pytorch_model.bin.index.json &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/quantization.py &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/special_tokens_map.json &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/tokenization_chatglm.py &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/tokenizer.model &> /dev/null
|
||||
sudo wget https://huggingface.co/THUDM/chatglm3-6b/resolve/main/tokenizer_config.json &> /dev/null
|
||||
du -sh $GITHUB_WORKSPACE
|
||||
du -sh $GITHUB_WORKSPACE/*
|
||||
du -sh $GITHUB_WORKSPACE/bge-large-zh-v1.5/*
|
||||
du -sh $GITHUB_WORKSPACE/chatglm3-6b/*
|
||||
- name: Show Runner Disk
|
||||
run: df -hT
|
||||
- name: Docker Build
|
||||
run: |
|
||||
docker build -t uswccr.ccs.tencentyun.com/chatchat/chatchat:${{ steps.imageTag.outputs.image_tag }} -f Dockerfile .
|
||||
- name: Show Images Size
|
||||
run: docker images
|
||||
- name: Login To Tencent CCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: uswccr.ccs.tencentyun.com
|
||||
username: ${{ secrets.CCR_REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.CCR_REGISTRY_PASSWORD }}
|
||||
- name: Docker Push
|
||||
run: docker push uswccr.ccs.tencentyun.com/chatchat/chatchat:${{ steps.imageTag.outputs.image_tag }}
|
||||
# - name: Login to Docker Hub
|
||||
# uses: docker/login-action@v2
|
||||
# with:
|
||||
# username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
# password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Update README.md
|
||||
run: |
|
||||
sed -i "s|uswccr.ccs.tencentyun.com/chatchat/chatchat:[^ ]*|uswccr.ccs.tencentyun.com/chatchat/chatchat:${{ steps.imageTag.outputs.image_tag }}|g" README.md
|
||||
sed -i "s|uswccr.ccs.tencentyun.com/chatchat/chatchat:[^ ]*|uswccr.ccs.tencentyun.com/chatchat/chatchat:${{ steps.imageTag.outputs.image_tag }}|g" README_en.md
|
||||
sed -i "s|uswccr.ccs.tencentyun.com/chatchat/chatchat:[^ ]*|uswccr.ccs.tencentyun.com/chatchat/chatchat:${{ steps.imageTag.outputs.image_tag }}|g" README_ja.md
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git commit -am "feat:update docker image:tag"
|
||||
- name: Push README.md
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GH_PAT }}
|
||||
branch: ${{ github.ref }}
|
||||
4
.gitignore
vendored
@ -173,4 +173,8 @@ cython_debug/
|
||||
.pytest_cache
|
||||
.DS_Store
|
||||
|
||||
# Test File
|
||||
test.py
|
||||
configs/*.py
|
||||
|
||||
|
||||
|
||||
27
Dockerfile
Normal file
@ -0,0 +1,27 @@
|
||||
# Base Image
|
||||
FROM nvidia/cuda:12.1.1-cudnn8-runtime-ubuntu22.04
|
||||
# Labels
|
||||
LABEL maintainer=chatchat
|
||||
# Environment Variables
|
||||
ENV HOME=/Langchain-Chatchat
|
||||
# Commands
|
||||
WORKDIR /
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
echo "Asia/Shanghai" > /etc/timezone && \
|
||||
apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends python3.11 python3-pip curl libgl1 libglib2.0-0 jq && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm -f /usr/bin/python3 && \
|
||||
ln -s /usr/bin/python3.11 /usr/bin/python3 && \
|
||||
mkdir -p $HOME
|
||||
# Copy the application files
|
||||
COPY . $HOME
|
||||
WORKDIR $HOME
|
||||
# Install dependencies from requirements.txt
|
||||
RUN pip3 install -r requirements.txt -i https://pypi.org/simple && \
|
||||
python3 copy_config_example.py && \
|
||||
sed -i 's|MODEL_ROOT_PATH = ""|MODEL_ROOT_PATH = "/Langchain-Chatchat"|' configs/model_config.py && \
|
||||
python3 init_database.py --recreate-vs
|
||||
EXPOSE 22 7861 8501
|
||||
ENTRYPOINT ["python3", "startup.py", "-a"]
|
||||
105
README.md
@ -1,12 +1,17 @@
|
||||

|
||||
|
||||
|
||||
🌍 [READ THIS IN ENGLISH](README_en.md)
|
||||
🌍 [日本語で読む](README_ja.md)
|
||||
|
||||
📃 **LangChain-Chatchat** (原 Langchain-ChatGLM)
|
||||
|
||||
基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现,开源、可离线部署的检索增强生成(RAG)大模型知识库项目。
|
||||
|
||||
### ⚠️ 重要提示
|
||||
|
||||
`0.2.10`将会是`0.2.x`系列的最后一个版本,`0.2.x`系列版本将会停止更新和技术支持,全力研发具有更强应用性的 `Langchain-Chatchat 0.3.x`。
|
||||
`0.2.10` 的后续 bug 修复将会直接推送到`master`分支,而不再进行版本更新。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
@ -14,23 +19,31 @@
|
||||
* [介绍](README.md#介绍)
|
||||
* [解决的痛点](README.md#解决的痛点)
|
||||
* [快速上手](README.md#快速上手)
|
||||
* [1. 环境配置](README.md#1-环境配置)
|
||||
* [2. 模型下载](README.md#2-模型下载)
|
||||
* [3. 初始化知识库和配置文件](README.md#3-初始化知识库和配置文件)
|
||||
* [4. 一键启动](README.md#4-一键启动)
|
||||
* [5. 启动界面示例](README.md#5-启动界面示例)
|
||||
* [1. 环境配置](README.md#1-环境配置)
|
||||
* [2. 模型下载](README.md#2-模型下载)
|
||||
* [3. 初始化知识库和配置文件](README.md#3-初始化知识库和配置文件)
|
||||
* [4. 一键启动](README.md#4-一键启动)
|
||||
* [5. 启动界面示例](README.md#5-启动界面示例)
|
||||
* [联系我们](README.md#联系我们)
|
||||
|
||||
|
||||
## 介绍
|
||||
|
||||
🤖️ 一种利用 [langchain](https://github.com/hwchase17/langchain) 思想实现的基于本地知识库的问答应用,目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。
|
||||
🤖️ 一种利用 [langchain](https://github.com/langchain-ai/langchain)
|
||||
思想实现的基于本地知识库的问答应用,目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。
|
||||
|
||||
💡 受 [GanymedeNil](https://github.com/GanymedeNil) 的项目 [document.ai](https://github.com/GanymedeNil/document.ai) 和 [AlexZhangji](https://github.com/AlexZhangji) 创建的 [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216) 启发,建立了全流程可使用开源模型实现的本地知识库问答应用。本项目的最新版本中通过使用 [FastChat](https://github.com/lm-sys/FastChat) 接入 Vicuna, Alpaca, LLaMA, Koala, RWKV 等模型,依托于 [langchain](https://github.com/langchain-ai/langchain) 框架支持通过基于 [FastAPI](https://github.com/tiangolo/fastapi) 提供的 API 调用服务,或使用基于 [Streamlit](https://github.com/streamlit/streamlit) 的 WebUI 进行操作。
|
||||
💡 受 [GanymedeNil](https://github.com/GanymedeNil) 的项目 [document.ai](https://github.com/GanymedeNil/document.ai)
|
||||
和 [AlexZhangji](https://github.com/AlexZhangji)
|
||||
创建的 [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216)
|
||||
启发,建立了全流程可使用开源模型实现的本地知识库问答应用。本项目的最新版本中通过使用 [FastChat](https://github.com/lm-sys/FastChat)
|
||||
接入 Vicuna, Alpaca, LLaMA, Koala, RWKV 等模型,依托于 [langchain](https://github.com/langchain-ai/langchain)
|
||||
框架支持通过基于 [FastAPI](https://github.com/tiangolo/fastapi) 提供的 API
|
||||
调用服务,或使用基于 [Streamlit](https://github.com/streamlit/streamlit) 的 WebUI 进行操作。
|
||||
|
||||
✅ 依托于本项目支持的开源 LLM 与 Embedding 模型,本项目可实现全部使用**开源**模型**离线私有部署**。与此同时,本项目也支持 OpenAI GPT API 的调用,并将在后续持续扩充对各类模型及模型 API 的接入。
|
||||
✅ 依托于本项目支持的开源 LLM 与 Embedding 模型,本项目可实现全部使用**开源**模型**离线私有部署**。与此同时,本项目也支持
|
||||
OpenAI GPT API 的调用,并将在后续持续扩充对各类模型及模型 API 的接入。
|
||||
|
||||
⛓️ 本项目实现原理如下图所示,过程包括加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 -> 在文本向量中匹配出与问句向量最相似的 `top k`个 -> 匹配出的文本作为上下文和问题一起添加到 `prompt`中 -> 提交给 `LLM`生成回答。
|
||||
⛓️ 本项目实现原理如下图所示,过程包括加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 ->
|
||||
在文本向量中匹配出与问句向量最相似的 `top k`个 -> 匹配出的文本作为上下文和问题一起添加到 `prompt`中 -> 提交给 `LLM`生成回答。
|
||||
|
||||
📺 [原理介绍视频](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
|
||||
|
||||
@ -42,37 +55,46 @@
|
||||
|
||||
🚩 本项目未涉及微调、训练过程,但可利用微调或训练对本项目效果进行优化。
|
||||
|
||||
🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) 中 `v11` 版本所使用代码已更新至本项目 `v0.2.7` 版本。
|
||||
🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) 中 `0.2.10`
|
||||
|
||||
🐳 [Docker 镜像](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.6) 已经更新到 ```0.2.7``` 版本。
|
||||
版本所使用代码已更新至本项目 `v0.2.10` 版本。
|
||||
|
||||
🌲 一行命令运行 Docker :
|
||||
🐳 [Docker 镜像](isafetech/chatchat:0.2.10) 已经更新到 ```0.2.10``` 版本。
|
||||
|
||||
🌲 本次更新后同时支持DockerHub、阿里云、腾讯云镜像源:
|
||||
|
||||
```shell
|
||||
docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7
|
||||
docker run -d --gpus all -p 80:8501 isafetech/chatchat:0.2.10
|
||||
docker run -d --gpus all -p 80:8501 uswccr.ccs.tencentyun.com/chatchat/chatchat:0.2.10
|
||||
docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.10
|
||||
```
|
||||
|
||||
🧩 本项目有一个非常完整的[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) , README只是一个简单的介绍,__仅仅是入门教程,能够基础运行__。 如果你想要更深入的了解本项目,或者想对本项目做出贡献。请移步 [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) 界面
|
||||
🧩 本项目有一个非常完整的[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) , README只是一个简单的介绍,_
|
||||
_仅仅是入门教程,能够基础运行__。
|
||||
如果你想要更深入的了解本项目,或者想对本项目做出贡献。请移步 [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
|
||||
界面
|
||||
|
||||
## 解决的痛点
|
||||
|
||||
该项目是一个可以实现 __完全本地化__推理的知识库增强方案, 重点解决数据安全保护,私域化部署的企业痛点。
|
||||
本开源方案采用```Apache License```,可以免费商用,无需付费。
|
||||
|
||||
我们支持市面上主流的本地大预言模型和Embedding模型,支持开源的本地向量数据库。
|
||||
我们支持市面上主流的本地大语言模型和Embedding模型,支持开源的本地向量数据库。
|
||||
支持列表详见[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
|
||||
|
||||
|
||||
## 快速上手
|
||||
|
||||
### 1. 环境配置
|
||||
|
||||
+ 首先,确保你的机器安装了 Python 3.8 - 3.10
|
||||
+ 首先,确保你的机器安装了 Python 3.8 - 3.11 (我们强烈推荐使用 Python3.11)。
|
||||
|
||||
```
|
||||
$ python --version
|
||||
Python 3.10.12
|
||||
Python 3.11.7
|
||||
```
|
||||
|
||||
接着,创建一个虚拟环境,并在虚拟环境内安装项目的依赖
|
||||
|
||||
```shell
|
||||
|
||||
# 拉取仓库
|
||||
@ -88,32 +110,44 @@ $ pip install -r requirements_webui.txt
|
||||
|
||||
# 默认依赖包括基本运行环境(FAISS向量库)。如果要使用 milvus/pg_vector 等向量库,请将 requirements.txt 中相应依赖取消注释再安装。
|
||||
```
|
||||
### 2, 模型下载
|
||||
|
||||
如需在本地或离线环境下运行本项目,需要首先将项目所需的模型下载至本地,通常开源 LLM 与 Embedding 模型可以从 [HuggingFace](https://huggingface.co/models) 下载。
|
||||
请注意,LangChain-Chatchat `0.2.x` 系列是针对 Langchain `0.0.x` 系列版本的,如果你使用的是 Langchain `0.1.x`
|
||||
系列版本,需要降级您的`Langchain`版本。
|
||||
|
||||
以本项目中默认使用的 LLM 模型 [THUDM/ChatGLM2-6B](https://huggingface.co/THUDM/chatglm2-6b) 与 Embedding 模型 [moka-ai/m3e-base](https://huggingface.co/moka-ai/m3e-base) 为例:
|
||||
### 2. 模型下载
|
||||
|
||||
下载模型需要先[安装 Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage),然后运行
|
||||
如需在本地或离线环境下运行本项目,需要首先将项目所需的模型下载至本地,通常开源 LLM 与 Embedding
|
||||
模型可以从 [HuggingFace](https://huggingface.co/models) 下载。
|
||||
|
||||
以本项目中默认使用的 LLM 模型 [THUDM/ChatGLM3-6B](https://huggingface.co/THUDM/chatglm3-6b) 与 Embedding
|
||||
模型 [BAAI/bge-large-zh](https://huggingface.co/BAAI/bge-large-zh) 为例:
|
||||
|
||||
下载模型需要先[安装 Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)
|
||||
,然后运行
|
||||
|
||||
```Shell
|
||||
$ git lfs install
|
||||
$ git clone https://huggingface.co/THUDM/chatglm2-6b
|
||||
$ git clone https://huggingface.co/moka-ai/m3e-base
|
||||
$ git clone https://huggingface.co/THUDM/chatglm3-6b
|
||||
$ git clone https://huggingface.co/BAAI/bge-large-zh
|
||||
```
|
||||
|
||||
### 3. 初始化知识库和配置文件
|
||||
|
||||
按照下列方式初始化自己的知识库和简单的复制配置文件
|
||||
|
||||
```shell
|
||||
$ python copy_config_example.py
|
||||
$ python init_database.py --recreate-vs
|
||||
```
|
||||
|
||||
### 4. 一键启动
|
||||
|
||||
按照以下命令启动项目
|
||||
|
||||
```shell
|
||||
$ python startup.py -a
|
||||
```
|
||||
|
||||
### 5. 启动界面示例
|
||||
|
||||
如果正常启动,你将能看到以下界面
|
||||
@ -132,23 +166,36 @@ $ python startup.py -a
|
||||
|
||||

|
||||
|
||||
|
||||
### 注意
|
||||
|
||||
以上方式只是为了快速上手,如果需要更多的功能和自定义启动方式 ,请参考[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
|
||||
以上方式只是为了快速上手,如果需要更多的功能和自定义启动方式
|
||||
,请参考[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 项目里程碑
|
||||
|
||||
+ `2023年4月`: `Langchain-ChatGLM 0.1.0` 发布,支持基于 ChatGLM-6B 模型的本地知识库问答。
|
||||
+ `2023年8月`: `Langchain-ChatGLM` 改名为 `Langchain-Chatchat`,`0.2.0` 发布,使用 `fastchat` 作为模型加载方案,支持更多的模型和数据库。
|
||||
+ `2023年10月`: `Langchain-Chatchat 0.2.5` 发布,推出 Agent 内容,开源项目在`Founder Park & Zhipu AI & Zilliz`
|
||||
举办的黑客马拉松获得三等奖。
|
||||
+ `2023年12月`: `Langchain-Chatchat` 开源项目获得超过 **20K** stars.
|
||||
+ `2024年1月`: `LangChain 0.1.x` 推出,`Langchain-Chatchat 0.2.x` 发布稳定版本`0.2.10`
|
||||
后将停止更新和技术支持,全力研发具有更强应用性的 `Langchain-Chatchat 0.3.x`。
|
||||
|
||||
+ 🔥 让我们一起期待未来 Chatchat 的故事 ···
|
||||
|
||||
---
|
||||
|
||||
## 联系我们
|
||||
|
||||
### Telegram
|
||||
|
||||
[](https://t.me/+RjliQ3jnJ1YyN2E9)
|
||||
|
||||
### 项目交流群
|
||||
<img src="img/qr_code_76.jpg" alt="二维码" width="300" />
|
||||
<img src="img/qr_code_108.jpg" alt="二维码" width="300" />
|
||||
|
||||
🎉 Langchain-Chatchat 项目微信交流群,如果你也对本项目感兴趣,欢迎加入群聊参与讨论交流。
|
||||
|
||||
|
||||
47
README_en.md
@ -1,12 +1,18 @@
|
||||

|
||||
|
||||
🌍 [中文文档](README.md)
|
||||
🌍 [日本語で読む](README_ja.md)
|
||||
|
||||
📃 **LangChain-Chatchat** (formerly Langchain-ChatGLM):
|
||||
|
||||
A LLM application aims to implement knowledge and search engine based QA based on Langchain and open-source or remote
|
||||
LLM API.
|
||||
|
||||
⚠️`0.2.10` will be the last version of the `0.2.x` series. The `0.2.x` series will stop updating and technical support,
|
||||
and strive to develop `Langchain-Chachat 0.3.x` with stronger applicability.
|
||||
Subsequent bug fixes for `0.2.10` will be pushed directly to the `master` branch without version updates.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
@ -24,7 +30,8 @@ LLM API.
|
||||
## Introduction
|
||||
|
||||
🤖️ A Q&A application based on local knowledge base implemented using the idea
|
||||
of [langchain](https://github.com/hwchase17/langchain). The goal is to build a KBQA(Knowledge based Q&A) solution that
|
||||
of [langchain](https://github.com/langchain-ai/langchain). The goal is to build a KBQA(Knowledge based Q&A) solution
|
||||
that
|
||||
is friendly to Chinese scenarios and open source models and can run both offline and online.
|
||||
|
||||
💡 Inspired by [document.ai](https://github.com/GanymedeNil/document.ai)
|
||||
@ -55,10 +62,17 @@ The main process analysis from the aspect of document process:
|
||||
🚩 The training or fine-tuning are not involved in the project, but still, one always can improve performance by do
|
||||
these.
|
||||
|
||||
🌐 [AutoDL image](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.5) is supported, and in v9 the codes are update
|
||||
to v0.2.5.
|
||||
🌐 [AutoDL image](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) is supported, and in `0.2.10` the codes are update to v0.2.10.
|
||||
|
||||
🐳 [Docker image](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.5)
|
||||
🐳 [Docker image](isafetech/chatchat:0.2.10) is supported to ```0.2.10```.
|
||||
|
||||
🌲 The latest update also provides support for image sources from DockerHub, Ali Cloud, and Tencent Cloud:
|
||||
|
||||
```shell
|
||||
docker run -d --gpus all -p 80:8501 isafetech/chatchat:0.2.10
|
||||
docker run -d --gpus all -p 80:8501 uswccr.ccs.tencentyun.com/chatchat/chatchat:0.2.10
|
||||
docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.10
|
||||
```
|
||||
|
||||
## Pain Points Addressed
|
||||
|
||||
@ -99,6 +113,9 @@ $ pip install -r requirements_webui.txt
|
||||
# 默认依赖包括基本运行环境(FAISS向量库)。如果要使用 milvus/pg_vector 等向量库,请将 requirements.txt 中相应依赖取消注释再安装。
|
||||
```
|
||||
|
||||
Please note that the LangChain-Chachat `0.2.x` series is for the Langchain `0.0.x` series version. If you are using the
|
||||
Langchain `0.1.x` series version, you need to downgrade.
|
||||
|
||||
### Model Download
|
||||
|
||||
If you need to run this project locally or in an offline environment, you must first download the required models for
|
||||
@ -157,15 +174,33 @@ please refer to the [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/
|
||||
|
||||
---
|
||||
|
||||
## Project Milestones
|
||||
|
||||
+ `April 2023`: `Langchain-ChatGLM 0.1.0` released, supporting local knowledge base question and answer based on the
|
||||
ChatGLM-6B model.
|
||||
+ `August 2023`: `Langchain-ChatGLM` was renamed to `Langchain-Chatchat`, `0.2.0` was released, using `fastchat` as the
|
||||
model loading solution, supporting more models and databases.
|
||||
+ `October 2023`: `Langchain-Chachat 0.2.5` was released, Agent content was launched, and the open source project won
|
||||
the third prize in the hackathon held by `Founder Park & Zhipu AI & Zilliz`.
|
||||
+ `December 2023`: `Langchain-Chachat` open source project received more than **20K** stars.
|
||||
+ `January 2024`: `LangChain 0.1.x` is launched, `Langchain-Chachat 0.2.x` is released. After the stable
|
||||
version `0.2.10` is released, updates and technical support will be stopped, and all efforts will be made to
|
||||
develop `Langchain with stronger applicability -Chat 0.3.x`.
|
||||
|
||||
|
||||
+ 🔥 Let’s look forward to the future Chatchat stories together···
|
||||
|
||||
---
|
||||
|
||||
## Contact Us
|
||||
|
||||
### Telegram
|
||||
|
||||
[](https://t.me/+RjliQ3jnJ1YyN2E9)
|
||||
|
||||
### WeChat Group、
|
||||
### WeChat Group
|
||||
|
||||
<img src="img/qr_code_67.jpg" alt="二维码" width="300" height="300" />
|
||||
<img src="img/qr_code_90.jpg" alt="二维码" width="300" height="300" />
|
||||
|
||||
### WeChat Official Account
|
||||
|
||||
|
||||
200
README_ja.md
Normal file
@ -0,0 +1,200 @@
|
||||

|
||||
|
||||
🌍 [中文文档](README.md)
|
||||
🌍 [READ THIS IN ENGLISH](README_en.md)
|
||||
|
||||
📃 **LangChain-Chatchat** (旧名 Langchain-ChatGLM)
|
||||
|
||||
ChatGLM などの大規模な言語モデルや Langchain などのアプリケーション フレームワークに基づいた、オープン
|
||||
ソースのオフライン展開可能な検索拡張生成 (RAG) 大規模モデル ナレッジ ベース プロジェクトです。
|
||||
|
||||
⚠️`0.2.10` は `0.2.x` シリーズの最終バージョンとなり、`0.2.x`
|
||||
シリーズはアップデートと技術サポートを終了し、より適用性の高い `Langchain-Chachat 0.3.x` の開発に努めます。 。
|
||||
`0.2.10` のその後のバグ修正は、バージョン更新なしで `master` ブランチに直接プッシュされます。
|
||||
|
||||
---
|
||||
|
||||
## 目次
|
||||
|
||||
- [イントロ](README_ja.md#イントロ)
|
||||
- [ペインポイントへの対応](README_ja.md#ペインポイントへの対応)
|
||||
- [クイックスタート](README_ja.md#クイックスタート)
|
||||
- [1. 環境セットアップ](README_ja.md#環境セットアップ)
|
||||
- [2. モデルをダウンロード](README_ja.md#モデルをダウンロード)
|
||||
- [3. ナレッジベースと設定ファイルの初期化](README_ja.md#ナレッジベースと設定ファイルの初期化)
|
||||
- [4. ワンクリック起動](README_ja.md#ワンクリック起動)
|
||||
- [5. 起動インターフェースの例](README_ja.md#起動インターフェースの例)
|
||||
- [お問い合わせ](README_ja.md#お問い合わせ)
|
||||
|
||||
## イントロ
|
||||
|
||||
🤖️ [langchain](https://github.com/hwchase17/langchain) のアイデアを用いて実装された、ローカルナレッジベースに基づく Q&A
|
||||
アプリケーション。
|
||||
目標は、中国のシナリオとオープンソースモデルに親和性があり、オフラインとオンラインの両方で実行可能な KBQA(ナレッジベースの
|
||||
Q&A)ソリューションを構築することです。
|
||||
|
||||
💡 [document.ai](https://github.com/GanymedeNil/document.ai)
|
||||
と [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216) に触発され、
|
||||
プロセス全体を通してオープンソースモデルまたはリモート LLM api を使用して実装することができるローカルナレッジベースの質問応答アプリケーションを構築します。
|
||||
このプロジェクトの最新バージョンでは、[FastChat](https://github.com/lm-sys/FastChat)
|
||||
を使用して、Vicuna、Alpaca、LLaMA、Koala、RWKV、その他多くのモデルにアクセスしています。
|
||||
このプロジェクトは [langchain](https://github.com/langchain-ai/langchain)
|
||||
に依存し、[FastAPI](https://github.com/tiangolo/fastapi) に基づいて提供されるAPIを通してサービスを呼び出したり、
|
||||
[Streamlit](https://github.com/streamlit/streamlit) に基づいて WebUI を使ったりすることをサポートしています。
|
||||
|
||||
✅ オープンソースの LLM と Embedding モデルに依存して、このプロジェクトはフルプロセスの **オフラインプライベートデプロイメント
|
||||
** を実現することができます。
|
||||
同時に、本プロジェクトは OpenAI GPT API や Zhipu API の呼び出しにも対応しており、今後も様々な機種やリモート API
|
||||
へのアクセスを拡大していきます。
|
||||
|
||||
⛓️ このプロジェクトの実施原則を下のグラフに示します。主なプロセスは以下の通りです:
|
||||
ファイルの読み込み -> テキストの読み込み -> テキストのセグメンテーション -> テキストのベクトル化 -> 質問のベクトル化 ->
|
||||
質問ベクトルと最も似ている `top-k` をテキストベクトルでマッチング ->
|
||||
マッチしたテキストをコンテキストと質問として `prompt` に追加 -> 回答を生成するために `LLM` に送信。
|
||||
|
||||
📺[video introduction](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
|
||||
|
||||

|
||||
|
||||
文書プロセスの側面からの主なプロセス分析:
|
||||
|
||||

|
||||
|
||||
🚩 トレーニングやファインチューニングはプロジェクトには含まれないが、これらを行うことで必ずパフォーマンスを向上させることができます。
|
||||
|
||||
🌐 [AutoDL イメージ](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.5)がサポートされ、`0.2.10` では v0.2.10
|
||||
にアップデートされました。
|
||||
|
||||
🐳 [Docker イメージ](isafetech/chatchat:0.2.10)
|
||||
|
||||
🌲 今回のアップデートにより、DockerHub、阿里雲、騰訊のクラウドにも対応しました。より広範なクラウド環境で利用可能となりました。
|
||||
|
||||
```shell
|
||||
docker run -d --gpus all -p 80:8501 isafetech/chatchat:0.2.10
|
||||
docker run -d --gpus all -p 80:8501 uswccr.ccs.tencentyun.com/chatchat/chatchat:0.2.10
|
||||
docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.10
|
||||
```
|
||||
|
||||
## ペインポイントへの対応
|
||||
|
||||
このプロジェクトは、完全にローカライズされた推論によってナレッジベースを強化するソリューションであり、特にデータセキュリティと企業向けのプライベートな展開の問題に取り組んでいます。
|
||||
このオープンソースソリューションは Apache ライセンスに基づき、無償で商用利用できます。
|
||||
私たちは、市場で入手可能な主流のローカル大予言モデルや Embedding モデル、オープンソースのローカルベクターデータベースをサポートしています。
|
||||
対応機種とデータベースの詳細については、[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) をご参照ください。
|
||||
|
||||
## クイックスタート
|
||||
|
||||
### 環境セットアップ
|
||||
|
||||
まず、マシンにPython 3.10がインストールされていることを確認してください。
|
||||
|
||||
```
|
||||
$ python --version
|
||||
Python 3.11.7
|
||||
```
|
||||
|
||||
次に、仮想環境を作成し、プロジェクトの依存関係を仮想環境内にインストールする。
|
||||
|
||||
```shell
|
||||
|
||||
# リポジトリをクローン
|
||||
$ git clone https://github.com/chatchat-space/Langchain-Chatchat.git
|
||||
|
||||
# ディレクトリに移動
|
||||
$ cd Langchain-Chatchat
|
||||
|
||||
# すべての依存関係をインストール
|
||||
$ pip install -r requirements.txt
|
||||
$ pip install -r requirements_api.txt
|
||||
$ pip install -r requirements_webui.txt
|
||||
|
||||
# デフォルトの依存関係には、基本的な実行環境(FAISS ベクターライブラリ)が含まれます。milvus/pg_vector などのベクターライブラリを使用する場合は、requirements.txt 内の対応する依存関係のコメントを解除してからインストールしてください。
|
||||
```
|
||||
|
||||
LangChain-Chachat `0.2.x` シリーズは Langchain `0.0.x` シリーズ用です。Langchain `0.1.x` シリーズをお使いの場合は、ダウングレードする必要があります。
|
||||
|
||||
### モデルをダウンロード
|
||||
|
||||
このプロジェクトをローカルまたはオフライン環境で実行する必要がある場合は、まずプロジェクトに必要なモデルをダウンロードする必要があります。
|
||||
通常、オープンソースの LLM と Embedding モデルは Hugging Face からダウンロードできる。
|
||||
|
||||
このプロジェクトで使用されているデフォルトの LLM
|
||||
モデルである [THUDM/chatglm2-6b](https://huggingface.co/THUDM/chatglm2-6b)と、Embedding
|
||||
モデル [moka-ai/m3e-base](https://huggingface.co/moka-ai/m3e-base) を例にとると、次のようになります:
|
||||
|
||||
モデルをダウンロードするには、まず [Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)
|
||||
をインストールし、次のように実行する必要があります:
|
||||
|
||||
```Shell
|
||||
$ git lfs install
|
||||
$ git clone https://huggingface.co/THUDM/chatglm2-6b
|
||||
$ git clone https://huggingface.co/moka-ai/m3e-base
|
||||
```
|
||||
|
||||
### ナレッジベースと設定ファイルの初期化
|
||||
|
||||
以下の手順に従って、ナレッジベースと設定ファイルを初期化してください:
|
||||
|
||||
```shell
|
||||
$ python copy_config_example.py
|
||||
$ python init_database.py --recreate-vs
|
||||
```
|
||||
|
||||
### ワンクリック起動
|
||||
|
||||
プロジェクトを開始するには、次のコマンドを実行します:
|
||||
|
||||
```shell
|
||||
$ python startup.py -a
|
||||
```
|
||||
|
||||
### 起動インターフェースの例
|
||||
|
||||
1. FastAPI docs インターフェース
|
||||
|
||||

|
||||
|
||||
2. webui ページ
|
||||
|
||||
- Web UI ダイアログページ:
|
||||
|
||||

|
||||
|
||||
- Web UI ナレッジベースマネジメントページ:
|
||||
|
||||

|
||||
|
||||
### 注
|
||||
|
||||
上記の手順はクイックスタートのために提供されています。より多くの機能が必要な場合や、起動方法をカスタマイズしたい場合は、[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
|
||||
を参照してください。
|
||||
|
||||
---
|
||||
|
||||
## プロジェクトのマイルストーン
|
||||
|
||||
+ `2023 年 4 月`: `Langchain-ChatGLM 0.1.0` がリリースされ、ChatGLM-6B モデルに基づくローカル ナレッジ ベースの質問と回答がサポートされました。
|
||||
+ `2023 年 8 月`: `Langchain-ChatGLM` は `Langchain-Chatchat` に名前変更され、モデル読み込みソリューションとして `fastchat` を使用し、より多くのモデルとデータベースをサポートする `0.2.0` がリリースされました。
|
||||
+ `2023 年 10 月`: `Langchain-Chachat 0.2.5` リリース、エージェント コンテンツ、オープンソース プロジェクトを`Founder Park & Zhipu AI & Zilliz`で開始
|
||||
開催したハッカソンでは3位に入賞しました。
|
||||
+ `2023 年 12 月`: `Langchain-Chachat`オープンソース プロジェクトは **20,000** つ以上のスターを獲得しました。
|
||||
+ `2024 年 1 月`: `LangChain 0.1.x` がリリースされ、`Langchain-Chachat 0.2.x` が安定版 `0.2.10` をリリースしました。
|
||||
今後はアップデートと技術サポートを停止し、より適用性の高い`Langchain-Chachat 0.3.x`の開発に努める予定です。
|
||||
|
||||
+ 🔥 これからのChatchatストーリーを一緒に楽しみにしましょう···
|
||||
|
||||
---
|
||||
|
||||
## お問い合わせ
|
||||
|
||||
### Telegram
|
||||
|
||||
[](https://t.me/+RjliQ3jnJ1YyN2E9)
|
||||
|
||||
### WeChat グループ
|
||||
|
||||
<img src="img/qr_code_90.jpg" alt="二维码" width="300" height="300" />
|
||||
|
||||
### WeChat 公式アカウント
|
||||
|
||||
<img src="img/official_wechat_mp_account.png" alt="图片" width="900" height="300" />
|
||||
@ -5,4 +5,4 @@ from .server_config import *
|
||||
from .prompt_config import *
|
||||
|
||||
|
||||
VERSION = "v0.2.8"
|
||||
VERSION = "v0.2.10"
|
||||
|
||||
@ -25,6 +25,8 @@ if not os.path.exists(LOG_PATH):
|
||||
|
||||
# 临时文件目录,主要用于文件对话
|
||||
BASE_TEMP_DIR = os.path.join(tempfile.gettempdir(), "chatchat")
|
||||
if os.path.isdir(BASE_TEMP_DIR):
|
||||
try:
|
||||
shutil.rmtree(BASE_TEMP_DIR)
|
||||
except Exception:
|
||||
pass
|
||||
os.makedirs(BASE_TEMP_DIR, exist_ok=True)
|
||||
|
||||
@ -3,7 +3,7 @@ import os
|
||||
# 默认使用的知识库
|
||||
DEFAULT_KNOWLEDGE_BASE = "samples"
|
||||
|
||||
# 默认向量库/全文检索引擎类型。可选:faiss, milvus(离线) & zilliz(在线), pgvector,全文检索引擎es
|
||||
# 默认向量库/全文检索引擎类型。可选:faiss, milvus(离线) & zilliz(在线), pgvector, chromadb 全文检索引擎es
|
||||
DEFAULT_VS_TYPE = "faiss"
|
||||
|
||||
# 缓存向量库数量(针对FAISS)
|
||||
@ -21,8 +21,9 @@ OVERLAP_SIZE = 50
|
||||
# 知识库匹配向量数量
|
||||
VECTOR_SEARCH_TOP_K = 3
|
||||
|
||||
# 知识库匹配相关度阈值,取值范围在0-1之间,SCORE越小,相关度越高,取到1相当于不筛选,建议设置在0.5左右
|
||||
SCORE_THRESHOLD = 1
|
||||
# 知识库匹配的距离阈值,一般取值范围在0-1之间,SCORE越小,距离越小从而相关度越高。
|
||||
# 但有用户报告遇到过匹配分值超过1的情况,为了兼容性默认设为1,在WEBUI中调整范围为0-2
|
||||
SCORE_THRESHOLD = 1.0
|
||||
|
||||
# 默认搜索引擎。可选:bing, duckduckgo, metaphor
|
||||
DEFAULT_SEARCH_ENGINE = "duckduckgo"
|
||||
@ -47,12 +48,17 @@ BING_SUBSCRIPTION_KEY = ""
|
||||
# metaphor搜索需要KEY
|
||||
METAPHOR_API_KEY = ""
|
||||
|
||||
# 心知天气 API KEY,用于天气Agent。申请:https://www.seniverse.com/
|
||||
SENIVERSE_API_KEY = ""
|
||||
|
||||
# 是否开启中文标题加强,以及标题增强的相关配置
|
||||
# 通过增加标题判断,判断哪些文本为标题,并在metadata中进行标记;
|
||||
# 然后将文本与往上一级的标题进行拼合,实现文本信息的增强。
|
||||
ZH_TITLE_ENHANCE = False
|
||||
|
||||
# PDF OCR 控制:只对宽高超过页面一定比例(图片宽/页面宽,图片高/页面高)的图片进行 OCR。
|
||||
# 这样可以避免 PDF 中一些小图片的干扰,提高非扫描版 PDF 处理速度
|
||||
PDF_OCR_THRESHOLD = (0.6, 0.6)
|
||||
|
||||
# 每个知识库的初始化介绍,用于在初始化知识库时显示和Agent调用,没写则没有介绍,不会被Agent调用。
|
||||
KB_INFO = {
|
||||
@ -100,7 +106,12 @@ kbs_config = {
|
||||
"index_name": "test_index",
|
||||
"user": "",
|
||||
"password": ""
|
||||
}
|
||||
},
|
||||
"milvus_kwargs":{
|
||||
"search_params":{"metric_type": "L2"}, #在此处增加search_params
|
||||
"index_params":{"metric_type": "L2","index_type": "HNSW"} # 在此处增加index_params
|
||||
},
|
||||
"chromadb": {}
|
||||
}
|
||||
|
||||
# TextSplitter配置项,如果你不明白其中的含义,就不要修改。
|
||||
|
||||
@ -6,11 +6,17 @@ import os
|
||||
MODEL_ROOT_PATH = ""
|
||||
|
||||
# 选用的 Embedding 名称
|
||||
EMBEDDING_MODEL = "bge-large-zh"
|
||||
EMBEDDING_MODEL = "bge-large-zh-v1.5"
|
||||
|
||||
# Embedding 模型运行设备。设为"auto"会自动检测,也可手动设定为"cuda","mps","cpu"其中之一。
|
||||
# Embedding 模型运行设备。设为 "auto" 会自动检测(会有警告),也可手动设定为 "cuda","mps","cpu","xpu" 其中之一。
|
||||
EMBEDDING_DEVICE = "auto"
|
||||
|
||||
# 选用的reranker模型
|
||||
RERANKER_MODEL = "bge-reranker-large"
|
||||
# 是否启用reranker模型
|
||||
USE_RERANKER = False
|
||||
RERANKER_MAX_LENGTH = 1024
|
||||
|
||||
# 如果需要在 EMBEDDING_MODEL 中增加自定义的关键字时配置
|
||||
EMBEDDING_KEYWORD_FILE = "keywords.txt"
|
||||
EMBEDDING_MODEL_OUTPUT_PATH = "output"
|
||||
@ -19,42 +25,34 @@ EMBEDDING_MODEL_OUTPUT_PATH = "output"
|
||||
# 列表中第一个模型将作为 API 和 WEBUI 的默认模型。
|
||||
# 在这里,我们使用目前主流的两个离线模型,其中,chatglm3-6b 为默认加载模型。
|
||||
# 如果你的显存不足,可使用 Qwen-1_8B-Chat, 该模型 FP16 仅需 3.8G显存。
|
||||
LLM_MODELS = ["chatglm3-6b", "zhipu-api", "openai-api"] # "Qwen-1_8B-Chat",
|
||||
|
||||
# AgentLM模型的名称 (可以不指定,指定之后就锁定进入Agent之后的Chain的模型,不指定就是LLM_MODELS[0])
|
||||
LLM_MODELS = ["chatglm3-6b", "zhipu-api", "openai-api"]
|
||||
Agent_MODEL = None
|
||||
|
||||
# LLM 运行设备。设为"auto"会自动检测,也可手动设定为"cuda","mps","cpu"其中之一。
|
||||
# LLM 模型运行设备。设为"auto"会自动检测(会有警告),也可手动设定为 "cuda","mps","cpu","xpu" 其中之一。
|
||||
LLM_DEVICE = "auto"
|
||||
|
||||
# 历史对话轮数
|
||||
HISTORY_LEN = 3
|
||||
|
||||
# 大模型最长支持的长度,如果不填写,则使用模型默认的最大长度,如果填写,则为用户设定的最大长度
|
||||
MAX_TOKENS = None
|
||||
MAX_TOKENS = 2048
|
||||
|
||||
# LLM通用对话参数
|
||||
TEMPERATURE = 0.7
|
||||
# TOP_P = 0.95 # ChatOpenAI暂不支持该参数
|
||||
|
||||
ONLINE_LLM_MODEL = {
|
||||
# 线上模型。请在server_config中为每个在线API设置不同的端口
|
||||
|
||||
"openai-api": {
|
||||
"model_name": "gpt-3.5-turbo",
|
||||
"model_name": "gpt-4",
|
||||
"api_base_url": "https://api.openai.com/v1",
|
||||
"api_key": "",
|
||||
"openai_proxy": "",
|
||||
},
|
||||
|
||||
# 具体注册及api key获取请前往 http://open.bigmodel.cn
|
||||
# 智谱AI API,具体注册及api key获取请前往 http://open.bigmodel.cn
|
||||
"zhipu-api": {
|
||||
"api_key": "",
|
||||
"version": "chatglm_turbo", # 可选包括 "chatglm_turbo"
|
||||
"version": "glm-4",
|
||||
"provider": "ChatGLMWorker",
|
||||
},
|
||||
|
||||
|
||||
# 具体注册及api key获取请前往 https://api.minimax.chat/
|
||||
"minimax-api": {
|
||||
"group_id": "",
|
||||
@ -63,13 +61,12 @@ ONLINE_LLM_MODEL = {
|
||||
"provider": "MiniMaxWorker",
|
||||
},
|
||||
|
||||
|
||||
# 具体注册及api key获取请前往 https://xinghuo.xfyun.cn/
|
||||
"xinghuo-api": {
|
||||
"APPID": "",
|
||||
"APISecret": "",
|
||||
"api_key": "",
|
||||
"version": "v1.5", # 你使用的讯飞星火大模型版本,可选包括 "v3.0", "v1.5", "v2.0"
|
||||
"version": "v3.5", # 你使用的讯飞星火大模型版本,可选包括 "v3.5","v3.0", "v2.0", "v1.5"
|
||||
"provider": "XingHuoWorker",
|
||||
},
|
||||
|
||||
@ -84,8 +81,8 @@ ONLINE_LLM_MODEL = {
|
||||
|
||||
# 火山方舟 API,文档参考 https://www.volcengine.com/docs/82379
|
||||
"fangzhou-api": {
|
||||
"version": "chatglm-6b-model", # 当前支持 "chatglm-6b-model", 更多的见文档模型支持列表中方舟部分。
|
||||
"version_url": "", # 可以不填写version,直接填写在方舟申请模型发布的API地址
|
||||
"version": "", # 对应火山方舟的 endpoint_id
|
||||
"version_url": "",
|
||||
"api_key": "",
|
||||
"secret_key": "",
|
||||
"provider": "FangZhouWorker",
|
||||
@ -93,14 +90,15 @@ ONLINE_LLM_MODEL = {
|
||||
|
||||
# 阿里云通义千问 API,文档参考 https://help.aliyun.com/zh/dashscope/developer-reference/api-details
|
||||
"qwen-api": {
|
||||
"version": "qwen-turbo", # 可选包括 "qwen-turbo", "qwen-plus"
|
||||
"api_key": "", # 请在阿里云控制台模型服务灵积API-KEY管理页面创建
|
||||
"version": "qwen-max",
|
||||
"api_key": "",
|
||||
"provider": "QwenWorker",
|
||||
"embed_model": "text-embedding-v1" # embedding 模型名称
|
||||
},
|
||||
|
||||
# 百川 API,申请方式请参考 https://www.baichuan-ai.com/home#api-enter
|
||||
"baichuan-api": {
|
||||
"version": "Baichuan2-53B", # 当前支持 "Baichuan2-53B", 见官方文档。
|
||||
"version": "Baichuan2-53B",
|
||||
"api_key": "",
|
||||
"secret_key": "",
|
||||
"provider": "BaiChuanWorker",
|
||||
@ -123,6 +121,24 @@ ONLINE_LLM_MODEL = {
|
||||
"provider": "TianGongWorker",
|
||||
},
|
||||
|
||||
# Gemini API https://makersuite.google.com/app/apikey
|
||||
"gemini-api": {
|
||||
"api_key": "",
|
||||
"provider": "GeminiWorker",
|
||||
},
|
||||
|
||||
# Claude API : https://www.anthropic.com/api
|
||||
# Available models:
|
||||
# Claude 3 Opus: claude-3-opus-20240229
|
||||
# Claude 3 Sonnet claude-3-sonnet-20240229
|
||||
# Claude 3 Haiku claude-3-haiku-20240307
|
||||
"claude-api": {
|
||||
"api_key": "",
|
||||
"version": "2023-06-01",
|
||||
"model_name":"claude-3-opus-20240229",
|
||||
"provider": "ClaudeWorker",
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# 在以下字典中修改属性值,以指定本地embedding模型存储位置。支持3种设置方法:
|
||||
@ -133,6 +149,7 @@ ONLINE_LLM_MODEL = {
|
||||
# - GanymedeNil/text2vec-large-chinese
|
||||
# - text2vec-large-chinese
|
||||
# 2.2 如果以上本地路径不存在,则使用huggingface模型
|
||||
|
||||
MODEL_PATH = {
|
||||
"embed_model": {
|
||||
"ernie-tiny": "nghuyong/ernie-3.0-nano-zh",
|
||||
@ -146,12 +163,16 @@ MODEL_PATH = {
|
||||
"m3e-small": "moka-ai/m3e-small",
|
||||
"m3e-base": "moka-ai/m3e-base",
|
||||
"m3e-large": "moka-ai/m3e-large",
|
||||
|
||||
"bge-small-zh": "BAAI/bge-small-zh",
|
||||
"bge-base-zh": "BAAI/bge-base-zh",
|
||||
"bge-large-zh": "BAAI/bge-large-zh",
|
||||
"bge-large-zh-noinstruct": "BAAI/bge-large-zh-noinstruct",
|
||||
"bge-base-zh-v1.5": "BAAI/bge-base-zh-v1.5",
|
||||
"bge-large-zh-v1.5": "BAAI/bge-large-zh-v1.5",
|
||||
|
||||
"bge-m3": "BAAI/bge-m3",
|
||||
|
||||
"piccolo-base-zh": "sensenova/piccolo-base-zh",
|
||||
"piccolo-large-zh": "sensenova/piccolo-large-zh",
|
||||
"nlp_gte_sentence-embedding_chinese-large": "damo/nlp_gte_sentence-embedding_chinese-large",
|
||||
@ -159,52 +180,67 @@ MODEL_PATH = {
|
||||
},
|
||||
|
||||
"llm_model": {
|
||||
# 以下部分模型并未完全测试,仅根据fastchat和vllm模型的模型列表推定支持
|
||||
"chatglm2-6b": "THUDM/chatglm2-6b",
|
||||
"chatglm2-6b-32k": "THUDM/chatglm2-6b-32k",
|
||||
|
||||
"chatglm3-6b": "THUDM/chatglm3-6b",
|
||||
"chatglm3-6b-32k": "THUDM/chatglm3-6b-32k",
|
||||
"chatglm3-6b-base": "THUDM/chatglm3-6b-base",
|
||||
|
||||
"Qwen-1_8B": "Qwen/Qwen-1_8B",
|
||||
"Orion-14B-Chat": "OrionStarAI/Orion-14B-Chat",
|
||||
"Orion-14B-Chat-Plugin": "OrionStarAI/Orion-14B-Chat-Plugin",
|
||||
"Orion-14B-LongChat": "OrionStarAI/Orion-14B-LongChat",
|
||||
|
||||
"Llama-2-7b-chat-hf": "meta-llama/Llama-2-7b-chat-hf",
|
||||
"Llama-2-13b-chat-hf": "meta-llama/Llama-2-13b-chat-hf",
|
||||
"Llama-2-70b-chat-hf": "meta-llama/Llama-2-70b-chat-hf",
|
||||
|
||||
"Qwen-1_8B-Chat": "Qwen/Qwen-1_8B-Chat",
|
||||
"Qwen-1_8B-Chat-Int8": "Qwen/Qwen-1_8B-Chat-Int8",
|
||||
"Qwen-1_8B-Chat-Int4": "Qwen/Qwen-1_8B-Chat-Int4",
|
||||
|
||||
"Qwen-7B": "Qwen/Qwen-7B",
|
||||
"Qwen-7B-Chat": "Qwen/Qwen-7B-Chat",
|
||||
|
||||
"Qwen-14B": "Qwen/Qwen-14B",
|
||||
"Qwen-14B-Chat": "Qwen/Qwen-14B-Chat",
|
||||
"Qwen-14B-Chat-Int8": "Qwen/Qwen-14B-Chat-Int8",
|
||||
"Qwen-14B-Chat-Int4": "Qwen/Qwen-14B-Chat-Int4",
|
||||
|
||||
"Qwen-72B": "Qwen/Qwen-72B",
|
||||
"Qwen-72B-Chat": "Qwen/Qwen-72B-Chat",
|
||||
"Qwen-72B-Chat-Int8": "Qwen/Qwen-72B-Chat-Int8",
|
||||
"Qwen-72B-Chat-Int4": "Qwen/Qwen-72B-Chat-Int4",
|
||||
|
||||
"baichuan2-13b": "baichuan-inc/Baichuan2-13B-Chat",
|
||||
"baichuan2-7b": "baichuan-inc/Baichuan2-7B-Chat",
|
||||
# Qwen1.5 模型 VLLM可能出现问题
|
||||
"Qwen1.5-0.5B-Chat": "Qwen/Qwen1.5-0.5B-Chat",
|
||||
"Qwen1.5-1.8B-Chat": "Qwen/Qwen1.5-1.8B-Chat",
|
||||
"Qwen1.5-4B-Chat": "Qwen/Qwen1.5-4B-Chat",
|
||||
"Qwen1.5-7B-Chat": "Qwen/Qwen1.5-7B-Chat",
|
||||
"Qwen1.5-14B-Chat": "Qwen/Qwen1.5-14B-Chat",
|
||||
"Qwen1.5-72B-Chat": "Qwen/Qwen1.5-72B-Chat",
|
||||
|
||||
"baichuan-7b": "baichuan-inc/Baichuan-7B",
|
||||
"baichuan-13b": "baichuan-inc/Baichuan-13B",
|
||||
"baichuan-7b-chat": "baichuan-inc/Baichuan-7B-Chat",
|
||||
"baichuan-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
|
||||
|
||||
"aquila-7b": "BAAI/Aquila-7B",
|
||||
"aquilachat-7b": "BAAI/AquilaChat-7B",
|
||||
"baichuan2-7b-chat": "baichuan-inc/Baichuan2-7B-Chat",
|
||||
"baichuan2-13b-chat": "baichuan-inc/Baichuan2-13B-Chat",
|
||||
|
||||
"internlm-7b": "internlm/internlm-7b",
|
||||
"internlm-chat-7b": "internlm/internlm-chat-7b",
|
||||
"internlm2-chat-7b": "internlm/internlm2-chat-7b",
|
||||
"internlm2-chat-20b": "internlm/internlm2-chat-20b",
|
||||
|
||||
"BlueLM-7B-Chat": "vivo-ai/BlueLM-7B-Chat",
|
||||
"BlueLM-7B-Chat-32k": "vivo-ai/BlueLM-7B-Chat-32k",
|
||||
|
||||
"Yi-34B-Chat": "https://huggingface.co/01-ai/Yi-34B-Chat",
|
||||
|
||||
"agentlm-7b": "THUDM/agentlm-7b",
|
||||
"agentlm-13b": "THUDM/agentlm-13b",
|
||||
"agentlm-70b": "THUDM/agentlm-70b",
|
||||
|
||||
"falcon-7b": "tiiuae/falcon-7b",
|
||||
"falcon-40b": "tiiuae/falcon-40b",
|
||||
"falcon-rw-7b": "tiiuae/falcon-rw-7b",
|
||||
|
||||
"aquila-7b": "BAAI/Aquila-7B",
|
||||
"aquilachat-7b": "BAAI/AquilaChat-7B",
|
||||
"open_llama_13b": "openlm-research/open_llama_13b",
|
||||
"vicuna-13b-v1.5": "lmsys/vicuna-13b-v1.5",
|
||||
"koala": "young-geng/koala",
|
||||
"mpt-7b": "mosaicml/mpt-7b",
|
||||
"mpt-7b-storywriter": "mosaicml/mpt-7b-storywriter",
|
||||
"mpt-30b": "mosaicml/mpt-30b",
|
||||
"opt-66b": "facebook/opt-66b",
|
||||
"opt-iml-max-30b": "facebook/opt-iml-max-30b",
|
||||
"gpt2": "gpt2",
|
||||
"gpt2-xl": "gpt2-xl",
|
||||
|
||||
"gpt-j-6b": "EleutherAI/gpt-j-6b",
|
||||
"gpt4all-j": "nomic-ai/gpt4all-j",
|
||||
"gpt-neox-20b": "EleutherAI/gpt-neox-20b",
|
||||
@ -212,58 +248,51 @@ MODEL_PATH = {
|
||||
"oasst-sft-4-pythia-12b-epoch-3.5": "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5",
|
||||
"dolly-v2-12b": "databricks/dolly-v2-12b",
|
||||
"stablelm-tuned-alpha-7b": "stabilityai/stablelm-tuned-alpha-7b",
|
||||
|
||||
"Llama-2-13b-hf": "meta-llama/Llama-2-13b-hf",
|
||||
"Llama-2-70b-hf": "meta-llama/Llama-2-70b-hf",
|
||||
"open_llama_13b": "openlm-research/open_llama_13b",
|
||||
"vicuna-13b-v1.3": "lmsys/vicuna-13b-v1.3",
|
||||
"koala": "young-geng/koala",
|
||||
|
||||
"mpt-7b": "mosaicml/mpt-7b",
|
||||
"mpt-7b-storywriter": "mosaicml/mpt-7b-storywriter",
|
||||
"mpt-30b": "mosaicml/mpt-30b",
|
||||
"opt-66b": "facebook/opt-66b",
|
||||
"opt-iml-max-30b": "facebook/opt-iml-max-30b",
|
||||
|
||||
"agentlm-7b": "THUDM/agentlm-7b",
|
||||
"agentlm-13b": "THUDM/agentlm-13b",
|
||||
"agentlm-70b": "THUDM/agentlm-70b",
|
||||
|
||||
"Yi-34B-Chat": "https://huggingface.co/01-ai/Yi-34B-Chat",
|
||||
},
|
||||
}
|
||||
|
||||
"reranker": {
|
||||
"bge-reranker-large": "BAAI/bge-reranker-large",
|
||||
"bge-reranker-base": "BAAI/bge-reranker-base",
|
||||
}
|
||||
}
|
||||
|
||||
# 通常情况下不需要更改以下内容
|
||||
|
||||
# nltk 模型存储路径
|
||||
NLTK_DATA_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "nltk_data")
|
||||
|
||||
# 使用VLLM可能导致模型推理能力下降,无法完成Agent任务
|
||||
VLLM_MODEL_DICT = {
|
||||
"aquila-7b": "BAAI/Aquila-7B",
|
||||
"aquilachat-7b": "BAAI/AquilaChat-7B",
|
||||
|
||||
"baichuan-7b": "baichuan-inc/Baichuan-7B",
|
||||
"baichuan-13b": "baichuan-inc/Baichuan-13B",
|
||||
"baichuan-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
|
||||
|
||||
"chatglm2-6b": "THUDM/chatglm2-6b",
|
||||
"chatglm2-6b-32k": "THUDM/chatglm2-6b-32k",
|
||||
"chatglm3-6b": "THUDM/chatglm3-6b",
|
||||
"chatglm3-6b-32k": "THUDM/chatglm3-6b-32k",
|
||||
|
||||
"Llama-2-7b-chat-hf": "meta-llama/Llama-2-7b-chat-hf",
|
||||
"Llama-2-13b-chat-hf": "meta-llama/Llama-2-13b-chat-hf",
|
||||
"Llama-2-70b-chat-hf": "meta-llama/Llama-2-70b-chat-hf",
|
||||
|
||||
"Qwen-1_8B-Chat": "Qwen/Qwen-1_8B-Chat",
|
||||
"Qwen-7B-Chat": "Qwen/Qwen-7B-Chat",
|
||||
"Qwen-14B-Chat": "Qwen/Qwen-14B-Chat",
|
||||
"Qwen-72B-Chat": "Qwen/Qwen-72B-Chat",
|
||||
|
||||
"baichuan-7b-chat": "baichuan-inc/Baichuan-7B-Chat",
|
||||
"baichuan-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
|
||||
"baichuan2-7b-chat": "baichuan-inc/Baichuan-7B-Chat",
|
||||
"baichuan2-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
|
||||
|
||||
"BlueLM-7B-Chat": "vivo-ai/BlueLM-7B-Chat",
|
||||
"BlueLM-7B-Chat-32k": "vivo-ai/BlueLM-7B-Chat-32k",
|
||||
|
||||
# 注意:bloom系列的tokenizer与model是分离的,因此虽然vllm支持,但与fschat框架不兼容
|
||||
# "bloom": "bigscience/bloom",
|
||||
# "bloomz": "bigscience/bloomz",
|
||||
# "bloomz-560m": "bigscience/bloomz-560m",
|
||||
# "bloomz-7b1": "bigscience/bloomz-7b1",
|
||||
# "bloomz-1b7": "bigscience/bloomz-1b7",
|
||||
|
||||
"internlm-7b": "internlm/internlm-7b",
|
||||
"internlm-chat-7b": "internlm/internlm-chat-7b",
|
||||
"internlm2-chat-7b": "internlm/Models/internlm2-chat-7b",
|
||||
"internlm2-chat-20b": "internlm/Models/internlm2-chat-20b",
|
||||
|
||||
"aquila-7b": "BAAI/Aquila-7B",
|
||||
"aquilachat-7b": "BAAI/AquilaChat-7B",
|
||||
|
||||
"falcon-7b": "tiiuae/falcon-7b",
|
||||
"falcon-40b": "tiiuae/falcon-40b",
|
||||
"falcon-rw-7b": "tiiuae/falcon-rw-7b",
|
||||
@ -276,8 +305,6 @@ VLLM_MODEL_DICT = {
|
||||
"oasst-sft-4-pythia-12b-epoch-3.5": "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5",
|
||||
"dolly-v2-12b": "databricks/dolly-v2-12b",
|
||||
"stablelm-tuned-alpha-7b": "stabilityai/stablelm-tuned-alpha-7b",
|
||||
"Llama-2-13b-hf": "meta-llama/Llama-2-13b-hf",
|
||||
"Llama-2-70b-hf": "meta-llama/Llama-2-70b-hf",
|
||||
"open_llama_13b": "openlm-research/open_llama_13b",
|
||||
"vicuna-13b-v1.3": "lmsys/vicuna-13b-v1.3",
|
||||
"koala": "young-geng/koala",
|
||||
@ -287,37 +314,14 @@ VLLM_MODEL_DICT = {
|
||||
"opt-66b": "facebook/opt-66b",
|
||||
"opt-iml-max-30b": "facebook/opt-iml-max-30b",
|
||||
|
||||
"Qwen-1_8B": "Qwen/Qwen-1_8B",
|
||||
"Qwen-1_8B-Chat": "Qwen/Qwen-1_8B-Chat",
|
||||
"Qwen-1_8B-Chat-Int8": "Qwen/Qwen-1_8B-Chat-Int8",
|
||||
"Qwen-1_8B-Chat-Int4": "Qwen/Qwen-1_8B-Chat-Int4",
|
||||
|
||||
"Qwen-7B": "Qwen/Qwen-7B",
|
||||
"Qwen-7B-Chat": "Qwen/Qwen-7B-Chat",
|
||||
|
||||
"Qwen-14B": "Qwen/Qwen-14B",
|
||||
"Qwen-14B-Chat": "Qwen/Qwen-14B-Chat",
|
||||
"Qwen-14B-Chat-Int8": "Qwen/Qwen-14B-Chat-Int8",
|
||||
"Qwen-14B-Chat-Int4": "Qwen/Qwen-14B-Chat-Int4",
|
||||
|
||||
"Qwen-72B": "Qwen/Qwen-72B",
|
||||
"Qwen-72B-Chat": "Qwen/Qwen-72B-Chat",
|
||||
"Qwen-72B-Chat-Int8": "Qwen/Qwen-72B-Chat-Int8",
|
||||
"Qwen-72B-Chat-Int4": "Qwen/Qwen-72B-Chat-Int4",
|
||||
|
||||
"agentlm-7b": "THUDM/agentlm-7b",
|
||||
"agentlm-13b": "THUDM/agentlm-13b",
|
||||
"agentlm-70b": "THUDM/agentlm-70b",
|
||||
|
||||
}
|
||||
|
||||
# 你认为支持Agent能力的模型,可以在这里添加,添加后不会出现可视化界面的警告
|
||||
# 经过我们测试,原生支持Agent的模型仅有以下几个
|
||||
SUPPORT_AGENT_MODEL = [
|
||||
"azure-api",
|
||||
"openai-api",
|
||||
"qwen-api",
|
||||
"Qwen",
|
||||
"chatglm3",
|
||||
"xinghuo-api",
|
||||
"openai-api", # GPT4 模型
|
||||
"qwen-api", # Qwen Max模型
|
||||
"zhipu-api", # 智谱AI GLM4模型
|
||||
"Qwen", # 所有Qwen系列本地模型
|
||||
"chatglm3-6b",
|
||||
"internlm2-chat-20b",
|
||||
"Orion-14B-Chat-Plugin",
|
||||
]
|
||||
|
||||
@ -40,8 +40,6 @@ FSCHAT_MODEL_WORKERS = {
|
||||
"device": LLM_DEVICE,
|
||||
# False,'vllm',使用的推理加速框架,使用vllm如果出现HuggingFace通信问题,参见doc/FAQ
|
||||
# vllm对一些模型支持还不成熟,暂时默认关闭
|
||||
# fschat=0.2.33的代码有bug, 如需使用,源码修改fastchat.server.vllm_worker,
|
||||
# 将103行中sampling_params = SamplingParams的参数stop=list(stop)修改为stop= [i for i in stop if i!=""]
|
||||
"infer_turbo": False,
|
||||
|
||||
# model_worker多卡加载需要配置的参数
|
||||
@ -92,14 +90,12 @@ FSCHAT_MODEL_WORKERS = {
|
||||
# 'disable_log_requests': False
|
||||
|
||||
},
|
||||
# 可以如下示例方式更改默认配置
|
||||
# "Qwen-1_8B-Chat": { # 使用default中的IP和端口
|
||||
# "device": "cpu",
|
||||
# },
|
||||
"chatglm3-6b": { # 使用default中的IP和端口
|
||||
"chatglm3-6b": {
|
||||
"device": "cuda",
|
||||
},
|
||||
"Qwen1.5-0.5B-Chat": {
|
||||
"device": "cuda",
|
||||
},
|
||||
|
||||
# 以下配置可以不用修改,在model_config中设置启动的模型
|
||||
"zhipu-api": {
|
||||
"port": 21001,
|
||||
@ -128,14 +124,14 @@ FSCHAT_MODEL_WORKERS = {
|
||||
"tiangong-api": {
|
||||
"port": 21009,
|
||||
},
|
||||
"gemini-api": {
|
||||
"port": 21010,
|
||||
},
|
||||
"claude-api": {
|
||||
"port": 21011,
|
||||
},
|
||||
}
|
||||
|
||||
# fastchat multi model worker server
|
||||
FSCHAT_MULTI_MODEL_WORKERS = {
|
||||
# TODO:
|
||||
}
|
||||
|
||||
# fastchat controller server
|
||||
FSCHAT_CONTROLLER = {
|
||||
"host": DEFAULT_BIND_HOST,
|
||||
"port": 20001,
|
||||
|
||||
@ -59,23 +59,26 @@ class FilteredCSVLoader(CSVLoader):
|
||||
docs = []
|
||||
csv_reader = csv.DictReader(csvfile, **self.csv_args) # type: ignore
|
||||
for i, row in enumerate(csv_reader):
|
||||
if self.columns_to_read[0] in row:
|
||||
content = row[self.columns_to_read[0]]
|
||||
# Extract the source if available
|
||||
source = (
|
||||
row.get(self.source_column, None)
|
||||
if self.source_column is not None
|
||||
else self.file_path
|
||||
)
|
||||
metadata = {"source": source, "row": i}
|
||||
content = []
|
||||
for col in self.columns_to_read:
|
||||
if col in row:
|
||||
content.append(f'{col}:{str(row[col])}')
|
||||
else:
|
||||
raise ValueError(f"Column '{self.columns_to_read[0]}' not found in CSV file.")
|
||||
content = '\n'.join(content)
|
||||
# Extract the source if available
|
||||
source = (
|
||||
row.get(self.source_column, None)
|
||||
if self.source_column is not None
|
||||
else self.file_path
|
||||
)
|
||||
metadata = {"source": source, "row": i}
|
||||
|
||||
for col in self.metadata_columns:
|
||||
if col in row:
|
||||
metadata[col] = row[col]
|
||||
for col in self.metadata_columns:
|
||||
if col in row:
|
||||
metadata[col] = row[col]
|
||||
|
||||
doc = Document(page_content=content, metadata=metadata)
|
||||
docs.append(doc)
|
||||
else:
|
||||
raise ValueError(f"Column '{self.columns_to_read[0]}' not found in CSV file.")
|
||||
doc = Document(page_content=content, metadata=metadata)
|
||||
docs.append(doc)
|
||||
|
||||
return docs
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
from .mypdfloader import RapidOCRPDFLoader
|
||||
from .myimgloader import RapidOCRLoader
|
||||
from .myimgloader import RapidOCRLoader
|
||||
from .mydocloader import RapidOCRDocLoader
|
||||
from .mypptloader import RapidOCRPPTLoader
|
||||
|
||||
71
document_loaders/mydocloader.py
Normal file
@ -0,0 +1,71 @@
|
||||
from langchain.document_loaders.unstructured import UnstructuredFileLoader
|
||||
from typing import List
|
||||
import tqdm
|
||||
|
||||
|
||||
class RapidOCRDocLoader(UnstructuredFileLoader):
|
||||
def _get_elements(self) -> List:
|
||||
def doc2text(filepath):
|
||||
from docx.table import _Cell, Table
|
||||
from docx.oxml.table import CT_Tbl
|
||||
from docx.oxml.text.paragraph import CT_P
|
||||
from docx.text.paragraph import Paragraph
|
||||
from docx import Document, ImagePart
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
import numpy as np
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
ocr = RapidOCR()
|
||||
doc = Document(filepath)
|
||||
resp = ""
|
||||
|
||||
def iter_block_items(parent):
|
||||
from docx.document import Document
|
||||
if isinstance(parent, Document):
|
||||
parent_elm = parent.element.body
|
||||
elif isinstance(parent, _Cell):
|
||||
parent_elm = parent._tc
|
||||
else:
|
||||
raise ValueError("RapidOCRDocLoader parse fail")
|
||||
|
||||
for child in parent_elm.iterchildren():
|
||||
if isinstance(child, CT_P):
|
||||
yield Paragraph(child, parent)
|
||||
elif isinstance(child, CT_Tbl):
|
||||
yield Table(child, parent)
|
||||
|
||||
b_unit = tqdm.tqdm(total=len(doc.paragraphs)+len(doc.tables),
|
||||
desc="RapidOCRDocLoader block index: 0")
|
||||
for i, block in enumerate(iter_block_items(doc)):
|
||||
b_unit.set_description(
|
||||
"RapidOCRDocLoader block index: {}".format(i))
|
||||
b_unit.refresh()
|
||||
if isinstance(block, Paragraph):
|
||||
resp += block.text.strip() + "\n"
|
||||
images = block._element.xpath('.//pic:pic') # 获取所有图片
|
||||
for image in images:
|
||||
for img_id in image.xpath('.//a:blip/@r:embed'): # 获取图片id
|
||||
part = doc.part.related_parts[img_id] # 根据图片id获取对应的图片
|
||||
if isinstance(part, ImagePart):
|
||||
image = Image.open(BytesIO(part._blob))
|
||||
result, _ = ocr(np.array(image))
|
||||
if result:
|
||||
ocr_result = [line[1] for line in result]
|
||||
resp += "\n".join(ocr_result)
|
||||
elif isinstance(block, Table):
|
||||
for row in block.rows:
|
||||
for cell in row.cells:
|
||||
for paragraph in cell.paragraphs:
|
||||
resp += paragraph.text.strip() + "\n"
|
||||
b_unit.update(1)
|
||||
return resp
|
||||
|
||||
text = doc2text(self.file_path)
|
||||
from unstructured.partition.text import partition_text
|
||||
return partition_text(text=text, **self.unstructured_kwargs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
loader = RapidOCRDocLoader(file_path="../tests/samples/ocr_test.docx")
|
||||
docs = loader.load()
|
||||
print(docs)
|
||||
@ -1,13 +1,13 @@
|
||||
from typing import List
|
||||
from langchain.document_loaders.unstructured import UnstructuredFileLoader
|
||||
from document_loaders.ocr import get_ocr
|
||||
|
||||
|
||||
class RapidOCRLoader(UnstructuredFileLoader):
|
||||
def _get_elements(self) -> List:
|
||||
def img2text(filepath):
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
resp = ""
|
||||
ocr = RapidOCR()
|
||||
ocr = get_ocr()
|
||||
result, _ = ocr(filepath)
|
||||
if result:
|
||||
ocr_result = [line[1] for line in result]
|
||||
|
||||
@ -1,37 +1,76 @@
|
||||
from typing import List
|
||||
from langchain.document_loaders.unstructured import UnstructuredFileLoader
|
||||
import cv2
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
from configs import PDF_OCR_THRESHOLD
|
||||
from document_loaders.ocr import get_ocr
|
||||
import tqdm
|
||||
|
||||
|
||||
class RapidOCRPDFLoader(UnstructuredFileLoader):
|
||||
def _get_elements(self) -> List:
|
||||
def rotate_img(img, angle):
|
||||
'''
|
||||
img --image
|
||||
angle --rotation angle
|
||||
return--rotated img
|
||||
'''
|
||||
|
||||
h, w = img.shape[:2]
|
||||
rotate_center = (w/2, h/2)
|
||||
#获取旋转矩阵
|
||||
# 参数1为旋转中心点;
|
||||
# 参数2为旋转角度,正值-逆时针旋转;负值-顺时针旋转
|
||||
# 参数3为各向同性的比例因子,1.0原图,2.0变成原来的2倍,0.5变成原来的0.5倍
|
||||
M = cv2.getRotationMatrix2D(rotate_center, angle, 1.0)
|
||||
#计算图像新边界
|
||||
new_w = int(h * np.abs(M[0, 1]) + w * np.abs(M[0, 0]))
|
||||
new_h = int(h * np.abs(M[0, 0]) + w * np.abs(M[0, 1]))
|
||||
#调整旋转矩阵以考虑平移
|
||||
M[0, 2] += (new_w - w) / 2
|
||||
M[1, 2] += (new_h - h) / 2
|
||||
|
||||
rotated_img = cv2.warpAffine(img, M, (new_w, new_h))
|
||||
return rotated_img
|
||||
|
||||
def pdf2text(filepath):
|
||||
import fitz # pyMuPDF里面的fitz包,不要与pip install fitz混淆
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
import numpy as np
|
||||
ocr = RapidOCR()
|
||||
ocr = get_ocr()
|
||||
doc = fitz.open(filepath)
|
||||
resp = ""
|
||||
|
||||
b_unit = tqdm.tqdm(total=doc.page_count, desc="RapidOCRPDFLoader context page index: 0")
|
||||
for i, page in enumerate(doc):
|
||||
|
||||
# 更新描述
|
||||
b_unit.set_description("RapidOCRPDFLoader context page index: {}".format(i))
|
||||
# 立即显示进度条更新结果
|
||||
b_unit.refresh()
|
||||
# TODO: 依据文本与图片顺序调整处理方式
|
||||
text = page.get_text("")
|
||||
resp += text + "\n"
|
||||
|
||||
img_list = page.get_images()
|
||||
img_list = page.get_image_info(xrefs=True)
|
||||
for img in img_list:
|
||||
pix = fitz.Pixmap(doc, img[0])
|
||||
img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
|
||||
result, _ = ocr(img_array)
|
||||
if result:
|
||||
ocr_result = [line[1] for line in result]
|
||||
resp += "\n".join(ocr_result)
|
||||
if xref := img.get("xref"):
|
||||
bbox = img["bbox"]
|
||||
# 检查图片尺寸是否超过设定的阈值
|
||||
if ((bbox[2] - bbox[0]) / (page.rect.width) < PDF_OCR_THRESHOLD[0]
|
||||
or (bbox[3] - bbox[1]) / (page.rect.height) < PDF_OCR_THRESHOLD[1]):
|
||||
continue
|
||||
pix = fitz.Pixmap(doc, xref)
|
||||
samples = pix.samples
|
||||
if int(page.rotation)!=0: #如果Page有旋转角度,则旋转图片
|
||||
img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
|
||||
tmp_img = Image.fromarray(img_array);
|
||||
ori_img = cv2.cvtColor(np.array(tmp_img),cv2.COLOR_RGB2BGR)
|
||||
rot_img = rotate_img(img=ori_img, angle=360-page.rotation)
|
||||
img_array = cv2.cvtColor(rot_img, cv2.COLOR_RGB2BGR)
|
||||
else:
|
||||
img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
|
||||
|
||||
result, _ = ocr(img_array)
|
||||
if result:
|
||||
ocr_result = [line[1] for line in result]
|
||||
resp += "\n".join(ocr_result)
|
||||
|
||||
# 更新进度
|
||||
b_unit.update(1)
|
||||
@ -43,6 +82,6 @@ class RapidOCRPDFLoader(UnstructuredFileLoader):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
loader = RapidOCRPDFLoader(file_path="../tests/samples/ocr_test.pdf")
|
||||
loader = RapidOCRPDFLoader(file_path="/Users/tonysong/Desktop/test.pdf")
|
||||
docs = loader.load()
|
||||
print(docs)
|
||||
|
||||
59
document_loaders/mypptloader.py
Normal file
@ -0,0 +1,59 @@
|
||||
from langchain.document_loaders.unstructured import UnstructuredFileLoader
|
||||
from typing import List
|
||||
import tqdm
|
||||
|
||||
|
||||
class RapidOCRPPTLoader(UnstructuredFileLoader):
|
||||
def _get_elements(self) -> List:
|
||||
def ppt2text(filepath):
|
||||
from pptx import Presentation
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
from io import BytesIO
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
ocr = RapidOCR()
|
||||
prs = Presentation(filepath)
|
||||
resp = ""
|
||||
|
||||
def extract_text(shape):
|
||||
nonlocal resp
|
||||
if shape.has_text_frame:
|
||||
resp += shape.text.strip() + "\n"
|
||||
if shape.has_table:
|
||||
for row in shape.table.rows:
|
||||
for cell in row.cells:
|
||||
for paragraph in cell.text_frame.paragraphs:
|
||||
resp += paragraph.text.strip() + "\n"
|
||||
if shape.shape_type == 13: # 13 表示图片
|
||||
image = Image.open(BytesIO(shape.image.blob))
|
||||
result, _ = ocr(np.array(image))
|
||||
if result:
|
||||
ocr_result = [line[1] for line in result]
|
||||
resp += "\n".join(ocr_result)
|
||||
elif shape.shape_type == 6: # 6 表示组合
|
||||
for child_shape in shape.shapes:
|
||||
extract_text(child_shape)
|
||||
|
||||
b_unit = tqdm.tqdm(total=len(prs.slides),
|
||||
desc="RapidOCRPPTLoader slide index: 1")
|
||||
# 遍历所有幻灯片
|
||||
for slide_number, slide in enumerate(prs.slides, start=1):
|
||||
b_unit.set_description(
|
||||
"RapidOCRPPTLoader slide index: {}".format(slide_number))
|
||||
b_unit.refresh()
|
||||
sorted_shapes = sorted(slide.shapes,
|
||||
key=lambda x: (x.top, x.left)) # 从上到下、从左到右遍历
|
||||
for shape in sorted_shapes:
|
||||
extract_text(shape)
|
||||
b_unit.update(1)
|
||||
return resp
|
||||
|
||||
text = ppt2text(self.file_path)
|
||||
from unstructured.partition.text import partition_text
|
||||
return partition_text(text=text, **self.unstructured_kwargs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
loader = RapidOCRPPTLoader(file_path="../tests/samples/ocr_test.pptx")
|
||||
docs = loader.load()
|
||||
print(docs)
|
||||
18
document_loaders/ocr.py
Normal file
@ -0,0 +1,18 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
try:
|
||||
from rapidocr_paddle import RapidOCR
|
||||
except ImportError:
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
|
||||
|
||||
def get_ocr(use_cuda: bool = True) -> "RapidOCR":
|
||||
try:
|
||||
from rapidocr_paddle import RapidOCR
|
||||
ocr = RapidOCR(det_use_cuda=use_cuda, cls_use_cuda=use_cuda, rec_use_cuda=use_cuda)
|
||||
except ImportError:
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
ocr = RapidOCR()
|
||||
return ocr
|
||||
@ -7,31 +7,35 @@
|
||||
保存的模型的位置位于原本嵌入模型的目录下,模型的名称为原模型名称+Merge_Keywords_时间戳
|
||||
'''
|
||||
import sys
|
||||
|
||||
sys.path.append("..")
|
||||
import os
|
||||
import torch
|
||||
|
||||
from datetime import datetime
|
||||
from configs import (
|
||||
MODEL_PATH,
|
||||
EMBEDDING_MODEL,
|
||||
EMBEDDING_KEYWORD_FILE,
|
||||
)
|
||||
import os
|
||||
import torch
|
||||
|
||||
from safetensors.torch import save_model
|
||||
from sentence_transformers import SentenceTransformer
|
||||
from langchain_core._api import deprecated
|
||||
|
||||
|
||||
@deprecated(
|
||||
since="0.3.0",
|
||||
message="自定义关键词 Langchain-Chatchat 0.3.x 重写, 0.2.x中相关功能将废弃",
|
||||
removal="0.3.0"
|
||||
)
|
||||
def get_keyword_embedding(bert_model, tokenizer, key_words):
|
||||
tokenizer_output = tokenizer(key_words, return_tensors="pt", padding=True, truncation=True)
|
||||
|
||||
# No need to manually convert to tensor as we've set return_tensors="pt"
|
||||
input_ids = tokenizer_output['input_ids']
|
||||
|
||||
# Remove the first and last token for each sequence in the batch
|
||||
input_ids = input_ids[:, 1:-1]
|
||||
|
||||
keyword_embedding = bert_model.embeddings.word_embeddings(input_ids)
|
||||
keyword_embedding = torch.mean(keyword_embedding, 1)
|
||||
|
||||
return keyword_embedding
|
||||
|
||||
|
||||
@ -47,14 +51,11 @@ def add_keyword_to_model(model_name=EMBEDDING_MODEL, keyword_file: str = "", out
|
||||
bert_model = word_embedding_model.auto_model
|
||||
tokenizer = word_embedding_model.tokenizer
|
||||
key_words_embedding = get_keyword_embedding(bert_model, tokenizer, key_words)
|
||||
# key_words_embedding = st_model.encode(key_words)
|
||||
|
||||
embedding_weight = bert_model.embeddings.word_embeddings.weight
|
||||
embedding_weight_len = len(embedding_weight)
|
||||
tokenizer.add_tokens(key_words)
|
||||
bert_model.resize_token_embeddings(len(tokenizer), pad_to_multiple_of=32)
|
||||
|
||||
# key_words_embedding_tensor = torch.from_numpy(key_words_embedding)
|
||||
embedding_weight = bert_model.embeddings.word_embeddings.weight
|
||||
with torch.no_grad():
|
||||
embedding_weight[embedding_weight_len:embedding_weight_len + key_words_len, :] = key_words_embedding
|
||||
@ -76,46 +77,3 @@ def add_keyword_to_embedding_model(path: str = EMBEDDING_KEYWORD_FILE):
|
||||
output_model_name = "{}_Merge_Keywords_{}".format(EMBEDDING_MODEL, current_time)
|
||||
output_model_path = os.path.join(model_parent_directory, output_model_name)
|
||||
add_keyword_to_model(model_name, keyword_file, output_model_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
add_keyword_to_embedding_model(EMBEDDING_KEYWORD_FILE)
|
||||
|
||||
# input_model_name = ""
|
||||
# output_model_path = ""
|
||||
# # 以下为加入关键字前后tokenizer的测试用例对比
|
||||
# def print_token_ids(output, tokenizer, sentences):
|
||||
# for idx, ids in enumerate(output['input_ids']):
|
||||
# print(f'sentence={sentences[idx]}')
|
||||
# print(f'ids={ids}')
|
||||
# for id in ids:
|
||||
# decoded_id = tokenizer.decode(id)
|
||||
# print(f' {decoded_id}->{id}')
|
||||
#
|
||||
# sentences = [
|
||||
# '数据科学与大数据技术',
|
||||
# 'Langchain-Chatchat'
|
||||
# ]
|
||||
#
|
||||
# st_no_keywords = SentenceTransformer(input_model_name)
|
||||
# tokenizer_without_keywords = st_no_keywords.tokenizer
|
||||
# print("===== tokenizer with no keywords added =====")
|
||||
# output = tokenizer_without_keywords(sentences)
|
||||
# print_token_ids(output, tokenizer_without_keywords, sentences)
|
||||
# print(f'-------- embedding with no keywords added -----')
|
||||
# embeddings = st_no_keywords.encode(sentences)
|
||||
# print(embeddings)
|
||||
#
|
||||
# print("--------------------------------------------")
|
||||
# print("--------------------------------------------")
|
||||
# print("--------------------------------------------")
|
||||
#
|
||||
# st_with_keywords = SentenceTransformer(output_model_path)
|
||||
# tokenizer_with_keywords = st_with_keywords.tokenizer
|
||||
# print("===== tokenizer with keyword added =====")
|
||||
# output = tokenizer_with_keywords(sentences)
|
||||
# print_token_ids(output, tokenizer_with_keywords, sentences)
|
||||
#
|
||||
# print(f'-------- embedding with keywords added -----')
|
||||
# embeddings = st_with_keywords.encode(sentences)
|
||||
# print(embeddings)
|
||||
BIN
img/qr_code_100.jpg
Normal file
|
After Width: | Height: | Size: 281 KiB |
BIN
img/qr_code_101.jpg
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
img/qr_code_102.jpg
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
img/qr_code_103.jpg
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
img/qr_code_104.jpg
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
img/qr_code_105.jpg
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
img/qr_code_106.jpg
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
img/qr_code_106_2.jpg
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
img/qr_code_107.jpg
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
img/qr_code_108.jpg
Normal file
|
After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 182 KiB |
BIN
img/qr_code_90.jpg
Normal file
|
After Width: | Height: | Size: 273 KiB |
BIN
img/qr_code_90.png
Normal file
|
After Width: | Height: | Size: 439 KiB |
BIN
img/qr_code_91.jpg
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
img/qr_code_92.jpg
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
img/qr_code_93.jpg
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
img/qr_code_94.jpg
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
img/qr_code_95.jpg
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
img/qr_code_96.jpg
Normal file
|
After Width: | Height: | Size: 222 KiB |
BIN
img/qr_code_97.jpg
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
img/qr_code_98.jpg
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
img/qr_code_99.jpg
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
img/qrcode_90_2.jpg
Normal file
|
After Width: | Height: | Size: 232 KiB |
@ -6,7 +6,6 @@ from configs.model_config import NLTK_DATA_PATH, EMBEDDING_MODEL
|
||||
import nltk
|
||||
nltk.data.path = [NLTK_DATA_PATH] + nltk.data.path
|
||||
from datetime import datetime
|
||||
import sys
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@ -50,11 +49,11 @@ if __name__ == "__main__":
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--increament",
|
||||
"--increment",
|
||||
action="store_true",
|
||||
help=('''
|
||||
update vector store for files exist in local folder and not exist in database.
|
||||
use this option if you want to create vectors increamentally.
|
||||
use this option if you want to create vectors incrementally.
|
||||
'''
|
||||
)
|
||||
)
|
||||
@ -100,7 +99,7 @@ if __name__ == "__main__":
|
||||
|
||||
if args.clear_tables:
|
||||
reset_tables()
|
||||
print("database talbes reseted")
|
||||
print("database tables reset")
|
||||
|
||||
if args.recreate_vs:
|
||||
create_tables()
|
||||
@ -110,8 +109,8 @@ if __name__ == "__main__":
|
||||
import_from_db(args.import_db)
|
||||
elif args.update_in_db:
|
||||
folder2db(kb_names=args.kb_name, mode="update_in_db", embed_model=args.embed_model)
|
||||
elif args.increament:
|
||||
folder2db(kb_names=args.kb_name, mode="increament", embed_model=args.embed_model)
|
||||
elif args.increment:
|
||||
folder2db(kb_names=args.kb_name, mode="increment", embed_model=args.embed_model)
|
||||
elif args.prune_db:
|
||||
prune_db_docs(args.kb_name)
|
||||
elif args.prune_folder:
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
- 2. 截至2023年,它是唯一一个提供可工作的DiskANN实现的主要供应商
|
||||
- 3. 支持在向量相似度检索过程中进行标量字段过滤,实现混合查询
|
||||
- 4. 采用 **存储与计算分离** 的架构设计
|
||||
- 5. 提供python,juava,go,node.js等语言SDK,也提供milvus lite等in-momery运行
|
||||
- 5. 提供python,java,go,node.js等语言SDK,也提供milvus lite等in-momery运行
|
||||
- 6. 提供了图形界面客户端
|
||||
- traiditional
|
||||
- ES
|
||||
@ -94,4 +94,4 @@
|
||||
- 它可以适应性地使用检索令牌进行检索,因此模型可以自发判断是不是有必要进行检索。它引入了多种细粒度的批评令牌,这些令牌用于评估生成内容的各个方面的质量。在生成过程中,作者使用期望的批评令牌概率的线性插值进行segment级的beam search,以在每一个时间步骤中确定最佳的K个续写方案
|
||||
- Agent
|
||||
- function call
|
||||
- ToolFormer
|
||||
- ToolFormer
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit f789e5dde10f91136012f3470c020c8d34572436
|
||||
Subproject commit 28f664aa08f8191a70339c9ecbe7a89b35a1032a
|
||||
107
markdown_docs/document_loaders/FilteredCSVloader.md
Normal file
@ -0,0 +1,107 @@
|
||||
## ClassDef FilteredCSVLoader
|
||||
**FilteredCSVLoader**: FilteredCSVLoader的功能是从CSV文件中加载并筛选指定列的数据,然后将这些数据转换为文档对象列表。
|
||||
|
||||
**属性**:
|
||||
- `file_path`: 要加载的CSV文件的路径。
|
||||
- `columns_to_read`: 需要读取的列名列表。
|
||||
- `source_column`: 指定作为数据源信息列的列名,如果未指定,则使用文件路径作为数据源信息。
|
||||
- `metadata_columns`: 需要作为元数据读取的列名列表。
|
||||
- `csv_args`: 传递给csv阅读器的额外参数字典。
|
||||
- `encoding`: 文件的编码格式。
|
||||
- `autodetect_encoding`: 是否自动检测文件编码。
|
||||
|
||||
**代码描述**:
|
||||
FilteredCSVLoader类继承自CSVLoader类,用于从CSV文件中加载数据,并根据指定的列名筛选数据。它重写了`__init__`方法以接收额外的参数,如`columns_to_read`,这是一个字符串列表,指定了需要从CSV文件中读取的列名。此外,它还提供了`load`方法来实际加载和处理CSV文件。
|
||||
|
||||
在`load`方法中,首先尝试打开指定的CSV文件。如果在读取文件时遇到`UnicodeDecodeError`错误,并且`autodetect_encoding`标志被设置为True,则会尝试自动检测文件编码并重新尝试读取文件。读取文件成功后,使用`csv.DictReader`读取CSV文件,根据`columns_to_read`中指定的列名筛选数据,并将筛选后的数据转换为文档对象列表。每个文档对象包含从指定列读取的内容和元数据,元数据中包含数据源信息和行号,以及`metadata_columns`中指定的任何其他元数据列的值。
|
||||
|
||||
**注意**:
|
||||
- 确保`file_path`指向的CSV文件存在且可读。
|
||||
- 在`columns_to_read`中指定的列必须存在于CSV文件中,否则会抛出`ValueError`。
|
||||
- 如果设置了`autodetect_encoding`为True,但自动检测编码失败,则会抛出`RuntimeError`。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
Document(page_content="这是第一行的内容", metadata={"source": "example.csv", "row": 0, "其他元数据列名": "值"}),
|
||||
Document(page_content="这是第二行的内容", metadata={"source": "example.csv", "row": 1, "其他元数据列名": "值"}),
|
||||
...
|
||||
]
|
||||
```
|
||||
此输出示例展示了`load`方法返回的文档对象列表,每个文档对象包含从CSV文件指定列读取的内容和元数据。
|
||||
### FunctionDef __init__(self, file_path, columns_to_read, source_column, metadata_columns, csv_args, encoding, autodetect_encoding)
|
||||
**__init__**: 此函数的功能是初始化FilteredCSVLoader对象。
|
||||
|
||||
**参数**:
|
||||
- `file_path`: 要读取的CSV文件的路径。
|
||||
- `columns_to_read`: 需要读取的列名列表。
|
||||
- `source_column`: 指定作为数据源的列名,可选参数,默认为None。
|
||||
- `metadata_columns`: 包含元数据的列名列表,默认为空列表。
|
||||
- `csv_args`: 传递给CSV读取器的额外参数,为字典格式,可选参数,默认为None。
|
||||
- `encoding`: 指定文件编码的字符串,可选参数,默认为None。
|
||||
- `autodetect_encoding`: 是否自动检测文件编码,布尔值,默认为False。
|
||||
|
||||
**代码描述**:
|
||||
此函数是`FilteredCSVLoader`类的构造函数,用于初始化一个`FilteredCSVLoader`实例。它首先调用父类的构造函数,传入`file_path`、`source_column`、`metadata_columns`、`csv_args`、`encoding`和`autodetect_encoding`参数,以完成基础的初始化工作。然后,它将`columns_to_read`参数的值赋给实例变量`self.columns_to_read`,以便后续操作中可以根据这些列名来读取CSV文件中的指定列。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,`file_path`和`columns_to_read`参数是必需的,因为它们分别指定了CSV文件的位置和需要读取的列。
|
||||
- `metadata_columns`参数允许用户指定哪些列包含元数据,这些元数据列不会被视为数据源的一部分。
|
||||
- 如果`csv_args`参数被提供,它将允许用户自定义CSV读取过程中的行为,例如指定分隔符、引号字符等。
|
||||
- `encoding`和`autodetect_encoding`参数与文件编码相关,如果CSV文件的编码不是标准的UTF-8,这两个参数将非常有用。`autodetect_encoding`为True时,系统将尝试自动检测文件编码,这可能有助于处理编码不明确的文件。
|
||||
***
|
||||
### FunctionDef load(self)
|
||||
**load**: 该函数的功能是加载数据并将其转换为文档对象列表。
|
||||
|
||||
**参数**: 该函数不接受任何外部参数,但依赖于类实例中的属性,如`file_path`和`encoding`。
|
||||
|
||||
**代码描述**: `load`函数负责从CSV文件中读取数据,并将这些数据转换为`Document`对象的列表。首先,函数尝试使用`open`函数以指定的编码方式打开文件路径`self.file_path`指定的CSV文件。文件成功打开后,调用`__read_file`私有方法来读取并处理CSV文件的内容。
|
||||
|
||||
如果在尝试打开文件时遇到`UnicodeDecodeError`编码错误,并且`self.autodetect_encoding`属性为真,则会尝试自动检测文件编码。这一过程通过调用`detect_file_encodings`函数实现,该函数返回一个可能的编码列表。然后,函数会尝试使用这些编码中的每一个重新打开并读取文件,直到成功读取文件或尝试完所有编码。
|
||||
|
||||
如果在文件处理过程中遇到任何其他异常,或者在自动检测编码后仍无法成功读取文件,`load`函数将抛出`RuntimeError`异常,指示文件加载过程中出现错误。
|
||||
|
||||
`load`函数调用的`__read_file`方法负责实际从CSV文件中读取数据,并将每行数据转换为`Document`对象。这一转换过程包括从CSV行中提取必要的内容和元数据,并将它们封装在`Document`对象中。
|
||||
|
||||
**注意**:
|
||||
- `load`函数依赖于类实例的状态,如文件路径和编码设置,因此在调用此函数之前应确保这些属性已正确设置。
|
||||
- 如果CSV文件的编码不是在初始化时指定的编码,并且未启用自动检测编码功能,那么读取文件可能会失败。
|
||||
- 当CSV文件中缺少必需的列或格式不正确时,`__read_file`方法可能会抛出`ValueError`异常。
|
||||
|
||||
**输出示例**: 假设CSV文件正确读取并处理,`load`函数可能返回如下的`Document`对象列表:
|
||||
```python
|
||||
[
|
||||
Document(page_content="示例文本1", metadata={"source": "path/to/file.csv", "row": 0, "其他元数据": "值"}),
|
||||
Document(page_content="示例文本2", metadata={"source": "path/to/file.csv", "row": 1, "其他元数据": "值"})
|
||||
]
|
||||
```
|
||||
此列表中的每个`Document`对象包含从CSV文件中读取的一行数据,其中`page_content`属性存储了该行指定列的内容,而`metadata`字典包含了源信息以及其他可能的元数据信息。
|
||||
***
|
||||
### FunctionDef __read_file(self, csvfile)
|
||||
**__read_file**: 该函数的功能是从CSV文件中读取数据,并将其转换为Document对象列表。
|
||||
|
||||
**参数**:
|
||||
- csvfile: TextIOWrapper类型,表示打开的CSV文件对象。
|
||||
|
||||
**代码描述**:
|
||||
`__read_file`函数是`FilteredCSVLoader`类的一个私有方法,用于读取CSV文件并将每行数据转换为`Document`对象。该函数首先创建一个空列表`docs`来存储转换后的`Document`对象。接着,使用`csv.DictReader`读取`csvfile`参数指定的CSV文件,其中`self.csv_args`包含了读取CSV文件时需要的参数设置。
|
||||
|
||||
对于CSV文件中的每一行,函数首先检查是否包含必需的列(由`self.columns_to_read[0]`指定)。如果该列存在,则从该列中提取内容作为`Document`对象的`page_content`。同时,尝试从行中获取源信息(由`self.source_column`指定),如果未指定`self.source_column`或该列不存在,则使用文件路径作为源信息。此外,还会从行中提取其他元数据列(由`self.metadata_columns`指定),并将这些信息一起存储在`metadata`字典中。
|
||||
|
||||
最后,使用提取的内容和元数据创建一个`Document`对象,并将其添加到`docs`列表中。如果在CSV文件中找不到必需的列,则抛出`ValueError`异常。
|
||||
|
||||
该函数被`FilteredCSVLoader`类的`load`方法调用,用于加载CSV文件并将其内容转换为一系列`Document`对象。`load`方法首先尝试以指定的编码打开文件,如果遇到编码错误且自动检测编码功能被启用,则尝试使用检测到的编码重新打开文件。如果在整个过程中遇到任何异常,`load`方法会抛出`RuntimeError`异常。
|
||||
|
||||
**注意**:
|
||||
- 由于`__read_file`是一个私有方法,因此它仅在`FilteredCSVLoader`类内部使用,不应直接从类外部调用。
|
||||
- 当CSV文件中缺少必需的列时,该函数会抛出`ValueError`异常。
|
||||
|
||||
**输出示例**:
|
||||
假设CSV文件包含以下内容,并且`columns_to_read`设置为`['content']`,`metadata_columns`设置为空列表,那么函数可能返回如下的`Document`对象列表:
|
||||
```python
|
||||
[
|
||||
Document(page_content="Hello, world!", metadata={"source": "path/to/file.csv", "row": 0}),
|
||||
Document(page_content="Another example.", metadata={"source": "path/to/file.csv", "row": 1})
|
||||
]
|
||||
```
|
||||
***
|
||||
106
markdown_docs/document_loaders/mydocloader.md
Normal file
@ -0,0 +1,106 @@
|
||||
## ClassDef RapidOCRDocLoader
|
||||
**RapidOCRDocLoader**: RapidOCRDocLoader的功能是从Word文档中提取文本和图片内容,并使用OCR技术转换图片中的文本。
|
||||
|
||||
**属性**:
|
||||
- 无特定公开属性,此类主要通过继承和方法实现功能。
|
||||
|
||||
**代码描述**:
|
||||
RapidOCRDocLoader类继承自UnstructuredFileLoader,专门用于处理Word文档(.docx)文件,提取其中的文本和图片内容。它通过定义一个内部函数`_get_elements`来实现这一功能。该函数首先定义了一个辅助函数`doc2text`,用于打开和解析Word文档,然后提取文档中的文本和图片内容。
|
||||
|
||||
在`doc2text`函数中,使用了python-docx库来遍历文档中的所有段落和表格。对于文档中的每个段落,直接提取其文本内容;对于表格,遍历每个单元格并提取其中的文本。此外,对于段落中包含的图片,使用了PIL库和RapidOCR库来识别图片中的文本。
|
||||
|
||||
RapidOCR是一个基于ONNX Runtime的OCR工具,能够从图片中识别文本。在本类中,对于每个找到的图片,首先将其转换为numpy数组,然后使用RapidOCR进行文本识别,最后将识别的文本添加到响应字符串中。
|
||||
|
||||
最终,`_get_elements`函数通过调用`doc2text`函数获取文档中的所有文本(包括OCR识别的文本),然后使用`partition_text`函数对文本进行分段处理,返回处理后的文本列表。
|
||||
|
||||
**注意**:
|
||||
- 使用RapidOCRDocLoader类之前,需要确保已安装python-docx、PIL、numpy和rapidocr_onnxruntime等依赖库。
|
||||
- 该类专门处理.docx格式的Word文档,不适用于其他类型的文档或图片文件。
|
||||
- OCR识别准确度受到图片质量的影响,对于低分辨率或图文混排的图片,识别结果可能不理想。
|
||||
|
||||
**输出示例**:
|
||||
假设一个Word文档包含以下内容:
|
||||
- 文本段落:“这是一个示例文档。”
|
||||
- 包含文本的图片:图片中的文本为“图片中的示例文本”。
|
||||
|
||||
使用RapidOCRDocLoader处理该文档后,可能的返回值为:
|
||||
```
|
||||
["这是一个示例文档。", "图片中的示例文本。"]
|
||||
```
|
||||
这个返回值是一个列表,包含了文档中所有文本内容,包括通过OCR技术识别出的图片中的文本。
|
||||
### FunctionDef _get_elements(self)
|
||||
**_get_elements**: 此函数的功能是从给定的Word文档中提取文本和图片内容,并将图片内容通过OCR技术转换为文本,最后将所有文本内容进行结构化分割。
|
||||
|
||||
**参数**: 此函数没有显式参数,但依赖于`self.file_path`和`self.unstructured_kwargs`两个对象属性。
|
||||
- `self.file_path`: 需要处理的Word文档的路径。
|
||||
- `self.unstructured_kwargs`: 用于文本结构化分割的参数。
|
||||
|
||||
**代码描述**:
|
||||
1. `_get_elements`函数首先定义了一个内部函数`doc2text`,用于将Word文档转换为文本。
|
||||
2. `doc2text`函数利用`python-docx`库来解析Word文档,通过迭代文档中的段落和表格来提取文本内容。
|
||||
3. 对于文档中的图片,`doc2text`使用`xpath`来定位,并通过`PIL`库和`ImagePart`来读取图片内容。然后,使用`RapidOCR`库将图片内容转换为文本。
|
||||
4. 文档中的文本和通过OCR转换得到的文本被累加到一个字符串中。
|
||||
5. 使用`tqdm`库来显示处理进度,提高用户体验。
|
||||
6. `_get_elements`函数通过调用`doc2text`函数获取文本内容,然后使用`partition_text`函数对文本进行结构化分割,分割依据是`self.unstructured_kwargs`中的参数。
|
||||
7. 最终,函数返回一个包含分割后文本块的列表。
|
||||
|
||||
**注意**:
|
||||
- 确保`self.file_path`指向的是一个有效的Word文档路径。
|
||||
- OCR转换对图片质量有一定要求,图片质量过低可能影响识别结果。
|
||||
- `self.unstructured_kwargs`参数需要正确配置以适应不同的文本结构化需求。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
"这是文档的第一部分文本。",
|
||||
"这是从图片中通过OCR技术识别出的文本。",
|
||||
"这是文档的另一部分文本。"
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数可能返回的分割后的文本块列表,包括直接从Word文档中提取的文本和通过OCR技术从图片中识别出的文本。
|
||||
#### FunctionDef doc2text(filepath)
|
||||
**doc2text**: 该函数的功能是将Word文档中的文本和图片内容转换为纯文本字符串。
|
||||
|
||||
**参数**:
|
||||
- filepath: Word文档的文件路径。
|
||||
|
||||
**代码描述**:
|
||||
`doc2text`函数首先导入了必要的库和模块,包括处理Word文档的`docx`库,图像处理库`PIL`,以及用于执行OCR(光学字符识别)的`rapidocr_onnxruntime`库。函数接收一个文件路径作为参数,用于指定需要转换的Word文档。
|
||||
|
||||
函数内部,首先使用`Document`类从给定的文件路径加载Word文档。然后,定义了一个`iter_block_items`内部函数,用于遍历文档中的所有段落和表格。这个遍历过程利用了`docx`库的类型判断功能,以确定当前处理的是段落还是表格,并据此进行相应的处理。
|
||||
|
||||
在遍历文档内容的过程中,函数使用了`ocr`对象(由`RapidOCR`类实例化)对文档中的图片进行OCR处理,将图片中的文本转换为可读的字符串。对于文档中的文本内容,直接将其文本值添加到响应字符串中。
|
||||
|
||||
此外,函数还处理了文档中的表格,遍历每个表格中的行和单元格,将单元格中的文本内容提取出来,同样添加到响应字符串中。
|
||||
|
||||
最后,函数返回一个包含了文档中所有文本内容和图片中识别出的文本内容的字符串。
|
||||
|
||||
**注意**:
|
||||
- 该函数依赖于`docx`、`PIL`和`rapidocr_onnxruntime`等库,使用前需要确保这些库已正确安装。
|
||||
- OCR处理可能不会100%准确,特别是对于图像质量较低或字体较小的图片,识别结果可能会有误差。
|
||||
- 函数的性能(包括OCR处理时间)会受到文档大小和内容复杂度的影响。
|
||||
|
||||
**输出示例**:
|
||||
```
|
||||
这是文档中的一段文本。
|
||||
|
||||
这是从文档中的一张图片中识别出的文本。
|
||||
```
|
||||
##### FunctionDef iter_block_items(parent)
|
||||
**iter_block_items**: 此函数的功能是遍历并生成文档中的段落和表格对象。
|
||||
|
||||
**参数**:
|
||||
- **parent**: 可以是`Document`对象或`_Cell`对象,表示要遍历的文档或单元格。
|
||||
|
||||
**代码描述**:
|
||||
`iter_block_items`函数是用于从Word文档中提取段落和表格的迭代器。它首先判断传入的`parent`参数类型。如果`parent`是`Document`类型,即整个文档,它会获取文档的主体部分。如果`parent`是`_Cell`类型,即表格中的单元格,它会获取该单元格的内容。函数通过遍历`parent_elm`的子元素,根据子元素的类型(段落或表格),生成对应的`Paragraph`或`Table`对象并返回。
|
||||
|
||||
在遍历过程中,使用`isinstance`函数检查每个子元素的类型。如果子元素是`CT_P`类型,表示它是一个段落,则创建并返回一个`Paragraph`对象。如果子元素是`CT_Tbl`类型,表示它是一个表格,则创建并返回一个`Table`对象。这样,使用此函数可以方便地从文档中提取出所有的段落和表格,以便进一步处理。
|
||||
|
||||
**注意**:
|
||||
- 传入的`parent`参数必须是`Document`或`_Cell`类型,否则函数会抛出`ValueError`异常,提示"RapidOCRDocLoader parse fail"。
|
||||
- 此函数依赖于`docx.document.Document`、`_Cell`、`CT_P`(段落类型)和`CT_Tbl`(表格类型)等类,因此在使用前需要确保这些类已正确导入和定义。
|
||||
- 生成的`Paragraph`和`Table`对象可以用于进一步的文本提取或格式化操作,但需要注意处理它们的方法可能依赖于具体的实现细节。
|
||||
***
|
||||
***
|
||||
***
|
||||
71
markdown_docs/document_loaders/myimgloader.md
Normal file
@ -0,0 +1,71 @@
|
||||
## ClassDef RapidOCRLoader
|
||||
**RapidOCRLoader**: RapidOCRLoader的功能是将图像文件中的文本通过OCR技术提取出来,并将提取的文本进行结构化处理。
|
||||
|
||||
**属性**:
|
||||
- 无特定公开属性,继承自UnstructuredFileLoader的属性。
|
||||
|
||||
**代码描述**:
|
||||
RapidOCRLoader是一个继承自UnstructuredFileLoader的类,专门用于处理图像文件中的文本提取。它通过定义一个内部函数`img2text`来实现OCR(光学字符识别)功能。`img2text`函数接受一个文件路径作为输入,使用`get_ocr`函数获取OCR处理器,然后对指定的图像文件进行文本识别。识别结果是一个列表,其中每个元素包含识别的文本行。这些文本行随后被连接成一个字符串,作为函数的返回值。
|
||||
|
||||
在`_get_elements`方法中,调用了`img2text`函数处理类初始化时指定的文件路径,将图像文件中的文本提取出来。提取出的文本随后通过`partition_text`函数进行结构化处理,这个函数根据提供的参数(通过`self.unstructured_kwargs`传递)对文本进行分区,最终返回一个文本分区列表。
|
||||
|
||||
在项目中,RapidOCRLoader类被用于测试模块`test_imgloader.py`中,通过`test_rapidocrloader`函数进行测试。测试函数创建了一个RapidOCRLoader实例,传入了一个OCR测试用的图像文件路径,然后调用`load`方法加载处理结果。测试验证了RapidOCRLoader能够成功提取图像中的文本,并且返回值是一个包含至少一个元素的列表,列表中的每个元素都是一个包含提取文本的对象。
|
||||
|
||||
**注意**:
|
||||
- 使用RapidOCRLoader之前,需要确保OCR处理器(通过`get_ocr`函数获取)已正确配置并可用。
|
||||
- 该类主要用于处理图像文件中的文本提取,不适用于非图像文件。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
{
|
||||
"page_content": "这是通过OCR技术提取的文本内容。"
|
||||
}
|
||||
]
|
||||
```
|
||||
此输出示例展示了RapidOCRLoader处理图像文件并通过OCR技术提取文本后的可能返回值。返回值是一个列表,列表中的每个元素都是一个字典,其中`page_content`键对应的值是提取的文本内容。
|
||||
### FunctionDef _get_elements(self)
|
||||
**_get_elements**: 该函数的功能是将图片文件中的文本内容提取出来,并根据给定的参数对提取出的文本进行分段处理。
|
||||
|
||||
**参数**:
|
||||
- 无直接参数,但函数通过`self.file_path`访问图片路径,通过`self.unstructured_kwargs`访问用于文本分段的参数。
|
||||
|
||||
**代码描述**:
|
||||
该函数首先定义了一个内部函数`img2text`,用于将指定路径的图片文件转换为文本。`img2text`函数通过调用`get_ocr()`函数获取OCR(光学字符识别)服务的实例,然后使用此实例对图片文件进行识别,将识别结果中的文本内容提取出来并返回。
|
||||
|
||||
在`_get_elements`函数的主体中,首先调用`img2text`函数,将`self.file_path`指定的图片文件转换为文本。然后,使用`partition_text`函数对提取的文本进行分段处理。`partition_text`函数接受一个文本字符串和一组分段参数(通过`self.unstructured_kwargs`提供),并返回分段后的文本列表。
|
||||
|
||||
**注意**:
|
||||
- 确保`self.file_path`正确指向了需要处理的图片文件。
|
||||
- `self.unstructured_kwargs`应包含适用于`partition_text`函数的所有必要参数,以确保文本可以按预期进行分段处理。
|
||||
- OCR识别的准确性可能受到图片质量和内容复杂度的影响,因此在处理极其复杂或低质量的图片时可能会遇到识别准确度下降的问题。
|
||||
|
||||
**输出示例**:
|
||||
假设图片中包含以下文本内容:“Hello World! Welcome to OCR processing.”,并且`partition_text`函数的参数设置为按句子分段,那么该函数可能返回如下列表:
|
||||
```python
|
||||
["Hello World!", "Welcome to OCR processing."]
|
||||
```
|
||||
#### FunctionDef img2text(filepath)
|
||||
**img2text**: 此函数的功能是将图片文件中的文字通过OCR技术识别出来,并以字符串形式返回。
|
||||
|
||||
**参数**:
|
||||
- filepath: 字符串类型,指定需要进行文字识别的图片文件路径。
|
||||
|
||||
**代码描述**:
|
||||
`img2text`函数是一个用于图像文字识别的高级封装。它首先调用`get_ocr`函数获取一个OCR对象,该对象是根据系统配置(是否使用CUDA加速)动态选择的OCR实现。随后,使用该OCR对象对传入的图片文件路径`filepath`指向的图片进行文字识别。识别结果是一个列表,其中每个元素是一个包含识别区域坐标和识别出的文字的元组。函数进一步处理这个列表,提取出所有识别到的文字,并将它们连接成一个单一的字符串,每行文字之间用换行符`\n`分隔。最后,返回这个字符串。
|
||||
|
||||
从功能角度看,`img2text`与其调用的`get_ocr`函数紧密相关。`get_ocr`负责提供OCR服务的对象,而`img2text`则利用这个对象完成具体的图像文字识别任务。这种设计使得`img2text`能够灵活适应不同的OCR技术实现,同时也便于在项目中重用OCR服务。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`filepath`是有效的图片文件路径,且文件存在。否则,OCR识别过程可能失败。
|
||||
- OCR识别的准确性受到多种因素的影响,包括图片质量、文字清晰度和字体大小等,因此在使用时应考虑这些因素可能对识别结果的影响。
|
||||
- 根据`get_ocr`函数的说明,如果系统中未安装支持CUDA的OCR包或在不支持CUDA的环境中运行,应确保`get_ocr`函数的`use_cuda`参数被设置为False,以避免运行时错误。
|
||||
|
||||
**输出示例**:
|
||||
```
|
||||
这是一个OCR识别的示例文本。
|
||||
第二行文字。
|
||||
```
|
||||
此输出示例展示了`img2text`函数处理后的可能输出,其中包含了从图片中识别出的文字,每行文字之间用换行符分隔。实际输出将根据输入图片中的文字内容而有所不同。
|
||||
***
|
||||
***
|
||||
89
markdown_docs/document_loaders/mypdfloader.md
Normal file
@ -0,0 +1,89 @@
|
||||
## ClassDef RapidOCRPDFLoader
|
||||
**RapidOCRPDFLoader**: RapidOCRPDFLoader的功能是从PDF文件中提取文本和图片内容,并通过OCR技术将图片内容转换为文本。
|
||||
|
||||
**属性**:
|
||||
- 无特定公开属性,该类主要通过方法实现功能。
|
||||
|
||||
**代码描述**:
|
||||
RapidOCRPDFLoader类继承自UnstructuredFileLoader,专门用于处理PDF文件的加载和内容提取。该类通过定义的`_get_elements`方法实现了从PDF中提取文本和图片的功能,并且能够处理图片的旋转和OCR识别,最终将识别的文本内容进行结构化处理。
|
||||
|
||||
在`_get_elements`方法中,首先定义了`rotate_img`函数用于处理图片旋转,接着定义了`pdf2text`函数用于将PDF文件中的文本和图片内容提取出来。`pdf2text`函数使用了fitz库(pyMuPDF)来打开和处理PDF文件,通过遍历每一页,提取页面文本和图片信息。对于图片内容,首先检查图片尺寸是否超过设定的阈值,然后根据页面的旋转角度决定是否需要旋转图片,最后使用OCR技术将图片内容转换为文本。
|
||||
|
||||
该类的使用场景在于需要从PDF文件中提取文本信息,同时也需要处理PDF中的图片内容,尤其是当图片中包含了重要的文本信息时。通过OCR技术,可以将这些图片中的文本信息转换为可读的文本格式,进一步增强文本提取的准确性和完整性。
|
||||
|
||||
**注意**:
|
||||
- 使用RapidOCRPDFLoader类之前,需要确保已经安装了fitz(pyMuPDF)库和OpenCV库,因为这两个库是处理PDF文件和图片旋转的关键。
|
||||
- OCR技术的准确性受到图片质量的影响,因此在处理高度压缩或质量较低的图片时,OCR的结果可能不够理想。
|
||||
- 该类在处理大型PDF文件时可能会消耗较多的计算资源,因此在资源受限的环境下使用时需要注意。
|
||||
|
||||
**输出示例**:
|
||||
假设处理一个包含文本和图片的PDF文件,RapidOCRPDFLoader可能会返回如下格式的文本内容:
|
||||
```
|
||||
第一页文本内容...
|
||||
图片1识别的文本内容...
|
||||
图片2识别的文本内容...
|
||||
第二页文本内容...
|
||||
图片3识别的文本内容...
|
||||
...
|
||||
```
|
||||
这个输出示例展示了RapidOCRPDFLoader如何将PDF文件中的文本和图片内容结合起来,提供一个连续的文本流,便于后续的处理和分析。
|
||||
### FunctionDef _get_elements(self)
|
||||
**_get_elements**: 该函数的功能是从PDF文件中提取文本和图像内容,并对图像进行OCR识别,最后将识别的文本内容进行结构化处理。
|
||||
|
||||
**参数**: 此函数没有直接的参数,它通过类的实例访问成员变量。
|
||||
|
||||
**代码描述**:
|
||||
- `_get_elements` 函数首先定义了两个内部函数:`rotate_img` 和 `pdf2text`。
|
||||
- `rotate_img` 函数用于旋转图像,接受图像和旋转角度作为参数,返回旋转后的图像。它通过OpenCV库计算旋转矩阵,并应用于输入图像以获得旋转后的图像。
|
||||
- `pdf2text` 函数负责将PDF文件的内容转换为文本。它使用`fitz`库(即PyMuPDF)打开PDF文件,遍历每一页,提取文本内容,并使用进度条(`tqdm`库)显示处理进度。对于每个页面上的图像,如果图像的尺寸超过了设定的阈值(`PDF_OCR_THRESHOLD`),则使用OCR(光学字符识别)技术识别图像中的文本。如果页面有旋转,则先对图像进行旋转校正,再进行OCR识别。
|
||||
- 在提取完所有页面的文本和图像内容后,`_get_elements` 函数使用`partition_text`函数对提取到的文本进行结构化处理,以便于后续的数据处理和分析。
|
||||
|
||||
**注意**:
|
||||
- 本函数依赖于OpenCV和PyMuPDF库进行图像处理和PDF文件的读取,需要确保这些库已正确安装和配置。
|
||||
- OCR识别的准确性受到图像质量的影响,图像的清晰度和旋转校正的准确性对识别结果有重要影响。
|
||||
- 函数中使用的`PDF_OCR_THRESHOLD`变量需要根据实际情况进行调整,以优化OCR识别的效果和性能。
|
||||
|
||||
**输出示例**:
|
||||
由于`_get_elements`函数的输出依赖于输入的PDF文件内容和OCR识别的结果,因此无法提供一个固定的输出示例。通常,该函数会返回一个包含结构化文本内容的列表,列表中的每个元素代表PDF中的一段文本内容,这些内容已经过OCR识别和结构化处理。
|
||||
#### FunctionDef rotate_img(img, angle)
|
||||
**rotate_img**: 该函数的功能是旋转图像。
|
||||
|
||||
**参数**:
|
||||
- img: 待旋转的图像。
|
||||
- angle: 旋转角度,正值表示逆时针旋转,负值表示顺时针旋转。
|
||||
|
||||
**代码描述**:
|
||||
`rotate_img` 函数接收一个图像和一个旋转角度作为输入,返回旋转后的图像。首先,它计算图像的高度和宽度,然后确定旋转中心,即图像的中心点。接着,使用 `cv2.getRotationMatrix2D` 方法获取旋转矩阵,该方法需要旋转中心、旋转角度和缩放比例(本例中为1.0,表示保持原始大小)作为输入。然后,计算旋转后图像的新边界,以确保旋转后的图像不会丢失任何部分。最后,通过调整旋转矩阵中的平移参数,使用 `cv2.warpAffine` 方法应用旋转矩阵,得到旋转后的图像并返回。
|
||||
|
||||
在项目中,`rotate_img` 函数被 `pdf2text` 函数调用,用于处理PDF文档中的图像。当PDF页面有旋转角度时,`pdf2text` 函数会提取页面中的图像,然后调用 `rotate_img` 函数将图像旋转回正常的方向,以便进行后续的OCR(光学字符识别)处理。这样可以确保OCR处理的准确性,特别是在处理扫描文档和图像密集型PDF文件时。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `cv2.getRotationMatrix2D` 和 `cv2.warpAffine` 方法时,需要确保已经导入了OpenCV库(即cv2)。
|
||||
- 旋转图像可能会导致图像边缘的一部分被裁剪。因此,计算新边界并调整平移参数是确保图像完整性的关键步骤。
|
||||
|
||||
**输出示例**:
|
||||
假设有一个图像 `img` 和旋转角度 `angle=90`,调用 `rotate_img(img, 90)` 后,将返回一个新的图像,其中原始图像已经逆时针旋转了90度。
|
||||
***
|
||||
#### FunctionDef pdf2text(filepath)
|
||||
**pdf2text**: 该函数的功能是将PDF文件中的文本和图片内容转换为文本格式。
|
||||
|
||||
**参数**:
|
||||
- filepath: PDF文件的路径。
|
||||
|
||||
**代码描述**:
|
||||
`pdf2text` 函数首先导入必要的库,包括`fitz`(用于处理PDF文件)和`numpy`(用于处理图像数据)。然后,它调用`get_ocr`函数获取OCR对象,用于后续的图像文字识别。通过打开指定路径的PDF文件,函数遍历每一页,使用`fitz`库提取页面上的文本内容,并将其累加到响应字符串中。
|
||||
|
||||
对于每个页面上的图像,函数通过`get_image_info`方法获取图像信息,并检查每个图像的尺寸是否超过预设的阈值(`PDF_OCR_THRESHOLD`)。如果图像尺寸合适,函数将使用`fitz.Pixmap`读取图像数据。如果页面有旋转角度,函数会调用`rotate_img`函数将图像旋转回正常方向,以确保OCR的准确性。随后,使用OCR对象对图像进行文字识别,并将识别结果添加到响应字符串中。
|
||||
|
||||
整个过程中,使用`tqdm`库显示处理进度,为用户提供友好的进度反馈。
|
||||
|
||||
**注意**:
|
||||
- 确保安装了`fitz`(也就是`PyMuPDF`)、`numpy`、`tqdm`等库。
|
||||
- `PDF_OCR_THRESHOLD`是一个预设的阈值,用于决定哪些图像需要进行OCR处理。该阈值需要根据实际情况进行调整。
|
||||
- 函数依赖于`get_ocr`和`rotate_img`两个函数,确保这些依赖函数正确实现并可用。
|
||||
- 由于OCR处理可能耗时,对于包含大量图像的PDF文件,执行该函数可能需要较长时间。
|
||||
|
||||
**输出示例**:
|
||||
调用`pdf2text(filepath)`函数后,将返回一个字符串,其中包含了PDF文件中所有页面的文本内容,以及通过OCR识别的图像中的文字。例如,如果PDF文件包含了文本“欢迎使用OCR”和一张包含文字“图像识别” 的图片,函数将返回一个包含“欢迎使用OCR\n图像识别” 的字符串。
|
||||
***
|
||||
***
|
||||
93
markdown_docs/document_loaders/mypptloader.md
Normal file
@ -0,0 +1,93 @@
|
||||
## ClassDef RapidOCRPPTLoader
|
||||
**RapidOCRPPTLoader**: RapidOCRPPTLoader的功能是从PowerPoint文件中提取文本和图片内容,并使用OCR技术转换图片中的文本。
|
||||
|
||||
**属性**:
|
||||
- 无特定公开属性,此类主要通过方法实现功能。
|
||||
|
||||
**代码描述**:
|
||||
RapidOCRPPTLoader类继承自UnstructuredFileLoader,专门用于处理PowerPoint文件(.pptx)。它通过内部定义的`_get_elements`方法实现主要功能。该方法首先定义了一个内部函数`ppt2text`,用于将PowerPoint文件中的文本和图片内容提取出来。`ppt2text`函数使用了`python-pptx`库来读取PowerPoint文件,`PIL`库处理图片,以及`rapidocr_onnxruntime`库来执行图片中的文字识别(OCR)。
|
||||
|
||||
在提取过程中,`ppt2text`函数会遍历所有幻灯片,并对每个幻灯片中的形状(包括文本框、表格、图片和组合形状)进行处理。对于文本框和表格,直接提取文本内容;对于图片,使用RapidOCR进行文字识别;对于组合形状,递归地对其子形状进行相同的处理。所有提取的文本内容将被拼接成一个字符串。
|
||||
|
||||
最后,`_get_elements`方法使用`partition_text`函数(来自`unstructured.partition.text`模块)对提取的文本进行分段处理,返回一个分段后的文本列表,以便后续处理。
|
||||
|
||||
**注意**:
|
||||
- 使用RapidOCRPPTLoader之前,需要确保安装了`python-pptx`、`PIL`、`numpy`、`tqdm`和`rapidocr_onnxruntime`等依赖库。
|
||||
- OCR技术的准确性受到图片质量的影响,因此在图片质量较低的情况下,文字识别的准确率可能会下降。
|
||||
- 由于OCR处理可能耗时较长,特别是在处理包含大量图片的PowerPoint文件时,应考虑执行时间和资源消耗。
|
||||
|
||||
**输出示例**:
|
||||
由于RapidOCRPPTLoader的输出依赖于输入的PowerPoint文件内容,因此无法提供一个固定的输出示例。一般而言,如果输入的PowerPoint文件包含文本和图片,输出将是一个包含提取文本(包括图片中识别的文字)的字符串列表。每个列表项代表PowerPoint中的一段文本内容。
|
||||
### FunctionDef _get_elements(self)
|
||||
**_get_elements**: 该函数的功能是从PPT文件中提取文本和图片内容,并将图片内容通过OCR技术转换为文本。
|
||||
|
||||
**参数**: 该函数没有显式参数,它是一个对象的方法,依赖于对象的状态。
|
||||
|
||||
**代码描述**:
|
||||
- `_get_elements` 方法首先定义了一个内部函数 `ppt2text`,该函数负责打开并读取PPT文件的内容。
|
||||
- 使用 `pptx.Presentation` 加载PPT文件,遍历每一页幻灯片。
|
||||
- 对于幻灯片中的每个元素,根据其类型(文本框、表格、图片、组合),采取不同的处理方式来提取文本。
|
||||
- 文本框和表格中的文本直接提取。
|
||||
- 对于图片,使用 `RapidOCR` 进行图像识别,将图片内容转换为文本。
|
||||
- 对于组合类型的元素,递归地调用 `extract_text` 函数,处理组合内的每个子元素。
|
||||
- 使用 `tqdm` 库显示处理进度。
|
||||
- 最后,通过调用 `partition_text` 函数,对提取出的文本进行进一步的处理或分割,具体取决于 `self.unstructured_kwargs` 参数的配置。
|
||||
|
||||
**注意**:
|
||||
- 该方法依赖于外部库 `pptx`、`PIL`、`numpy`、`io` 和 `rapidocr_onnxruntime`,在使用前需要确保这些库已经被安装。
|
||||
- OCR技术的准确性受到图片质量的影响,因此在图片质量较低的情况下,识别出的文本可能会有误差。
|
||||
- `partition_text` 函数的行为和输出取决于 `self.unstructured_kwargs` 参数的配置,这意味着该方法的输出可能会根据不同的配置而有所不同。
|
||||
|
||||
**输出示例**:
|
||||
由于 `_get_elements` 函数的输出依赖于输入的PPT文件内容以及OCR的准确性,因此很难提供一个具体的输出示例。一般而言,输出将是一个文本列表,其中包含了从PPT文件中提取并通过OCR技术转换的文本内容。例如,如果PPT中包含了一张包含文字“欢迎来到AI世界”的图片,那么该方法可能会输出一个包含字符串“欢迎来到AI世界”的列表(假设OCR识别准确)。
|
||||
#### FunctionDef ppt2text(filepath)
|
||||
**ppt2text**: 此函数的功能是将PowerPoint文件中的文本和图片转换为纯文本格式。
|
||||
|
||||
**参数**:
|
||||
- filepath: PowerPoint文件的路径。
|
||||
|
||||
**代码描述**:
|
||||
`ppt2text`函数首先导入必要的库,包括`pptx`用于读取PowerPoint文件,`PIL.Image`用于处理图片,`numpy`用于图片数据处理,`io.BytesIO`用于将字节流转换为文件,以及`rapidocr_onnxruntime.RapidOCR`用于执行OCR(光学字符识别)。
|
||||
|
||||
函数接收一个参数`filepath`,这是要处理的PowerPoint文件的路径。函数内部创建了一个`Presentation`对象来加载PowerPoint文件,并初始化一个空字符串`resp`用于存储最终的文本结果。
|
||||
|
||||
定义了一个内部函数`extract_text`,用于提取PowerPoint中的文本和图片。这个内部函数检查每个形状是否包含文本框、表格或图片,并相应地提取文本。对于图片,使用OCR技术将图片中的文本转换为可读文本。特别地,形状类型13代表图片,形状类型6代表组合。
|
||||
|
||||
使用`tqdm`库创建一个进度条,遍历所有幻灯片,并对每个幻灯片中的形状进行排序,以确保按照从上到下、从左到右的顺序处理形状。对于每个形状,调用`extract_text`函数提取文本。
|
||||
|
||||
最后,函数返回包含所有提取文本的字符串`resp`。
|
||||
|
||||
**注意**:
|
||||
- 确保安装了`python-pptx`、`Pillow`、`numpy`、`tqdm`和`rapidocr_onnxruntime`等依赖库。
|
||||
- OCR准确性受到图片质量的影响,可能无法100%准确识别图片中的文本。
|
||||
- 函数处理大型文件时可能需要较长时间。
|
||||
|
||||
**输出示例**:
|
||||
```
|
||||
"这是第一页的文本内容。
|
||||
这是从第一张图片中识别的文本。
|
||||
这是第二页的文本内容。
|
||||
这是从第二页的表格中提取的文本。"
|
||||
```
|
||||
此输出示例展示了从一个包含文本、图片和表格的PowerPoint文件中提取的文本内容。
|
||||
##### FunctionDef extract_text(shape)
|
||||
**extract_text**: 此函数的功能是从PowerPoint的特定形状中提取文本和图片中的文字。
|
||||
|
||||
**参数**:
|
||||
- shape: 需要从中提取文本的PowerPoint形状对象。
|
||||
|
||||
**代码描述**:
|
||||
`extract_text` 函数是为了从PowerPoint演示文稿中的不同形状(如文本框、表格、图片和组合形状)提取文本信息而设计的。该函数通过递归的方式处理形状,确保即使在组合形状中也能有效提取文本。
|
||||
|
||||
1. 首先,函数检查传入的形状是否有文本框(`has_text_frame`),如果有,则提取其中的文本并去除前后空格,之后添加到响应变量`resp`中。
|
||||
2. 接下来,函数检查形状是否包含表格(`has_table`)。对于表格中的每一行和每一个单元格,函数遍历其文本框中的段落,提取并清理文本,然后添加到`resp`。
|
||||
3. 函数还能处理图片类型的形状(形状类型代码为13)。对于图片,使用OCR(光学字符识别)技术提取图片中的文字。提取的文字结果被添加到`resp`中。
|
||||
4. 对于组合形状(形状类型代码为6),函数递归地调用自身,以提取组合内各个子形状的文本。
|
||||
|
||||
**注意**:
|
||||
- 该函数使用了`nonlocal`关键字声明的`resp`变量来累积提取的文本。这意味着`resp`变量应在函数外部定义,并在调用`extract_text`之前初始化。
|
||||
- 对于图片中的文字提取,函数依赖于OCR技术。因此,需要确保相关的OCR库(如在代码中使用的`ocr`函数)已正确安装并配置。
|
||||
- 形状类型代码(如13代表图片,6代表组合形状)是根据PowerPoint对象模型定义的。了解这些代码有助于理解函数如何区分处理不同类型的形状。
|
||||
***
|
||||
***
|
||||
***
|
||||
17
markdown_docs/document_loaders/ocr.md
Normal file
@ -0,0 +1,17 @@
|
||||
## FunctionDef get_ocr(use_cuda)
|
||||
**get_ocr**: 此函数的功能是获取一个OCR对象,用于执行图像或PDF中的文字识别。
|
||||
|
||||
**参数**:
|
||||
- use_cuda: 布尔值,指定是否使用CUDA加速。默认为True。
|
||||
|
||||
**代码描述**:
|
||||
`get_ocr`函数旨在提供一个灵活的方式来获取文字识别(OCR)的功能对象。它首先尝试从`rapidocr_paddle`模块导入`RapidOCR`类,如果成功,将创建一个`RapidOCR`实例,其中的CUDA加速设置将根据`use_cuda`参数来决定。如果在尝试导入`rapidocr_paddle`时发生`ImportError`异常,表明可能未安装相应的包,函数则会尝试从`rapidocr_onnxruntime`模块导入`RapidOCR`类,并创建一个不指定CUDA加速的`RapidOCR`实例。这种设计使得函数能够在不同的环境配置下灵活工作,即使在缺少某些依赖的情况下也能尽可能地提供OCR服务。
|
||||
|
||||
在项目中,`get_ocr`函数被用于不同的场景来执行OCR任务。例如,在`document_loaders/myimgloader.py`的`img2text`方法中,它被用来将图片文件中的文字识别出来;而在`document_loaders/mypdfloader.py`的`pdf2text`方法中,它被用于识别PDF文件中的文字以及PDF中嵌入图片的文字。这显示了`get_ocr`函数在项目中的多功能性和重要性,它为处理不同类型的文档提供了统一的OCR解决方案。
|
||||
|
||||
**注意**:
|
||||
- 在使用`get_ocr`函数时,需要确保至少安装了`rapidocr_paddle`或`rapidocr_onnxruntime`中的一个包,以便函数能够成功返回一个OCR对象。
|
||||
- 如果计划在没有CUDA支持的环境中使用,应将`use_cuda`参数设置为False,以避免不必要的错误。
|
||||
|
||||
**输出示例**:
|
||||
由于`get_ocr`函数返回的是一个`RapidOCR`对象,因此输出示例将依赖于该对象的具体实现。一般而言,可以预期该对象提供了执行OCR任务的方法,如对图片或PDF中的文字进行识别,并返回识别结果。
|
||||
58
markdown_docs/embeddings/add_embedding_keywords.md
Normal file
@ -0,0 +1,58 @@
|
||||
## FunctionDef get_keyword_embedding(bert_model, tokenizer, key_words)
|
||||
**get_keyword_embedding**: 该函数的功能是获取关键词的嵌入表示。
|
||||
|
||||
**参数**:
|
||||
- **bert_model**: 一个预训练的BERT模型,用于生成嵌入表示。
|
||||
- **tokenizer**: 与BERT模型相匹配的分词器,用于将关键词转换为模型能理解的格式。
|
||||
- **key_words**: 一个字符串列表,包含需要获取嵌入表示的关键词。
|
||||
|
||||
**代码描述**:
|
||||
`get_keyword_embedding`函数首先使用传入的`tokenizer`将关键词列表`key_words`转换为模型能够处理的输入格式。这一步骤包括将关键词转换为对应的输入ID,并对输入进行填充和截断以满足模型的要求。随后,函数从`tokenizer`的输出中提取`input_ids`,并去除每个序列的首尾特殊标记,因为这些标记对于关键词的嵌入表示不是必需的。
|
||||
|
||||
接着,函数利用`bert_model`的`embeddings.word_embeddings`属性,根据`input_ids`获取对应的嵌入表示。由于可能传入多个关键词,函数对所有关键词的嵌入表示进行平均,以获得一个统一的表示形式。
|
||||
|
||||
在项目中,`get_keyword_embedding`函数被`add_keyword_to_model`函数调用,用于将自定义关键词的嵌入表示添加到预训练的BERT模型中。这一过程涉及读取关键词文件,生成关键词的嵌入表示,扩展模型的嵌入层以包含这些新的关键词,最后将修改后的模型保存到指定路径。这使得模型能够理解并有效处理这些新增的关键词,从而提高模型在特定任务上的性能。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`bert_model`和`tokenizer`是匹配的,即它们来源于同一个预训练模型。
|
||||
- 关键词列表`key_words`应该是经过精心挑选的,因为这些关键词将直接影响模型的理解能力和性能。
|
||||
- 在调用此函数之前,应该已经准备好关键词文件,并确保其格式正确。
|
||||
|
||||
**输出示例**:
|
||||
假设传入了两个关键词`["AI", "机器学习"]`,函数可能返回一个形状为`(2, embedding_size)`的张量,其中`embedding_size`是模型嵌入层的维度,表示这两个关键词的平均嵌入表示。
|
||||
## FunctionDef add_keyword_to_model(model_name, keyword_file, output_model_path)
|
||||
**add_keyword_to_model**: 该函数的功能是将自定义关键词添加到预训练的嵌入模型中。
|
||||
|
||||
**参数**:
|
||||
- **model_name**: 字符串类型,默认为`EMBEDDING_MODEL`。指定要使用的预训练嵌入模型的名称。
|
||||
- **keyword_file**: 字符串类型,默认为空字符串。指定包含自定义关键词的文件路径。
|
||||
- **output_model_path**: 字符串类型,可为`None`。指定添加了关键词后的模型保存路径。
|
||||
|
||||
**代码描述**:
|
||||
首先,函数通过读取`keyword_file`文件,将文件中的每一行作为一个关键词添加到`key_words`列表中。接着,使用指定的`model_name`加载一个句子转换器模型(SentenceTransformer模型),并从中提取第一个模块作为词嵌入模型。通过这个词嵌入模型,可以获取到BERT模型及其分词器。
|
||||
|
||||
然后,函数调用`get_keyword_embedding`函数,传入BERT模型、分词器和关键词列表,以获取这些关键词的嵌入表示。接下来,函数将这些新的关键词嵌入添加到BERT模型的嵌入层中。这一步骤包括扩展分词器以包含新的关键词,调整BERT模型的嵌入层大小以适应新增的关键词,并将关键词的嵌入表示直接赋值给模型的嵌入层权重。
|
||||
|
||||
最后,如果提供了`output_model_path`参数,则函数会在该路径下创建必要的目录,并将更新后的词嵌入模型以及BERT模型保存到指定位置。这一过程确保了模型能够在后续的使用中,理解并有效处理这些新增的关键词。
|
||||
|
||||
**注意**:
|
||||
- 确保`keyword_file`文件存在且格式正确,每行应包含一个关键词。
|
||||
- 由于模型的嵌入层大小会根据新增关键词进行调整,因此在添加关键词后,模型的大小可能会增加。
|
||||
- 在保存模型时,会使用`safetensors`格式保存BERT模型,确保模型的兼容性和安全性。
|
||||
- 添加关键词到模型是一个影响模型性能的操作,因此应谨慎选择关键词,并考虑到这些关键词在特定任务上的实际应用价值。
|
||||
## FunctionDef add_keyword_to_embedding_model(path)
|
||||
**add_keyword_to_embedding_model**: 该函数的功能是将自定义关键词添加到指定的嵌入模型中。
|
||||
|
||||
**参数**:
|
||||
- **path**: 字符串类型,默认为`EMBEDDING_KEYWORD_FILE`。指定包含自定义关键词的文件路径。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先通过`os.path.join(path)`获取关键词文件的完整路径。然后,它从配置中读取模型的名称和路径,这些配置通过`MODEL_PATH["embed_model"][EMBEDDING_MODEL]`获得。接着,函数计算模型所在的父目录,并生成一个包含当前时间戳的新模型名称,格式为`EMBEDDING_MODEL_Merge_Keywords_当前时间`,以确保输出模型名称的唯一性。
|
||||
|
||||
接下来,函数调用`add_keyword_to_model`,这是一个重要的调用关系,因为`add_keyword_to_model`负责实际将关键词添加到嵌入模型中。在调用`add_keyword_to_model`时,传入当前使用的模型名称、关键词文件路径以及新模型的保存路径。这一步骤完成了将自定义关键词集成到预训练嵌入模型中的核心功能。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`path`参数指向一个有效的关键词文件,且该文件格式正确,每行包含一个要添加的关键词。
|
||||
- 该函数依赖于`add_keyword_to_model`函数,后者负责实际的关键词添加逻辑,包括读取关键词、更新模型的嵌入层以及保存更新后的模型。因此,了解`add_keyword_to_model`的具体实现对于理解整个关键词添加过程是非常重要的。
|
||||
- 生成的新模型名称包含时间戳,这有助于区分不同时间点生成的模型版本。
|
||||
- 在使用此函数时,应考虑到模型大小可能会因为添加新的关键词而增加,这可能会对模型加载和运行时的性能产生影响。
|
||||
46
markdown_docs/release.md
Normal file
@ -0,0 +1,46 @@
|
||||
## FunctionDef get_latest_tag
|
||||
**get_latest_tag**: 此函数的功能是获取Git仓库中最新的标签。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `get_latest_tag` 函数首先使用 `subprocess.check_output` 方法执行 `git tag` 命令,以获取当前Git仓库中所有的标签。然后,通过对输出结果进行解码(UTF-8)和分割,将其转换成一个标签列表。接下来,使用 `sorted` 函数和一个自定义的排序键,基于标签的版本号(假设遵循 `v主版本号.次版本号.修订号` 的格式)对标签列表进行排序。排序键通过正则表达式 `re.match` 匹配每个标签的版本号,并将其转换为整数元组,以便进行比较。最后,函数返回排序后的最后一个元素,即最新的标签。
|
||||
|
||||
在项目中,`get_latest_tag` 函数被 `main` 函数调用,用于获取当前Git仓库中的最新标签,并在终端中显示。此外,`main` 函数还根据用户的输入决定如何递增版本号,并创建新的标签推送到远程仓库。因此,`get_latest_tag` 函数在自动化版本控制和发布流程中起着关键作用,它确保了版本号的正确递增和新版本标签的生成。
|
||||
|
||||
**注意**: 使用此函数时,需要确保当前环境已安装Git,并且函数调用是在一个Git仓库的根目录下进行的。此外,此函数假定标签遵循 `v主版本号.次版本号.修订号` 的命名约定,如果标签不遵循此格式,可能无法正确排序和识别最新标签。
|
||||
|
||||
**输出示例**: 假设Git仓库中的最新标签为 `v1.2.3`,则函数调用 `get_latest_tag()` 将返回字符串 `"v1.2.3"`。
|
||||
## FunctionDef update_version_number(latest_tag, increment)
|
||||
**update_version_number**: 此函数用于根据最新的Git标签和用户指定的版本号递增规则来更新版本号。
|
||||
|
||||
**参数**:
|
||||
- `latest_tag`: 最新的Git标签,字符串格式,预期为`vX.Y.Z`的形式,其中X、Y、Z分别代表主版本号、次版本号和修订号。
|
||||
- `increment`: 用户指定的版本号递增规则,接受的值为`'X'`、`'Y'`或`'Z'`,分别代表递增主版本号、次版本号或修订号。
|
||||
|
||||
**代码描述**:
|
||||
函数首先通过正则表达式从`latest_tag`中提取出当前的主版本号、次版本号和修订号,并将它们转换为整数。根据`increment`参数的值,函数将相应的版本号部分递增。如果`increment`为`'X'`,则主版本号加一,次版本号和修订号重置为0。如果`increment`为`'Y'`,则次版本号加一,修订号重置为0。如果`increment`为`'Z'`,则修订号加一。最后,函数将更新后的版本号拼接成`vX.Y.Z`的格式并返回。
|
||||
|
||||
此函数在项目中被`main`函数调用。在`main`函数中,首先获取当前最新的Git标签,然后询问用户希望递增哪部分版本号(主版本号、次版本号或修订号)。用户输入后,`update_version_number`函数被调用以生成新的版本号。根据用户的确认,新的版本号可能会被用来创建Git标签并推送到远程仓库。
|
||||
|
||||
**注意**:
|
||||
- 输入的`latest_tag`必须严格遵循`vX.Y.Z`的格式,否则正则表达式匹配将失败,函数将无法正确执行。
|
||||
- `increment`参数仅接受`'X'`、`'Y'`、`'Z'`三个值,任何其他输入都将导致函数无法按预期递增版本号。
|
||||
|
||||
**输出示例**:
|
||||
如果`latest_tag`为`v1.2.3`且`increment`为`'Y'`,则函数将返回`v1.3.0`。
|
||||
## FunctionDef main
|
||||
**main**: 此函数的功能是自动化Git版本控制流程,包括获取最新Git标签,递增版本号,并根据用户确认将新版本号作为标签推送到远程仓库。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `main` 函数首先通过调用 `get_latest_tag` 函数获取当前Git仓库中的最新标签,并将其打印出来。接着,函数提示用户选择要递增的版本号部分(主版本号X、次版本号Y或修订号Z)。用户的选择通过标准输入接收,并转换为大写字母以便后续处理。如果用户输入的不是X、Y或Z中的任何一个,系统会提示错误并要求用户重新输入,直到输入正确为止。
|
||||
|
||||
一旦获得有效输入,`main` 函数将调用 `update_version_number` 函数,传入最新的Git标签和用户选择的递增部分,以生成新的版本号。新版本号随后被打印出来,询问用户是否确认更新版本号并推送到远程仓库。用户的确认通过标准输入接收,并转换为小写字母进行判断。
|
||||
|
||||
如果用户确认(输入'y'),则使用 `subprocess.run` 方法执行Git命令,首先创建新的版本标签,然后将该标签推送到远程仓库。操作完成后,打印出相应的提示信息。如果用户不确认(输入'n'),则打印出操作已取消的信息。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数之前,需要确保当前环境已安装Git,并且函数调用是在一个Git仓库的根目录下进行的。
|
||||
- 用户输入的处理是大小写不敏感的,即输入'X'、'x'均被视为有效输入,并且都会被转换为大写进行处理。
|
||||
- 在推送新标签到远程仓库之前,函数会要求用户进行确认。这是一个安全措施,以防止意外修改远程仓库。
|
||||
- 此函数依赖于`get_latest_tag`和`update_version_number`两个函数。`get_latest_tag`用于获取最新的Git标签,而`update_version_number`根据用户指定的递增规则更新版本号。这两个函数的正确执行是`main`函数能够正确工作的基础。
|
||||
301
markdown_docs/server/agent/callbacks.md
Normal file
@ -0,0 +1,301 @@
|
||||
## FunctionDef dumps(obj)
|
||||
**dumps**: 该函数的功能是将字典对象转换为JSON格式的字符串。
|
||||
|
||||
**参数**:
|
||||
- obj: 需要被转换为JSON字符串的字典对象。
|
||||
|
||||
**代码描述**:
|
||||
`dumps`函数是一个简单但非常核心的功能,它接受一个字典对象作为输入参数,并使用`json.dumps`方法将该字典转换为一个JSON格式的字符串。在转换过程中,`ensure_ascii=False`参数确保了字符串中的非ASCII字符不会被转义,从而保持了原始数据的可读性和完整性。
|
||||
|
||||
在项目中,`dumps`函数被多个异步回调处理器中的方法调用,这些方法包括`on_tool_start`、`on_tool_end`、`on_tool_error`、`on_llm_new_token`、`on_llm_start`、`on_chat_model_start`、`on_llm_end`、`on_llm_error`和`on_agent_finish`。这些方法通常在处理某些事件(如工具开始、结束、出错等)时,需要将当前工具的状态或其他相关信息序列化为JSON字符串,并将其放入队列中等待进一步处理。通过使用`dumps`函数,确保了这些信息在序列化过程中的格式统一和准确性。
|
||||
|
||||
**注意**:
|
||||
- 在使用`dumps`函数时,需要确保传入的对象是字典类型,因为`json.dumps`方法只能处理字典类型的数据。
|
||||
- 考虑到`ensure_ascii=False`参数的使用,确保在处理JSON字符串的环境中支持非ASCII字符。
|
||||
|
||||
**输出示例**:
|
||||
假设有一个字典对象`{"name": "测试工具", "status": "运行中"}`,使用`dumps`函数处理后的输出示例为:
|
||||
```json
|
||||
{"name": "测试工具", "status": "运行中"}
|
||||
```
|
||||
这个输出是一个标准的JSON格式字符串,可以被进一步用于网络传输、存储或其他需要JSON格式数据的场景中。
|
||||
## ClassDef Status
|
||||
**Status**: Status 类用于定义不同状态的常量。
|
||||
|
||||
**属性**:
|
||||
- `start`: 表示开始状态。
|
||||
- `running`: 表示运行中状态。
|
||||
- `complete`: 表示完成状态。
|
||||
- `agent_action`: 表示代理执行动作状态。
|
||||
- `agent_finish`: 表示代理完成状态。
|
||||
- `error`: 表示错误状态。
|
||||
- `tool_finish`: 表示工具执行完成状态。
|
||||
|
||||
**代码描述**:
|
||||
Status 类在项目中扮演了重要的角色,它通过定义一系列的整型常量来表示不同的状态,这些状态在异步回调处理中被广泛使用,以便于跟踪和管理异步任务的执行流程。例如,在处理工具启动、结束、错误等事件时,会根据不同的事件类型更新当前工具的状态。这些状态不仅帮助开发者理解当前任务的执行阶段,还能够在出现错误或完成任务时提供明确的指示,进而采取相应的处理措施。
|
||||
|
||||
在项目中,Status 类的状态值被用于标识异步操作的不同阶段,如在工具开始执行时标记为 `agent_action`,在工具执行结束时标记为 `tool_finish`,在遇到错误时标记为 `error` 等。这些状态值在 `CustomAsyncIteratorCallbackHandler` 类的各个方法中被引用,以便于在异步操作过程中管理和响应不同的事件。
|
||||
|
||||
例如,在 `on_tool_start` 方法中,使用 `Status.agent_action` 来标记当前工具的状态为代理执行动作状态;在 `on_tool_end` 方法中,使用 `Status.tool_finish` 来更新工具状态为执行完成状态;在 `on_tool_error` 方法中,使用 `Status.error` 来标记错误状态。这种状态管理机制使得异步操作的管理变得更加清晰和有序。
|
||||
|
||||
**注意**:
|
||||
- 在使用 Status 类时,开发者需要确保正确地引用了对应的状态常量,以保证异步操作的状态能够被准确地跟踪和管理。
|
||||
- 状态值的更新应该与实际的异步操作流程相匹配,以避免状态不一致导致的逻辑错误。
|
||||
- 在处理异步操作时,应该根据状态值来决定下一步的操作,如是否继续执行、是否需要处理错误等,以确保程序的健壮性。
|
||||
## ClassDef CustomAsyncIteratorCallbackHandler
|
||||
**CustomAsyncIteratorCallbackHandler**: CustomAsyncIteratorCallbackHandler类的功能是作为异步迭代器回调处理器,用于处理工具的启动、结束、错误以及与长期语言模型(LLM)交互的各个阶段的回调。
|
||||
|
||||
**属性**:
|
||||
- `queue`: 用于存储处理结果的异步队列。
|
||||
- `done`: 一个事件,用于标记处理完成。
|
||||
- `cur_tool`: 当前处理的工具信息。
|
||||
- `out`: 用于控制输出的标志。
|
||||
|
||||
**代码描述**:
|
||||
CustomAsyncIteratorCallbackHandler类继承自AsyncIteratorCallbackHandler,提供了一系列异步方法来处理不同的事件,如工具的启动(on_tool_start)、结束(on_tool_end)、错误(on_tool_error)、与LLM交互的新令牌(on_llm_new_token)、LLM的启动(on_llm_start)和结束(on_llm_end)等。这些方法通过更新`cur_tool`字典和向`queue`队列中添加信息来记录每个事件的处理结果。
|
||||
|
||||
在处理工具启动事件时,该类会对输入字符串进行预处理,移除可能导致处理中断的特定停止词,然后将处理后的信息加入到队列中。在工具结束或发生错误时,也会相应地更新`cur_tool`字典,并将结果加入队列。对于LLM的交互,该类能够处理新令牌的接收、LLM的启动和结束事件,以及错误处理,同样通过更新`cur_tool`字典和队列来记录状态。
|
||||
|
||||
此类在项目中被用于处理与长期语言模型(LLM)的交互过程中的回调,特别是在`server/chat/agent_chat.py/agent_chat/agent_chat_iterator`中,它被用作回调处理器来管理异步聊天迭代器的状态。通过这种方式,它能够收集和整理从LLM和其他工具中得到的输出,为最终的用户交互提供必要的信息。
|
||||
|
||||
**注意**:
|
||||
- 在使用此类时,需要注意其异步特性,确保在适当的异步环境中调用其方法。
|
||||
- 由于它处理的信息可能来自不同的来源(如LLM或其他工具),需要确保输入的数据格式正确,以避免处理过程中的错误。
|
||||
|
||||
**输出示例**:
|
||||
假设处理了一个工具的启动和结束事件,队列中的一个可能的输出示例为:
|
||||
```json
|
||||
{
|
||||
"tool_name": "示例工具",
|
||||
"input_str": "处理前的输入",
|
||||
"output_str": "处理后的输出",
|
||||
"status": "tool_finish",
|
||||
"run_id": "示例运行ID",
|
||||
"llm_token": "",
|
||||
"final_answer": "",
|
||||
"error": ""
|
||||
}
|
||||
```
|
||||
这表示一个工具已经完成了它的任务,其中包含了工具的名称、输入输出字符串、状态、运行ID等信息。
|
||||
### FunctionDef __init__(self)
|
||||
**__init__**: 该函数用于初始化CustomAsyncIteratorCallbackHandler类的实例。
|
||||
|
||||
**参数**: 该函数不接受任何外部参数。
|
||||
|
||||
**代码描述**:
|
||||
此函数是CustomAsyncIteratorCallbackHandler类的构造函数,负责初始化类实例。在这个初始化过程中,首先通过`super().__init__()`调用父类的构造函数来继承父类的初始化逻辑。接着,函数创建了一个异步队列`self.queue`,这个队列用于存储异步操作的结果。此外,`self.done`是一个异步事件(`asyncio.Event`),用于标记异步操作何时完成。`self.cur_tool`是一个字典,用于存储当前工具的状态或数据。最后,`self.out`被设置为True,这可能表示某种输出状态或标志。
|
||||
|
||||
**注意**:
|
||||
- 在使用CustomAsyncIteratorCallbackHandler类之前,了解异步编程和`asyncio`库的基本概念是非常重要的,因为该类的实现依赖于Python的异步编程特性。
|
||||
- `self.queue`用于异步任务之间的通信,确保在使用时正确处理队列中的数据。
|
||||
- `self.done`事件用于控制异步流程,特别是在需要等待某些异步操作完成时。
|
||||
- `self.cur_tool`字典的具体用途和结构应根据实际应用场景进行定义和使用。
|
||||
- `self.out`的具体含义和用途可能根据实际代码逻辑有所不同,开发者应根据上下文来理解和使用它。
|
||||
***
|
||||
### FunctionDef on_tool_start(self, serialized, input_str)
|
||||
**on_tool_start**: 该函数的功能是在工具开始执行时进行初始化和预处理操作。
|
||||
|
||||
**参数**:
|
||||
- serialized: 一个字典,包含序列化后的工具信息。
|
||||
- input_str: 字符串类型,表示工具的输入文本。
|
||||
- run_id: UUID类型,表示当前运行的唯一标识符。
|
||||
- parent_run_id: UUID类型或None,表示父运行的唯一标识符,可选参数。
|
||||
- tags: 字符串列表或None,表示与当前运行相关的标签,可选参数。
|
||||
- metadata: 字典或None,包含与当前运行相关的元数据,可选参数。
|
||||
- **kwargs: 接受任意额外的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`on_tool_start`函数是`CustomAsyncIteratorCallbackHandler`类的一个方法,它在工具开始执行时被调用。该方法首先对输入字符串`input_str`进行预处理,移除可能导致处理中断的特定停止词,如"Observation:", "Thought", 等。这一步骤是为了确保输入字符串在后续处理中不会因为包含特定词汇而提前中断。
|
||||
|
||||
接着,方法使用`serialized`参数中的工具名称和处理后的`input_str`,以及其他相关信息(如运行ID、状态等),构建一个表示当前工具状态的字典`cur_tool`。这个字典包括工具名称、输入输出字符串、状态、运行ID等关键信息。
|
||||
|
||||
最后,`on_tool_start`方法调用`dumps`函数将`cur_tool`字典序列化为JSON格式的字符串,并使用`queue.put_nowait`方法将其异步地放入队列中。这一步是为了将当前工具的状态信息传递给其他部分的处理流程,例如用于监控、日志记录或进一步的数据处理。
|
||||
|
||||
在整个过程中,`Status.agent_action`状态被用来标记当前工具的状态,表示代理正在执行动作。这与`Status`类中定义的其他状态一起,帮助系统跟踪和管理异步任务的执行流程。
|
||||
|
||||
**注意**:
|
||||
- 在使用`on_tool_start`方法时,确保传入的`serialized`参数包含必要的工具信息,如工具名称。
|
||||
- 输入字符串`input_str`可能会根据预定义的停止词被截断,这一点在设计输入内容时需要考虑。
|
||||
- 该方法是异步的,因此在调用时需要使用`await`关键字。
|
||||
- 通过`**kwargs`参数,`on_tool_start`方法能够灵活接收并处理额外的关键字参数,这提供了更大的灵活性,但同时也要求调用者注意参数的正确性和相关性。
|
||||
***
|
||||
### FunctionDef on_tool_end(self, output)
|
||||
**on_tool_end**: 该函数的功能是在工具执行结束时更新工具的状态并处理输出。
|
||||
|
||||
**参数**:
|
||||
- `output`: 字符串类型,表示工具执行的输出内容。
|
||||
- `run_id`: UUID类型,表示当前运行的唯一标识符。
|
||||
- `parent_run_id`: UUID类型或None,表示父运行的唯一标识符,可选参数。
|
||||
- `tags`: 字符串列表或None,表示与当前运行相关的标签,可选参数。
|
||||
- `**kwargs`: 接收任意额外的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`on_tool_end`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,用于处理工具执行结束后的逻辑。该函数首先将实例变量`out`设置为True,表示输出已经准备好。然后,使用`cur_tool.update`方法更新当前工具的状态为`Status.tool_finish`,表示工具执行完成,并将工具的输出字符串中的"Answer:"部分替换为空字符串。最后,该函数将当前工具的状态和更新后的输出通过`dumps`函数序列化为JSON格式的字符串,并使用`queue.put_nowait`方法将其放入队列中,以便进一步处理。
|
||||
|
||||
该函数与`dumps`函数和`Status`类有直接的关联。`dumps`函数用于将字典对象转换为JSON格式的字符串,确保了工具状态和输出信息在序列化过程中的格式统一和准确性。`Status`类提供了一系列状态常量,其中`Status.tool_finish`表示工具执行完成的状态,用于在工具执行结束时更新当前工具的状态。
|
||||
|
||||
**注意**:
|
||||
- 在调用`on_tool_end`函数时,必须确保传入的`output`和`run_id`参数有效,且`run_id`应为唯一标识符。
|
||||
- 可选参数`parent_run_id`和`tags`可以根据需要传入,以提供更多关于当前运行的上下文信息。
|
||||
- 在处理输出字符串时,`output.replace("Answer:", "")`操作是为了去除可能存在的前缀"Answer:",以获取纯净的输出内容。
|
||||
- 该函数是异步的,因此在调用时需要使用`await`关键字。
|
||||
- 在使用`queue.put_nowait`方法将信息放入队列时,应确保队列已经正确初始化并准备好接收数据。
|
||||
***
|
||||
### FunctionDef on_tool_error(self, error)
|
||||
**on_tool_error**: 该函数的功能是处理工具执行过程中发生的错误。
|
||||
|
||||
**参数**:
|
||||
- `error`: 异常或键盘中断的实例,表示发生的错误。
|
||||
- `run_id`: UUID格式,表示当前运行的唯一标识。
|
||||
- `parent_run_id`: UUID格式或None,表示父运行的唯一标识,如果存在的话。
|
||||
- `tags`: 字符串列表或None,表示与当前错误相关的标签。
|
||||
- `**kwargs`: 接受任意额外的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`on_tool_error`函数是`CustomAsyncIteratorCallbackHandler`类中的一个异步方法,用于处理在工具执行过程中发生的错误。当工具执行过程中遇到异常或键盘中断时,此方法会被调用。函数首先使用`self.cur_tool.update`方法更新当前工具的状态为`Status.error`,并记录错误信息。接着,它将当前工具的状态和错误信息序列化为JSON格式的字符串,并使用`self.queue.put_nowait`方法将该字符串放入队列中,以便后续处理。
|
||||
|
||||
该函数与`dumps`函数和`Status`类有直接的关联。`dumps`函数用于将字典对象转换为JSON格式的字符串,确保错误信息和工具状态以正确的格式被序列化和传输。`Status`类则提供了一个`error`状态常量,用于明确标识工具当前处于错误状态。这种设计使得错误处理过程既清晰又高效,便于后续的错误追踪和处理。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,必须确保传入的`error`参数是一个异常或键盘中断的实例,以便正确记录错误信息。
|
||||
- `run_id`和`parent_run_id`参数应为有效的UUID格式,以确保能够准确追踪到具体的运行实例和其父实例(如果有)。
|
||||
- `tags`参数可以用于提供额外的错误上下文信息,有助于错误的分类和分析。
|
||||
- 该函数是异步的,调用时需要使用`await`关键字。
|
||||
***
|
||||
### FunctionDef on_llm_new_token(self, token)
|
||||
**on_llm_new_token**: 该函数的功能是处理新的LLM(Large Language Model)生成的令牌。
|
||||
|
||||
**参数**:
|
||||
- token: 字符串类型,表示LLM生成的新令牌。
|
||||
- **kwargs: 接收任意数量的关键字参数,这些参数可以在函数体内使用,但在当前函数实现中未直接使用。
|
||||
|
||||
**代码描述**:
|
||||
`on_llm_new_token`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,主要用于处理由大型语言模型生成的新令牌。函数首先定义了一个名为`special_tokens`的列表,其中包含了特定的令牌字符串,如"Action"和"<|observation|>"。这些特殊令牌用于识别LLM生成的令牌中是否包含特定的动作或观察结果。
|
||||
|
||||
函数接着遍历`special_tokens`列表,检查传入的`token`是否包含列表中的任一特殊令牌。如果发现`token`中包含特殊令牌,函数将执行以下操作:
|
||||
1. 使用`split`方法分割`token`,以特殊令牌为界,取分割后的第一部分作为`before_action`。
|
||||
2. 调用`self.cur_tool.update`方法更新当前工具的状态为`Status.running`,并将`before_action`加上换行符后设置为`llm_token`。
|
||||
3. 使用`dumps`函数将`self.cur_tool`对象转换为JSON格式的字符串,并通过`self.queue.put_nowait`方法将其放入队列中。
|
||||
4. 设置`self.out`为`False`,并终止循环。
|
||||
|
||||
如果`token`非空且`self.out`为`True`(即未找到特殊令牌),则直接将`token`作为`llm_token`更新到`self.cur_tool`中,并同样将其序列化后放入队列。
|
||||
|
||||
此函数通过检查LLM生成的令牌是否包含特定的动作或观察结果,来决定是否更新当前工具的状态和内容,并将更新后的信息放入队列中,以供后续处理。
|
||||
|
||||
**注意**:
|
||||
- 函数中使用了`dumps`函数将字典对象序列化为JSON字符串,这一步骤是为了确保队列中的数据格式统一,便于后续的处理和传输。
|
||||
- `Status.running`是从`Status`类中引用的一个状态值,表示当前工具或任务正在运行中。在更新工具状态时,需要确保使用正确的状态值。
|
||||
- 函数的异步性质要求调用者在使用时配合`await`关键字,以确保异步操作的正确执行。
|
||||
- 函数实现中未直接使用`**kwargs`参数,这意味着函数设计上允许接收额外的关键字参数,以便于未来扩展或在不同上下文中灵活使用。
|
||||
***
|
||||
### FunctionDef on_llm_start(self, serialized, prompts)
|
||||
**on_llm_start**: 该函数的功能是在长期学习模型(LLM)启动时更新当前工具的状态并将其序列化后放入队列中。
|
||||
|
||||
**参数**:
|
||||
- `serialized`: 一个字典,包含序列化信息,其类型为`Dict[str, Any]`。
|
||||
- `prompts`: 一个字符串列表,包含提示信息,其类型为`List[str]`。
|
||||
- `**kwargs`: 接收任意数量的关键字参数,其类型为`Any`。
|
||||
|
||||
**代码描述**:
|
||||
`on_llm_start`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,主要用于处理长期学习模型(LLM)启动时的逻辑。在该方法中,首先通过调用`self.cur_tool.update`方法更新当前工具的状态为`Status.start`,并将`llm_token`设置为空字符串。这表示当前工具已经开始执行,但尚未生成或接收到任何LLM令牌。
|
||||
|
||||
接下来,该方法使用`dumps`函数将`self.cur_tool`对象序列化为JSON格式的字符串。`dumps`函数是一个核心功能,它接受一个字典对象作为输入,并将其转换为JSON格式的字符串,确保了非ASCII字符的可读性和完整性。在本方法中,`dumps`函数的使用确保了当前工具状态的序列化信息格式统一和准确性。
|
||||
|
||||
最后,序列化后的字符串通过`self.queue.put_nowait`方法立即放入队列中,等待进一步处理。这一步骤是异步操作的一部分,确保了即使在高并发环境下,也能高效地处理大量的任务。
|
||||
|
||||
**注意**:
|
||||
- 在使用`on_llm_start`方法时,需要确保传入的`serialized`参数是正确格式的字典,以及`prompts`参数是一个字符串列表。这些参数对于方法的执行至关重要。
|
||||
- 该方法是异步的,因此在调用时需要使用`await`关键字。
|
||||
- 更新状态和序列化操作应该与实际的LLM启动逻辑相匹配,以确保状态的准确性和信息的完整性。
|
||||
- 在处理异步任务时,应当注意异常处理,确保即使在遇到错误的情况下,也能保证程序的稳定运行。
|
||||
***
|
||||
### FunctionDef on_chat_model_start(self, serialized, messages)
|
||||
**on_chat_model_start**: 该函数的功能是在聊天模型开始时进行初始化设置。
|
||||
|
||||
**参数**:
|
||||
- `serialized`: 一个字典类型参数,包含序列化信息。
|
||||
- `messages`: 一个列表类型参数,包含消息列表。
|
||||
- `run_id`: 一个UUID类型参数,表示运行的唯一标识。
|
||||
- `parent_run_id`: 一个可选的UUID类型参数,表示父运行的唯一标识。
|
||||
- `tags`: 一个可选的字符串列表类型参数,包含标签信息。
|
||||
- `metadata`: 一个可选的字典类型参数,包含元数据信息。
|
||||
- `**kwargs`: 接收任意额外的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`on_chat_model_start`函数是`CustomAsyncIteratorCallbackHandler`类的一个方法,它主要用于处理聊天模型开始时的初始化工作。在这个方法中,首先通过`self.cur_tool.update`方法更新当前工具的状态为`Status.start`,并将`llm_token`设置为空字符串。这表示聊天模型开始执行,且当前没有任何长寿命模型(Long-Lived Model)的令牌。接着,使用`self.queue.put_nowait`方法将`self.cur_tool`的序列化信息(通过`dumps`函数转换为JSON格式的字符串)立即放入队列中,以便后续处理。
|
||||
|
||||
这个方法中调用了两个重要的对象:`Status`和`dumps`。`Status`类用于定义不同的状态常量,其中`Status.start`表示开始状态,用于标识聊天模型的启动。`dumps`函数用于将字典对象转换为JSON格式的字符串,这里它被用来序列化`self.cur_tool`的信息,以便将这些信息以字符串形式放入队列中。
|
||||
|
||||
**注意**:
|
||||
- 在调用`on_chat_model_start`方法时,需要确保传入的参数符合要求,特别是`run_id`必须是有效的UUID。
|
||||
- `serialized`参数应包含所有必要的序列化信息,以确保聊天模型可以正确初始化。
|
||||
- 使用`tags`和`metadata`参数可以提供额外的上下文信息,但它们是可选的。
|
||||
- 该方法是异步的,因此在调用时需要使用`await`关键字。
|
||||
- 在实际应用中,应注意`**kwargs`参数的使用,确保不会传入意外的关键字参数,以避免潜在的错误。
|
||||
***
|
||||
### FunctionDef on_llm_end(self, response)
|
||||
**on_llm_end**: 该函数的功能是在LLM(大型语言模型)任务结束时更新当前工具的状态并将其放入队列中。
|
||||
|
||||
**参数**:
|
||||
- `response`: LLMResult类型,表示LLM任务的结果。
|
||||
- `**kwargs`: 接受任意额外的关键字参数,提供了函数调用的灵活性。
|
||||
|
||||
**代码描述**:
|
||||
`on_llm_end`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,它在大型语言模型(LLM)任务结束时被调用。此函数首先使用`self.cur_tool.update`方法更新当前工具的状态为`Status.complete`,表示任务已完成,并设置`llm_token`为换行符("\n")。这一步骤是为了标记当前处理的工具或任务已经完成,准备进行下一步操作。
|
||||
|
||||
接着,函数使用`self.queue.put_nowait`方法将`self.cur_tool`的JSON字符串表示(通过调用`dumps`函数转换得到)放入队列中,以便后续处理。`dumps`函数将`self.cur_tool`字典对象转换为JSON格式的字符串,确保了信息在序列化过程中的格式统一和准确性。这一步骤是异步处理流程中的一个关键环节,它确保了任务状态的更新和信息的传递能够及时且准确地完成。
|
||||
|
||||
在整个项目中,`dumps`函数和`Status`类是与`on_llm_end`函数紧密相关的两个对象。`dumps`函数负责将字典对象序列化为JSON字符串,而`Status`类提供了一组预定义的状态常量,用于标识异步操作的不同阶段。这些工具和机制共同支持了`on_llm_end`函数的实现,使其能够有效地管理和传递LLM任务的结束状态。
|
||||
|
||||
**注意**:
|
||||
- 在调用`on_llm_end`函数时,需要确保传入的`response`参数是`LLMResult`类型,以保证函数能够正确处理LLM任务的结果。
|
||||
- 函数内部使用了`**kwargs`来接受任意额外的关键字参数,这提供了调用时的灵活性,但调用者应注意只传递需要的参数,避免不必要的混淆。
|
||||
- 更新状态和放入队列的操作是异步执行的,调用此函数时应注意处理可能出现的异步执行相关的问题,如并发控制和异常处理。
|
||||
***
|
||||
### FunctionDef on_llm_error(self, error)
|
||||
**on_llm_error**: 该函数的功能是处理LLM错误事件。
|
||||
|
||||
**参数**:
|
||||
- `error`: 接收一个异常对象,可以是`Exception`或`KeyboardInterrupt`类型,表示发生的错误。
|
||||
- `**kwargs`: 接收任意数量的关键字参数,提供额外的灵活性以处理不同的错误情况。
|
||||
|
||||
**代码描述**:
|
||||
`on_llm_error`函数是`CustomAsyncIteratorCallbackHandler`类的一个方法,专门用于处理LLM(长寿命模型)在执行过程中遇到的错误。当LLM执行过程中发生错误时,此函数会被触发。
|
||||
|
||||
在函数内部,首先通过`self.cur_tool.update`方法更新当前工具的状态为`Status.error`,并记录错误信息。这里的`Status.error`是一个从`Status`类中定义的常量,表示当前工具处于错误状态。错误信息则通过将`error`参数转换为字符串形式来记录。
|
||||
|
||||
接下来,函数使用`self.queue.put_nowait`方法将当前工具的状态信息异步地放入队列中。在放入队列之前,使用`dumps`函数将工具状态信息序列化为JSON格式的字符串。`dumps`函数是一个关键的功能,它将字典对象转换为JSON格式的字符串,确保了信息在网络传输或存储过程中的格式统一和准确性。
|
||||
|
||||
**注意**:
|
||||
- 在处理LLM错误时,确保传递给`on_llm_error`函数的`error`参数包含了足够的错误信息,以便于准确记录和后续处理。
|
||||
- 使用`**kwargs`参数提供了额外的灵活性,但在调用时需要注意传递的关键字参数应与错误处理逻辑相匹配。
|
||||
- 在更新工具状态和序列化状态信息时,应确保操作的原子性和错误处理机制,避免因异常处理不当导致的进一步错误。
|
||||
- 考虑到`dumps`函数的使用,确保传入的对象符合JSON序列化的要求,并注意处理非ASCII字符的情况。
|
||||
***
|
||||
### FunctionDef on_agent_finish(self, finish)
|
||||
**on_agent_finish**: 该函数的功能是在代理执行完成时更新当前工具的状态,并将其最终结果放入队列中。
|
||||
|
||||
**参数**:
|
||||
- `finish`: 一个`AgentFinish`类型的对象,包含代理执行的最终结果。
|
||||
- `run_id`: 一个`UUID`类型的对象,表示当前运行的唯一标识。
|
||||
- `parent_run_id`: 一个可选的`UUID`类型的对象,表示父运行的唯一标识。
|
||||
- `tags`: 一个可选的字符串列表,包含与当前运行相关的标签。
|
||||
- `**kwargs`: 接受任意额外的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`on_agent_finish`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,它在代理执行完成时被调用。该方法首先使用`finish.return_values["output"]`获取代理执行的最终输出结果,并将当前工具的状态更新为`Status.agent_finish`,同时设置最终答案为代理的输出结果。然后,它使用`dumps`函数将当前工具的状态序列化为JSON格式的字符串,并使用`put_nowait`方法将这个字符串放入队列中,以便后续处理。最后,`cur_tool`被重置为空字典,为下一次代理执行做准备。
|
||||
|
||||
在这个过程中,`dumps`函数负责将字典对象转换为JSON格式的字符串,确保了信息在序列化过程中的格式统一和准确性。`Status`类提供了`agent_finish`状态,标识代理执行已完成,这对于跟踪和管理异步任务的执行流程至关重要。
|
||||
|
||||
**注意**:
|
||||
- 确保`finish`参数提供了有效的代理执行结果,特别是`finish.return_values["output"]`能够正确获取到输出结果。
|
||||
- 使用`dumps`函数时,需要确保传入的对象是字典类型,以避免序列化错误。
|
||||
- 在将信息放入队列时,使用`put_nowait`方法可以避免阻塞,但需要确保队列处理速度足以应对放入的速度,避免队列溢出。
|
||||
|
||||
**输出示例**:
|
||||
由于`on_agent_finish`方法没有返回值,其主要作用是更新状态并将信息放入队列,因此没有直接的输出示例。但可以假设在代理执行完成后,队列中将包含一个类似于以下的JSON格式字符串:
|
||||
```json
|
||||
{"status": 5, "final_answer": "代理执行的输出结果"}
|
||||
```
|
||||
这表示当前工具的状态已更新为代理完成状态,且最终答案已设置为代理的输出结果。
|
||||
***
|
||||
296
markdown_docs/server/agent/custom_agent/ChatGLM3Agent.md
Normal file
@ -0,0 +1,296 @@
|
||||
## ClassDef StructuredChatOutputParserWithRetries
|
||||
**StructuredChatOutputParserWithRetries**: 该类的功能是为结构化聊天代理提供带有重试机制的输出解析。
|
||||
|
||||
**属性**:
|
||||
- base_parser: 使用的基础解析器。
|
||||
- output_fixing_parser: 使用的输出修正解析器,可选。
|
||||
|
||||
**代码描述**:
|
||||
StructuredChatOutputParserWithRetries 类继承自 AgentOutputParser,主要用于解析结构化聊天代理的输出。它通过定义两个主要属性——base_parser 和 output_fixing_parser 来实现其功能。base_parser 是一个 StructuredChatOutputParser 实例,用于基本的输出解析。output_fixing_parser 是一个可选的 OutputFixingParser 实例,用于在必要时修正输出。
|
||||
|
||||
该类的核心方法是 parse,它接受一个字符串 text 作为输入,并尝试解析这个字符串以生成一个代理动作(AgentAction)或代理完成信号(AgentFinish)。解析过程首先尝试找到特殊标记(如 "Action:" 或 "<|observation|>")的位置,然后根据是否包含 "tool_call" 来决定如何处理文本。如果包含 "tool_call",则进一步解析以提取动作和参数;否则,直接将文本作为最终答案处理。解析完成后,根据 output_fixing_parser 的存在与否,选择相应的解析器进行最终解析。
|
||||
|
||||
在项目中,StructuredChatOutputParserWithRetries 被 StructuredGLM3ChatAgent 类作为默认的输出解析器使用。通过 StructuredGLM3ChatAgent 类的 _get_default_output_parser 方法,可以看出 StructuredChatOutputParserWithRetries 被用于构建结构化聊天代理,以处理语言模型(LLM)的输出并将其转换为适合代理处理的格式。
|
||||
|
||||
**注意**:
|
||||
- 在使用 StructuredChatOutputParserWithRetries 类时,需要确保传入的文本格式符合预期,特别是当涉及到特殊标记和工具调用格式时。
|
||||
- 如果提供了 output_fixing_parser,它将用于在基础解析失败或需要修正时进行二次解析。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
Action:
|
||||
```
|
||||
{
|
||||
"action": "Final Answer",
|
||||
"action_input": "这是解析后的文本"
|
||||
}
|
||||
```
|
||||
在这个示例中,假设传入的文本不包含 "tool_call",则 parse 方法将直接将文本视为最终答案,并构建相应的 JSON 字符串作为输出。
|
||||
### FunctionDef parse(self, text)
|
||||
**parse**: 此函数的功能是解析文本并生成相应的动作或最终答案。
|
||||
|
||||
**参数**:
|
||||
- `text`: 需要解析的文本,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先定义了一个包含特殊标记的列表`special_tokens`,这些特殊标记用于在文本中查找特定的位置。接着,它会找到这些特殊标记中第一个出现的位置,并将文本截断到这个位置,以便进一步处理。
|
||||
|
||||
如果文本中包含"tool_call",则认为这是一个需要执行的动作。函数会找到动作描述结束的位置(即"```"的位置),并提取出动作名称和参数。参数会被解析成键值对的形式,并存储在一个字典中。然后,这些信息会被组织成一个JSON对象,准备进行下一步的解析。
|
||||
|
||||
如果文本中不包含"tool_call",则认为这是一个最终答案,直接将文本作为动作输入,动作名称设为"Final Answer"。
|
||||
|
||||
之后,函数会根据是否存在`output_fixing_parser`来决定使用哪个解析器进行解析。如果存在,就使用`output_fixing_parser`解析器,否则使用`base_parser`解析器。解析的结果会被返回。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保传入的文本格式正确,特别是当文本中包含动作描述时,需要遵循特定的格式(例如,动作和参数的正确分隔)。
|
||||
- 如果在解析过程中遇到任何异常,函数会抛出`OutputParserException`异常,异常信息中会包含无法解析的原始文本。
|
||||
|
||||
**输出示例**:
|
||||
假设文本内容为一个动作调用,解析后可能的返回值为:
|
||||
```json
|
||||
{
|
||||
"action": "tool_call_example",
|
||||
"action_input": {
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}
|
||||
}
|
||||
```
|
||||
如果文本内容为最终答案,解析后可能的返回值为:
|
||||
```json
|
||||
{
|
||||
"action": "Final Answer",
|
||||
"action_input": "这是一个最终答案的示例文本。"
|
||||
}
|
||||
```
|
||||
***
|
||||
### FunctionDef _type(self)
|
||||
**_type**: 该函数的功能是返回一个特定的字符串。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `_type` 函数是一个非常简单的方法,其主要目的是返回一个预定义的字符串。这个字符串代表了一个特定的类型标识,即 "structured_chat_ChatGLM3_6b_with_retries"。这个标识通常用于区分不同的处理逻辑或数据格式。在这个上下文中,它可能表示使用了特定配置或策略的聊天模型,特别是指一个结构化的聊天输出解析器,该解析器配置了重试机制。这种类型的标识对于维护代码的清晰度和可维护性非常重要,因为它允许开发者快速识别和理解代码块的用途和行为。
|
||||
|
||||
**注意**: 使用此函数时,需要注意它返回的字符串是硬编码的,这意味着如果未来需要更改类型标识,将需要直接修改此函数的返回值。因此,维护此部分代码时应谨慎,确保任何更改都不会影响依赖此标识的其他代码逻辑。
|
||||
|
||||
**输出示例**: 调用 `_type` 函数将返回以下字符串:
|
||||
```
|
||||
"structured_chat_ChatGLM3_6b_with_retries"
|
||||
```
|
||||
***
|
||||
## ClassDef StructuredGLM3ChatAgent
|
||||
**StructuredGLM3ChatAgent**: 该类的功能是实现一个结构化的聊天代理,用于处理和响应基于ChatGLM3-6B模型的对话。
|
||||
|
||||
**属性**:
|
||||
- output_parser: 用于解析代理输出的解析器,默认为StructuredChatOutputParserWithRetries实例。
|
||||
- observation_prefix: 用于在ChatGLM3-6B观察结果前添加的前缀字符串。
|
||||
- llm_prefix: 用于在语言模型调用前添加的前缀字符串。
|
||||
|
||||
**代码描述**:
|
||||
StructuredGLM3ChatAgent 类继承自 Agent 类,提供了结构化聊天代理的实现。它通过定义特定的属性和方法来处理与语言模型(LLM)的交互,生成提示(prompt),并解析LLM的输出。
|
||||
|
||||
- **属性定义**:
|
||||
- `output_parser` 属性指定了用于解析代理输出的解析器,其默认值为 StructuredChatOutputParserWithRetries 类的实例,该解析器提供了带有重试机制的输出解析功能。
|
||||
- `observation_prefix` 和 `llm_prefix` 属性分别定义了在观察结果和语言模型调用前添加的前缀字符串,用于格式化生成的提示。
|
||||
|
||||
- **方法分析**:
|
||||
- `_construct_scratchpad` 方法用于构建代理的草稿本,它基于中间步骤生成一个字符串,用于记录代理的工作过程。
|
||||
- `_get_default_output_parser` 类方法返回一个默认的输出解析器实例,用于解析语言模型的输出。
|
||||
- `create_prompt` 类方法用于根据提供的工具和输入变量生成提示模板,该方法将工具的信息和其他输入变量格式化为一个字符串模板,用于生成语言模型的输入。
|
||||
- `from_llm_and_tools` 类方法用于根据语言模型和工具集合构建一个StructuredGLM3ChatAgent实例,它通过组合语言模型、工具和其他参数来初始化代理。
|
||||
|
||||
**注意**:
|
||||
- 在使用 StructuredGLM3ChatAgent 类时,需要确保提供的工具和语言模型与代理的目标任务相匹配。
|
||||
- 输出解析器(output_parser)应该能够准确解析语言模型的输出,以便代理能够正确响应用户的输入。
|
||||
- 在构建提示时,应注意格式化字符串模板,确保它们能够正确地被语言模型理解和处理。
|
||||
|
||||
**输出示例**:
|
||||
假设代理接收到的输入是一个简单的问答任务,输出示例可能如下:
|
||||
```
|
||||
{
|
||||
"action": "Final Answer",
|
||||
"action_input": "这是代理基于语言模型输出解析后的回答"
|
||||
}
|
||||
```
|
||||
在这个示例中,代理通过解析语言模型的输出,生成了一个包含最终回答的动作(Action)和相应输入(action_input)的JSON对象。
|
||||
### FunctionDef observation_prefix(self)
|
||||
**observation_prefix**: 此函数的功能是生成并返回ChatGLM3-6B观察的前缀字符串。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `observation_prefix`函数是`StructuredGLM3ChatAgent`类的一个方法,它的主要作用是为ChatGLM3-6B模型的观察提供一个统一的前缀。这个前缀用于在处理聊天或对话数据时,标识出哪些内容是观察到的信息。在这个函数中,返回的字符串是"Observation:",这意味着所有通过此方法处理的观察数据将以"Observation:"作为开头。这有助于模型识别和处理输入数据,确保数据格式的一致性和准确性。
|
||||
|
||||
**注意**: 使用此函数时,需要注意它返回的前缀字符串是固定的。如果在不同的上下文或应用中需要不同的前缀,可能需要对此函数进行相应的修改或扩展。
|
||||
|
||||
**输出示例**: 调用`observation_prefix`函数将返回以下字符串:
|
||||
```
|
||||
Observation:
|
||||
```
|
||||
***
|
||||
### FunctionDef llm_prefix(self)
|
||||
**llm_prefix函数功能**: 该函数的功能是生成并返回一个用于在调用大型语言模型(llm)时附加的前缀字符串。
|
||||
|
||||
**参数**: 该函数没有参数。
|
||||
|
||||
**代码描述**: `llm_prefix`函数定义在`StructuredGLM3ChatAgent`类中,是一个简单的成员函数,不接受任何参数,并且返回一个固定的字符串`"Thought:"`。这个字符串作为前缀,其目的是在向大型语言模型(llm)发起调用时,附加到实际的查询或命令之前,以此来可能影响或指定模型的回应方式。这种做法在与大型语言模型交互时很常见,用于引导模型的回应更加符合期望的上下文或风格。
|
||||
|
||||
**注意**: 使用`llm_prefix`函数时,需要注意的是,返回的前缀字符串`"Thought:"`是硬编码的,这意味着在不同的应用场景下,如果需要不同的前缀来引导大型语言模型的回应,可能需要修改这个函数的返回值。此外,这个前缀的有效性和适用性可能会随着大型语言模型的不同或者模型训练数据的更新而变化,因此在实际应用中需要根据模型的具体表现来调整。
|
||||
|
||||
**输出示例**: 调用`llm_prefix`函数将返回字符串`"Thought:"`。
|
||||
|
||||
通过上述分析,开发者和初学者可以了解到`llm_prefix`函数的作用、使用方法以及需要注意的事项。这有助于在使用`StructuredGLM3ChatAgent`类与大型语言模型进行交互时,能够更有效地引导模型的回应,从而提高交互的质量和效果。
|
||||
***
|
||||
### FunctionDef _construct_scratchpad(self, intermediate_steps)
|
||||
**_construct_scratchpad**: 此函数的功能是构建并返回一个代表中间步骤的字符串。
|
||||
|
||||
**参数**:
|
||||
- **intermediate_steps**: 一个列表,包含元组,每个元组由AgentAction和字符串组成,代表中间的操作步骤。
|
||||
|
||||
**代码描述**:
|
||||
`_construct_scratchpad` 函数首先调用其父类的 `_construct_scratchpad` 方法,传入中间步骤的数据(`intermediate_steps`),并接收返回的字符串(`agent_scratchpad`)。此字符串代表了到目前为止的工作进展。函数接着检查 `agent_scratchpad` 是否为字符串类型,如果不是,则抛出 `ValueError` 异常,确保后续操作的数据类型正确性。
|
||||
|
||||
如果 `agent_scratchpad` 非空,函数将返回一个格式化的字符串,该字符串以一种友好的方式向用户展示之前的工作成果,即使实际上这个函数并没有直接访问到这些成果,只是通过参数传递得到的信息。如果 `agent_scratchpad` 为空,则直接返回该空字符串。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `intermediate_steps` 参数格式正确,即列表中包含的元素为元组,且元组包含的是 `AgentAction` 和字符串。
|
||||
- 此函数假设父类的 `_construct_scratchpad` 方法已正确实现并能返回一个字符串。如果父类方法的实现发生变化,可能需要相应地调整此函数。
|
||||
|
||||
**输出示例**:
|
||||
如果 `intermediate_steps` 包含了一系列的操作步骤,且父类方法返回了这些步骤的字符串表示,例如 "Step 1: Do something; Step 2: Do something else;",那么此函数可能返回的字符串示例为:
|
||||
|
||||
```
|
||||
"This was your previous work (but I haven't seen any of it! I only see what you return as final answer):
|
||||
Step 1: Do something; Step 2: Do something else;"
|
||||
```
|
||||
***
|
||||
### FunctionDef _get_default_output_parser(cls, llm)
|
||||
**_get_default_output_parser**: 该函数的功能是获取默认的输出解析器。
|
||||
|
||||
**参数**:
|
||||
- `llm`: 可选参数,类型为 `BaseLanguageModel`,表示基础语言模型。
|
||||
- `**kwargs`: 接受任意数量的关键字参数。
|
||||
|
||||
**代码描述**: `_get_default_output_parser` 函数是 `StructuredGLM3ChatAgent` 类的一个类方法,用于获取默认的输出解析器。该方法接受一个可选的语言模型实例 `llm` 和任意数量的关键字参数 `**kwargs`。函数体内部,它创建并返回一个 `StructuredChatOutputParserWithRetries` 实例,将 `llm` 作为参数传递给该实例。`StructuredChatOutputParserWithRetries` 类是专门为结构化聊天代理设计的输出解析器,具有重试机制,能够处理语言模型的输出并将其转换为适合代理处理的格式。
|
||||
|
||||
在项目中,`_get_default_output_parser` 方法被 `from_llm_and_tools` 方法调用,以获取默认的输出解析器实例。如果在创建 `StructuredGLM3ChatAgent` 实例时没有明确指定输出解析器,则会通过调用 `_get_default_output_parser` 方法来获取默认的输出解析器实例,并将其用于处理语言模型的输出。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `_get_default_output_parser` 方法时,需要确保传入的 `llm` 参数(如果有)是一个有效的语言模型实例。
|
||||
- 该方法设计为灵活接受任意数量的关键字参数 `**kwargs`,但在当前实现中并未直接使用这些额外的参数。开发者在扩展或修改方法时可以根据需要利用这些参数。
|
||||
|
||||
**输出示例**: 由于 `_get_default_output_parser` 方法返回的是一个 `StructuredChatOutputParserWithRetries` 实例,因此输出示例将依赖于该实例的具体实现。假设 `llm` 参数为 `None`,调用 `_get_default_output_parser` 方法将返回一个不带语言模型实例的 `StructuredChatOutputParserWithRetries` 实例。
|
||||
***
|
||||
### FunctionDef _stop(self)
|
||||
**_stop函数的功能**: `_stop`函数的目的是结束当前的会话并返回一个特定的标记列表。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `_stop`函数是`StructuredGLM3ChatAgent`类的一个私有方法,用于在聊天代理的会话中标记结束点。当调用此函数时,它会返回一个包含单个字符串元素`"<|observation|>"`的列表。这个返回值通常用于指示聊天模型的会话已经结束,或者需要进行某种形式的重置或观察。在聊天代理的上下文中,这个特定的字符串可能被用作一个信号或标记,以触发特定的行为或处理逻辑。
|
||||
|
||||
**注意**: 虽然`_stop`函数的实现看起来简单,但它在聊天代理的逻辑中可能扮演着关键角色。使用时需要确保聊天模型或处理逻辑能够正确识别并处理返回的`"<|observation|>"`标记。此外,由于`_stop`是一个私有方法,它仅在`StructuredGLM3ChatAgent`类的内部被调用,不应该直接从类的实例外部访问或调用。
|
||||
|
||||
**输出示例**: 调用`_stop`函数可能会返回如下列表:
|
||||
```python
|
||||
["<|observation|>"]
|
||||
```
|
||||
这个列表包含一个字符串元素,即`"<|observation|>"`,用于表示聊天会话的结束或需要进行观察的状态。
|
||||
***
|
||||
### FunctionDef create_prompt(cls, tools, prompt, input_variables, memory_prompts)
|
||||
**create_prompt**: 此函数的功能是基于提供的工具和模板参数构建聊天提示模板。
|
||||
|
||||
**参数**:
|
||||
- `tools`: 一个实现了BaseTool接口的对象序列,代表聊天代理可以使用的工具。
|
||||
- `prompt`: 一个字符串模板,用于格式化最终的提示信息。
|
||||
- `input_variables`: 一个字符串列表,指定输入变量的名称,默认为None。
|
||||
- `memory_prompts`: 一个BasePromptTemplate对象的列表,用于提供记忆提示,默认为None。
|
||||
|
||||
**代码描述**:
|
||||
`create_prompt`函数首先遍历`tools`参数中的每个工具,提取其名称、描述和参数模式,并将这些信息格式化为一个简化的JSON结构。这个结构包括工具的名称、描述和参数。接着,函数将这些工具信息格式化为一个字符串,其中每个工具的信息占据一行,包括其名称、描述和参数。这个格式化的字符串以及其他提供的模板参数(如工具名称列表、历史记录、输入和代理草稿板)被用来填充`prompt`模板字符串。
|
||||
|
||||
如果`input_variables`未指定,则默认为`["input", "agent_scratchpad"]`。`memory_prompts`参数允许将额外的提示信息加入到最终的提示模板中,这些信息可以是之前的对话历史或其他重要信息。
|
||||
|
||||
最后,函数使用格式化后的提示信息和输入变量列表创建一个`ChatPromptTemplate`对象,并将其返回。这个返回的对象可以直接用于生成聊天代理的提示信息。
|
||||
|
||||
在项目中,`create_prompt`函数被`from_llm_and_tools`方法调用,用于根据语言模型(LLM)和工具集合构建一个聊天代理。这表明`create_prompt`函数在构建聊天代理的初始化过程中起着核心作用,特别是在准备聊天代理的提示模板方面。
|
||||
|
||||
**注意**:
|
||||
- 确保`prompt`参数提供的模板字符串正确地使用了所有预期的变量,以避免格式化时出现错误。
|
||||
- `tools`参数中的工具对象需要实现`BaseTool`接口,确保它们具有`name`、`description`和`args_schema`属性。
|
||||
|
||||
**输出示例**:
|
||||
假设有两个工具,分别为"Calculator"和"Translator",且`prompt`参数为"Available tools: {tools}\nInput: {input}",则函数可能返回的`ChatPromptTemplate`对象中的`messages`属性可能包含以下字符串:
|
||||
|
||||
```
|
||||
Available tools:
|
||||
Calculator: A simple calculator, args: {'number1': 'Number', 'number2': 'Number'}
|
||||
Translator: Translates text from one language to another, args: {'text': 'String', 'target_language': 'String'}
|
||||
Input: {input}
|
||||
```
|
||||
***
|
||||
### FunctionDef from_llm_and_tools(cls, llm, tools, prompt, callback_manager, output_parser, human_message_template, input_variables, memory_prompts)
|
||||
**from_llm_and_tools**: 该函数的功能是从语言模型(LLM)和工具集合构建一个聊天代理。
|
||||
|
||||
**参数**:
|
||||
- `cls`: 类方法的第一个参数,指代当前类。
|
||||
- `llm`: `BaseLanguageModel`的实例,表示基础语言模型。
|
||||
- `tools`: 实现了`BaseTool`接口的对象序列,代表聊天代理可以使用的工具。
|
||||
- `prompt`: 字符串类型,用于格式化最终的提示信息,默认为None。
|
||||
- `callback_manager`: `BaseCallbackManager`的实例,用于管理回调函数,默认为None。
|
||||
- `output_parser`: `AgentOutputParser`的实例,用于解析代理输出,默认为None。
|
||||
- `human_message_template`: 字符串类型,表示人类消息模板,默认为`HUMAN_MESSAGE_TEMPLATE`。
|
||||
- `input_variables`: 字符串列表,指定输入变量的名称,默认为None。
|
||||
- `memory_prompts`: `BasePromptTemplate`对象的列表,用于提供记忆提示,默认为None。
|
||||
- `**kwargs`: 接受任意数量的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`from_llm_and_tools`函数首先验证提供的工具集合是否有效。然后,它调用`create_prompt`方法来创建聊天提示模板,该模板基于提供的工具、提示、输入变量和记忆提示。接着,使用`llm`、生成的`prompt`和`callback_manager`创建一个`LLMChain`实例。此外,函数从工具集合中提取工具名称,并尝试获取默认的输出解析器,如果未提供`output_parser`参数,则调用`_get_default_output_parser`方法获取默认解析器。最后,使用这些组件构建并返回一个`StructuredGLM3ChatAgent`实例。
|
||||
|
||||
**注意**:
|
||||
- 确保提供的`llm`和`tools`参数是有效的实例,且`tools`中的每个工具都实现了`BaseTool`接口。
|
||||
- 如果在调用时未指定`output_parser`,则会自动使用默认的输出解析器。
|
||||
- `**kwargs`参数提供了额外的灵活性,允许在创建代理时传递额外的配置选项。
|
||||
|
||||
**输出示例**:
|
||||
由于`from_llm_and_tools`函数返回的是一个`StructuredGLM3ChatAgent`实例,因此输出示例将依赖于该实例的具体实现。例如,如果使用默认参数调用此函数,将返回一个配置了基础语言模型、指定工具集合和默认输出解析器的`StructuredGLM3ChatAgent`实例。这个实例可以直接用于处理聊天对话,执行工具命令,并解析语言模型的输出。
|
||||
***
|
||||
### FunctionDef _agent_type(self)
|
||||
**_agent_type**: 该函数的功能是抛出一个 ValueError 异常。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `_agent_type` 函数是 `StructuredGLM3ChatAgent` 类的一个私有方法,其设计初衷是为了在子类中被重写,用以指定或返回特定的代理类型字符串。在其原始形态中,此函数直接抛出一个 `ValueError` 异常,这表明如果直接调用此方法而没有在子类中进行适当的重写,则会明确地指出这一点。这是一种常见的编程模式,用于强制要求子类实现特定的方法。
|
||||
|
||||
**注意**: 在使用 `StructuredGLM3ChatAgent` 类或其任何子类时,开发者需要确保 `_agent_type` 方法被正确重写以避免运行时错误。此方法的存在强调了一个设计原则,即某些方法是专门设计给子类来实现的,而不是直接在父类中使用。因此,如果你在开发过程中遇到了 `ValueError`,这可能是因为你尝试调用了一个应该被子类重写的方法,但是没有这样做。
|
||||
***
|
||||
## FunctionDef initialize_glm3_agent(tools, llm, prompt, memory, agent_kwargs)
|
||||
**initialize_glm3_agent**: 该函数的功能是初始化一个基于GLM3模型的聊天代理。
|
||||
|
||||
**参数**:
|
||||
- `tools`: 实现了`BaseTool`接口的对象序列,代表聊天代理可以使用的工具。
|
||||
- `llm`: `BaseLanguageModel`的实例,表示基础语言模型。
|
||||
- `prompt`: 字符串类型,用于格式化最终的提示信息,默认为None。
|
||||
- `memory`: `ConversationBufferWindowMemory`的实例,用于存储聊天历史,默认为None。
|
||||
- `agent_kwargs`: 字典类型,包含创建聊天代理时需要的额外参数,默认为None。
|
||||
- `tags`: 字符串序列,用于标记或分类代理,默认为None。
|
||||
- `**kwargs`: 接受任意数量的关键字参数,提供额外的配置选项。
|
||||
|
||||
**代码描述**:
|
||||
`initialize_glm3_agent`函数首先检查是否提供了`tags`参数,并将其转换为列表形式。然后,检查`agent_kwargs`参数是否为None,如果是,则将其初始化为空字典。接下来,使用`StructuredGLM3ChatAgent.from_llm_and_tools`类方法创建一个`StructuredGLM3ChatAgent`实例,该实例基于提供的语言模型、工具集合、提示信息以及`agent_kwargs`中的其他参数。最后,使用`AgentExecutor.from_agent_and_tools`方法创建并返回一个`AgentExecutor`实例,该实例包含了刚刚创建的聊天代理、工具集合、聊天历史以及标签。
|
||||
|
||||
**注意**:
|
||||
- 在使用`initialize_glm3_agent`函数时,确保提供的`tools`和`llm`参数是有效的实例,且`tools`中的每个工具都实现了`BaseTool`接口。
|
||||
- `prompt`参数允许自定义聊天代理的提示信息,可以根据需要提供。
|
||||
- `memory`参数用于存储和管理聊天历史,有助于实现更连贯的对话。
|
||||
- `agent_kwargs`和`**kwargs`提供了额外的灵活性,允许在创建聊天代理时传递额外的配置选项。
|
||||
|
||||
**输出示例**:
|
||||
假设调用`initialize_glm3_agent`函数并提供了必要的参数,可能会返回如下的`AgentExecutor`实例:
|
||||
```
|
||||
AgentExecutor(
|
||||
agent=StructuredGLM3ChatAgent(...),
|
||||
tools=[...],
|
||||
memory=ConversationBufferWindowMemory(...),
|
||||
tags=['example_tag']
|
||||
)
|
||||
```
|
||||
在这个示例中,`AgentExecutor`实例包含了一个配置好的`StructuredGLM3ChatAgent`聊天代理,以及相关的工具集合、聊天历史和标签。这个实例可以直接用于处理聊天对话,执行工具命令,并解析语言模型的输出。
|
||||
128
markdown_docs/server/agent/custom_template.md
Normal file
@ -0,0 +1,128 @@
|
||||
## ClassDef CustomPromptTemplate
|
||||
**CustomPromptTemplate**: CustomPromptTemplate类的功能是根据提供的模板和工具列表,格式化生成一个定制化的提示字符串。
|
||||
|
||||
**属性**:
|
||||
- `template`: 字符串类型,用于定义提示信息的模板。
|
||||
- `tools`: Tool对象的列表,每个Tool对象包含工具的名称和描述。
|
||||
|
||||
**代码描述**:
|
||||
CustomPromptTemplate类继承自StringPromptTemplate,主要用于生成定制化的提示信息。它通过`format`方法接收关键字参数,其中`intermediate_steps`是一个列表,包含了动作和观察的元组。该方法首先将`intermediate_steps`中的信息格式化为字符串,然后将其以及工具的名称和描述添加到模板中,最后返回格式化后的字符串。
|
||||
|
||||
在项目中,CustomPromptTemplate类被用于`server/chat/agent_chat.py/agent_chat/agent_chat_iterator`中,以生成与用户交互的提示信息。通过提供的模板和工具列表,CustomPromptTemplate能够生成包含工具使用说明和中间步骤描述的提示信息,这对于指导用户如何与代理进行交互是非常有用的。特别是在异步的聊天环境中,准确和详细的提示信息能够极大地提升用户体验。
|
||||
|
||||
**注意**:
|
||||
- 在使用CustomPromptTemplate时,需要确保传递给`format`方法的`intermediate_steps`参数格式正确,即包含动作和观察的元组列表。
|
||||
- 工具列表`tools`应包含所有可能会在提示信息中提及的工具,每个工具都应有名称和描述。
|
||||
|
||||
**输出示例**:
|
||||
假设有以下模板和工具列表:
|
||||
- 模板:`"请使用以下工具:{tools}\n{agent_scratchpad}"`
|
||||
- 工具列表:`[Tool(name="Tool1", description="This is tool 1"), Tool(name="Tool2", description="This is tool 2")]`
|
||||
- `intermediate_steps`:`[("action1", "observation1"), ("action2", "observation2")]`
|
||||
|
||||
调用`format`方法后,可能返回的字符串为:
|
||||
```
|
||||
请使用以下工具:
|
||||
Tool1: This is tool 1
|
||||
Tool2: This is tool 2
|
||||
action1
|
||||
Observation: observation1
|
||||
Thought: action2
|
||||
Observation: observation2
|
||||
Thought:
|
||||
```
|
||||
### FunctionDef format(self)
|
||||
**功能**: `format` 函数的功能是根据提供的参数和内部逻辑,格式化并返回一个字符串。
|
||||
|
||||
**参数**:
|
||||
- `**kwargs`: 关键字参数,可以接受多个命名参数,用于动态传递给模板和内部逻辑处理。
|
||||
|
||||
**代码描述**:
|
||||
该函数首先从传入的关键字参数(`kwargs`)中提取出`intermediate_steps`参数。`intermediate_steps`应该是一个包含动作和观察结果的元组列表。函数遍历这个列表,将每个动作的日志和对应的观察结果格式化为字符串,并拼接到`thoughts`字符串中。
|
||||
|
||||
接下来,函数将`thoughts`字符串添加到`kwargs`字典中,键名为`agent_scratchpad`。此外,还会处理`self.tools`,这是一个工具对象列表。函数将每个工具的名称和描述格式化为字符串,并将这些字符串以换行符连接,结果赋值给`kwargs`字典中的`tools`键。同时,将所有工具的名称提取出来,以逗号和空格连接成一个字符串,赋值给`kwargs`字典中的`tool_names`键。
|
||||
|
||||
最后,函数使用`self.template.format(**kwargs)`语句,将处理好的`kwargs`字典作为参数,传递给模板的`format`方法,并返回格式化后的字符串。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`kwargs`中包含`intermediate_steps`键,且其值格式正确。
|
||||
- `self.tools`应该是一个包含有`name`和`description`属性的对象列表。
|
||||
- 该函数依赖于`self.template`的`format`方法,确保`self.template`已正确初始化并可以接受`kwargs`作为参数。
|
||||
|
||||
**输出示例**:
|
||||
```plaintext
|
||||
Action: Move Forward
|
||||
Observation: Wall detected
|
||||
Thought:
|
||||
Tool1: Used for cutting
|
||||
Tool2: Used for digging
|
||||
Tool Names: Tool1, Tool2
|
||||
```
|
||||
***
|
||||
## ClassDef CustomOutputParser
|
||||
**CustomOutputParser**: CustomOutputParser类的功能是解析大模型输出,并根据输出内容决定下一步操作。
|
||||
|
||||
**属性**:
|
||||
- `begin`: 一个布尔值,用于指示解析过程是否应该开始或停止。
|
||||
|
||||
**代码描述**:
|
||||
CustomOutputParser类继承自AgentOutputParser,是一个专门用于解析大模型输出的解析器。它通过分析模型的输出内容,来决定是继续执行某些操作,还是结束会话。具体来说,它会检查模型输出中是否包含特定的关键词或短语,如"Final Answer:"或"Action:",并据此返回相应的操作指令。
|
||||
|
||||
在初始化时,`begin`属性被设置为True,表示解析器准备开始解析输出。在`parse`方法中,首先检查是否所有支持的代理模型都不在模型容器中,并且`begin`为True。如果条件满足,它会查找输出中的停止词(如"Observation:"),并根据这些停止词截断输出,以准备进一步的解析。
|
||||
|
||||
如果输出中包含"Final Answer:",则表示大模型已经给出了最终答案,解析器将重置`begin`为True,并返回一个包含最终答案的AgentFinish对象。如果输出中包含"Action:",则解析器会解析出相应的操作和输入,尝试执行该操作,并返回一个AgentAction对象。如果解析过程中遇到异常,或者输出不符合预期的格式,解析器将返回一个包含错误信息的AgentFinish对象。
|
||||
|
||||
**注意**:
|
||||
- 在使用CustomOutputParser时,需要确保大模型的输出格式与解析器预期的格式相匹配,否则可能无法正确解析出操作指令。
|
||||
- 解析器依赖于输出中的特定关键词或短语来决定操作,因此在设计大模型的输出格式时,需要考虑这一点。
|
||||
|
||||
**输出示例**:
|
||||
假设大模型的输出为"Final Answer: 42",CustomOutputParser解析后可能返回的对象为:
|
||||
```
|
||||
AgentFinish(return_values={"output": "42"}, log="Final Answer: 42")
|
||||
```
|
||||
如果大模型的输出为"Action: Calculate Action Input: 42 + 1",解析后可能返回的对象为:
|
||||
```
|
||||
AgentAction(tool="Calculate", tool_input="42 + 1", log="Action: Calculate Action Input: 42 + 1")
|
||||
```
|
||||
|
||||
在项目中,CustomOutputParser被用于解析大模型在与用户交互过程中的输出,以决定是否需要调用特定的工具或服务来辅助完成用户的请求。这使得整个系统能够更加智能和灵活地处理各种不同的用户需求。
|
||||
### FunctionDef __init__(self)
|
||||
**__init__**: 该函数用于初始化CustomOutputParser对象。
|
||||
|
||||
**参数**: 该函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: 在CustomOutputParser类的__init__方法中,首先通过`super().__init__()`调用父类的构造函数来确保父类被正确初始化。接着,该方法设置了一个实例变量`self.begin`并将其初始化为True。这个变量可能用于标记解析开始,或者用于控制某些只在初始化时需要执行的操作。
|
||||
|
||||
**注意**: 在使用CustomOutputParser类时,不需要手动传递任何参数给__init__方法。创建对象后,可以根据实际需求修改`self.begin`的值,但通常情况下,该变量的初始值True已足够满足大多数使用场景。此外,如果CustomOutputParser类继承自一个具有复杂初始化逻辑的父类,`super().__init__()`确保了这些逻辑不会被遗漏。
|
||||
***
|
||||
### FunctionDef parse(self, llm_output)
|
||||
**parse**: 此函数的功能是解析从大型语言模型(LLM)输出的文本,并根据输出内容决定下一步的操作。
|
||||
|
||||
**参数**:
|
||||
- `llm_output`: 字符串类型,代表从大型语言模型(LLM)接收到的输出文本。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先检查是否有支持的代理模型存在于`model_container.MODEL`中,并且是否是开始解析。如果是开始解析且没有支持的代理模型,它会查找输出中的停止词(例如"Observation:"),并截取至第一个停止词之前的文本作为新的输出文本。
|
||||
|
||||
如果输出文本中包含"Final Answer:",则表示大型语言模型已经给出了最终答案。此时,函数会将"Final Answer:"之后的文本作为输出,并标记为解析结束。
|
||||
|
||||
如果输出文本中包含"Action:",则表示需要执行特定的动作。函数会解析出动作名称和动作输入,然后尝试执行该动作。如果执行成功,会返回一个`AgentAction`对象,包含动作名称、动作输入和原始日志。
|
||||
|
||||
如果上述条件都不满足,或者在解析动作时遇到异常,函数会返回一个`AgentFinish`对象,表示解析结束,同时包含错误信息或大模型自身的回答。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保`model_container.MODEL`和`SUPPORT_AGENT_MODEL`已正确设置,以便函数能够正确判断是否有支持的代理模型。
|
||||
- 函数的返回值类型可能是`AgentFinish`、`tuple[dict[str, str], str]`或`AgentAction`,调用者需要根据返回值类型进行相应的处理。
|
||||
|
||||
**输出示例**:
|
||||
假设`llm_output`为"Final Answer: 42",则函数可能返回的示例为:
|
||||
```python
|
||||
AgentFinish(return_values={"output": "42"}, log="Final Answer: 42")
|
||||
```
|
||||
|
||||
如果`llm_output`为"Action: Email Action Input: john.doe@example.com",则函数可能返回的示例为:
|
||||
```python
|
||||
AgentAction(tool="Email", tool_input="john.doe@example.com", log="Action: Email Action Input: john.doe@example.com")
|
||||
```
|
||||
***
|
||||
29
markdown_docs/server/agent/model_contain.md
Normal file
@ -0,0 +1,29 @@
|
||||
## ClassDef ModelContainer
|
||||
**ModelContainer**: ModelContainer 类的功能是作为模型和数据库的容器。
|
||||
|
||||
**属性**:
|
||||
- MODEL: 用于存储模型实例。初始值为 None,表示在创建 ModelContainer 实例时,并没有预设的模型。
|
||||
- DATABASE: 用于存储数据库连接实例。初始值同样为 None,表示在创建 ModelContainer 实例时,并没有预设的数据库连接。
|
||||
|
||||
**代码描述**:
|
||||
ModelContainer 类是一个简单的容器类,设计用来存储模型实例和数据库连接实例。这个类通过定义两个属性 `MODEL` 和 `DATABASE` 来实现其功能。这两个属性在类的初始化方法 `__init__` 中被设置为 None,这意味着在创建 ModelContainer 的实例时,这两个属性都不会持有任何值。这种设计允许开发者在创建 ModelContainer 实例后,根据需要将模型实例和数据库连接实例分别赋值给这两个属性。
|
||||
|
||||
**注意**:
|
||||
- 在使用 ModelContainer 类时,开发者需要注意,`MODEL` 和 `DATABASE` 属性在初始状态下是 None。因此,在尝试访问这些属性或其方法之前,需要确保它们已被正确赋值,以避免遇到 `NoneType` 对象没有该方法的错误。
|
||||
- ModelContainer 类提供了一种灵活的方式来管理模型和数据库连接,但它本身不提供任何方法来初始化 `MODEL` 和 `DATABASE` 属性。开发者需要根据自己的需求,手动为这两个属性赋值。
|
||||
- 由于 ModelContainer 类的设计相对简单,它可以根据项目的需要进行扩展,例如添加更多的属性或方法来满足更复杂的需求。
|
||||
### FunctionDef __init__(self)
|
||||
**__init__**: 此函数用于初始化ModelContainer类的实例。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: 在ModelContainer类的实例被创建时,`__init__`函数会被自动调用。此函数主要完成以下几点初始化操作:
|
||||
- 将`MODEL`属性设置为`None`。这意味着在实例化后,该属性暂时不关联任何模型,需要后续根据具体需求进行赋值。
|
||||
- 将`DATABASE`属性也设置为`None`。这表明在实例化的初始阶段,该属性不关联任何数据库,同样需要在后续操作中根据需要进行关联。
|
||||
|
||||
通过这种方式,`__init__`函数为ModelContainer类的实例提供了一个清晰、干净的初始状态,便于后续的属性赋值和方法调用。
|
||||
|
||||
**注意**:
|
||||
- 在使用ModelContainer类创建实例后,需要根据实际情况给`MODEL`和`DATABASE`属性赋予具体的模型和数据库实例,以便于进行后续的操作。
|
||||
- 由于`MODEL`和`DATABASE`在初始化时都被设置为`None`,在对这两个属性进行操作前,建议先检查它们是否已被正确赋值,以避免在使用未初始化的属性时引发错误。
|
||||
***
|
||||
36
markdown_docs/server/agent/tools/arxiv.md
Normal file
@ -0,0 +1,36 @@
|
||||
## FunctionDef arxiv(query)
|
||||
**arxiv**: 该函数用于执行对Arxiv的查询操作。
|
||||
|
||||
**参数**:
|
||||
- **query**: 字符串类型,表示要在Arxiv上执行的查询内容。
|
||||
|
||||
**代码描述**:
|
||||
`arxiv`函数是一个简单但功能强大的接口,用于在Arxiv数据库中执行查询。它首先创建了一个`ArxivQueryRun`的实例,然后调用该实例的`run`方法来执行查询。查询的具体内容由参数`query`指定,该参数应为一个字符串,表示用户希望在Arxiv上搜索的关键词或查询表达式。
|
||||
|
||||
在项目结构中,`arxiv`函数位于`server/agent/tools/arxiv.py`路径下,并且是`arxiv.py`模块中定义的核心功能之一。尽管在当前项目的其他部分,如`server/agent/tools/__init__.py`和`server/agent/tools_select.py`中没有直接的调用示例,但可以推断`arxiv`函数设计为被这些模块或其他项目部分调用,以实现对Arxiv数据库的查询功能。
|
||||
|
||||
**注意**:
|
||||
- 在使用`arxiv`函数时,需要确保传入的查询字符串`query`是有效的,即它应该符合Arxiv的查询语法和要求。
|
||||
- 该函数的执行结果依赖于`ArxivQueryRun`类的`run`方法的实现,因此需要确保该方法能够正确处理传入的查询字符串,并返回期望的查询结果。
|
||||
|
||||
**输出示例**:
|
||||
假设对`arxiv`函数的调用如下:
|
||||
```python
|
||||
result = arxiv("deep learning")
|
||||
```
|
||||
则该函数可能返回一个包含查询结果的对象,例如包含多篇关于深度学习的论文的列表。具体的返回值格式将取决于`ArxivQueryRun`类的`run`方法的实现细节。
|
||||
## ClassDef ArxivInput
|
||||
**ArxivInput**: ArxivInput类的功能是定义一个用于搜索查询的输入模型。
|
||||
|
||||
**属性**:
|
||||
- query: 表示搜索查询标题的字符串。
|
||||
|
||||
**代码描述**:
|
||||
ArxivInput类继承自BaseModel,这意味着它是一个模型类,用于定义数据结构。在这个类中,定义了一个名为`query`的属性,该属性是一个字符串类型,用于存储用户的搜索查询标题。通过使用`Field`函数,为`query`属性提供了一个描述,即"The search query title",这有助于理解该属性的用途。
|
||||
|
||||
在项目中,ArxivInput类作为一个数据模型,被用于处理与arXiv相关的搜索查询。尽管在提供的代码调用情况中没有直接的示例,但可以推断,该类可能会被用于在`server/agent/tools`目录下的其他模块中,作为接收用户搜索请求的输入参数。这样的设计使得代码更加模块化,便于维护和扩展。
|
||||
|
||||
**注意**:
|
||||
- 在使用ArxivInput类时,需要确保传入的`query`参数是一个有效的字符串,因为它将直接影响搜索结果的相关性和准确性。
|
||||
- 由于ArxivInput继承自BaseModel,可以利用Pydantic库提供的数据验证功能,确保输入数据的合法性。
|
||||
- 考虑到ArxivInput类可能会被用于网络请求,应当注意处理潜在的安全问题,如SQL注入或跨站脚本攻击(XSS),确保用户输入被适当地清理和验证。
|
||||
32
markdown_docs/server/agent/tools/calculate.md
Normal file
@ -0,0 +1,32 @@
|
||||
## ClassDef CalculatorInput
|
||||
**CalculatorInput**: CalculatorInput类的功能是定义计算器输入的数据结构。
|
||||
|
||||
**属性**:
|
||||
- `query`: 表示计算器查询的字符串,是一个必填字段。
|
||||
|
||||
**代码描述**:
|
||||
CalculatorInput类继承自BaseModel,这表明它是使用Pydantic库创建的,用于数据验证和设置。在这个类中,定义了一个属性`query`,它是一个字符串类型的字段。通过使用`Field()`函数,我们可以为这个字段添加额外的验证或描述信息,虽然在当前的代码示例中没有显示出来。这个类的主要作用是作为计算器服务的输入数据模型,确保传入的查询是有效且符合预期格式的字符串。
|
||||
|
||||
从项目结构来看,CalculatorInput类位于`server/agent/tools/calculate.py`文件中,但是在提供的项目信息中,并没有直接的代码示例显示这个类是如何被其他对象调用的。然而,基于它的定义和位置,我们可以推断CalculatorInput类可能被用于处理来自于`server/agent/tools`目录下其他模块的计算请求。例如,它可能被用于验证和解析用户输入,然后这些输入将被传递给实际执行计算的逻辑。
|
||||
|
||||
**注意**:
|
||||
- 使用CalculatorInput类时,需要确保传入的`query`字段是一个有效的字符串,因为这是进行计算前的必要条件。
|
||||
- 由于CalculatorInput使用了Pydantic库,开发者需要熟悉Pydantic的基本使用方法,以便正确地定义和使用数据模型。
|
||||
- 虽然当前的CalculatorInput类定义相对简单,但开发者可以根据实际需求,通过添加更多的字段或使用Pydantic提供的更高级的验证功能来扩展它。
|
||||
## FunctionDef calculate(query)
|
||||
**calculate**: 此函数的功能是执行数学计算查询。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,表示需要进行计算的数学查询语句。
|
||||
|
||||
**代码描述**:
|
||||
`calculate` 函数是一个用于执行数学计算的函数。它首先从`model_container`中获取一个模型实例,该模型被假定为已经加载并准备好处理数学计算查询。接着,使用`LLMMathChain.from_llm`方法创建一个`LLMMathChain`实例,这个实例能够利用提供的模型(`model`)来处理数学计算。在创建`LLMMathChain`实例时,会传入模型和一个标志`verbose=True`以及一个提示`PROMPT`,这表明在执行计算时会有更详细的输出信息。最后,通过调用`LLMMathChain`实例的`run`方法,传入用户的查询(`query`),执行实际的计算,并将计算结果返回。
|
||||
|
||||
在项目中,尽管`server/agent/tools/__init__.py`和`server/agent/tools_select.py`这两个对象的代码和文档未提供详细信息,但可以推断`calculate`函数可能被设计为一个核心的数学计算工具,供项目中的其他部分调用以执行具体的数学计算任务。这种设计使得数学计算功能模块化,便于在不同的上下文中重用和维护。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用此函数之前,`model_container.MODEL`已正确加载并初始化,因为这是执行计算的关键。
|
||||
- 由于函数使用了`verbose=True`,调用时会产生详细的日志输出,这对于调试和分析计算过程很有帮助,但在生产环境中可能需要根据实际情况调整。
|
||||
|
||||
**输出示例**:
|
||||
假设传入的`query`为"2 + 2",函数可能返回一个类似于`"4"`的字符串,表示计算结果。实际返回值将依赖于模型的具体实现和处理能力。
|
||||
61
markdown_docs/server/agent/tools/search_internet.md
Normal file
@ -0,0 +1,61 @@
|
||||
## FunctionDef search_engine_iter(query)
|
||||
**search_engine_iter**: 该函数用于通过指定的搜索引擎异步检索查询内容,并生成相关的回答。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的查询内容,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_engine_iter`函数是一个异步函数,主要用于处理用户的查询请求。它首先调用`search_engine_chat`函数,向指定的搜索引擎(本例中为Bing)发送查询请求,并设置了一系列参数,包括模型名称、温度值、历史记录、返回结果的数量、最大Token数、提示名称以及是否以流式传输的方式返回结果。这些参数的设置旨在优化搜索结果的相关性和质量。
|
||||
|
||||
在调用`search_engine_chat`后,函数通过异步迭代器`response.body_iterator`遍历响应体。每次迭代返回的数据是一个JSON字符串,包含了搜索引擎返回的答案和相关文档。函数解析这些JSON字符串,提取出答案和文档信息,并将答案内容累加到`contents`变量中。
|
||||
|
||||
最终,函数返回累加后的`contents`变量,即包含了所有相关答案的字符串。
|
||||
|
||||
**注意**:
|
||||
- 该函数是异步的,因此在调用时需要使用`await`关键字或在异步环境中调用。
|
||||
- 函数的执行依赖于外部的搜索引擎服务和LLM模型,因此执行时间可能受到网络状况和服务响应时间的影响。
|
||||
- 在使用该函数之前,需要确保已经配置了相应的搜索引擎API密钥和LLM模型。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
"根据您的查询,这里是生成的回答。"
|
||||
```
|
||||
该输出示例展示了函数可能返回的答案内容。实际返回的内容将根据查询内容和搜索引擎返回的结果而有所不同。
|
||||
## FunctionDef search_internet(query)
|
||||
**search_internet**: 该函数用于通过异步方式调用搜索引擎,检索用户查询的内容。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的查询内容,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_internet`函数是一个简洁的接口,用于触发对指定查询内容的互联网搜索。它通过调用`search_engine_iter`函数实现,后者是一个异步函数,负责具体的搜索操作和处理逻辑。在`search_internet`函数中,使用`asyncio.run`方法来运行`search_engine_iter`函数,这允许同步代码中方便地调用异步函数,并等待其结果。
|
||||
|
||||
`search_engine_iter`函数详细描述了搜索过程,包括向搜索引擎发送请求、处理返回的数据,并最终将累加的答案内容作为字符串返回。这个过程涉及到异步编程的知识,特别是在处理网络请求和响应时的异步迭代。
|
||||
|
||||
**注意**:
|
||||
- 由于`search_internet`函数内部使用了`asyncio.run`,它不应该被用在已经运行的异步函数或事件循环中,以避免抛出异常。
|
||||
- 函数的执行效率和结果质量依赖于外部搜索引擎的响应速度和准确性,因此在网络状况不佳或搜索引擎服务不稳定时,可能会影响使用体验。
|
||||
- 在使用之前,确保相关的搜索引擎API密钥和配置已经正确设置,以保证搜索功能的正常工作。
|
||||
|
||||
**输出示例**:
|
||||
假设用户查询的内容为“Python 异步编程”,函数可能返回的字符串示例为:
|
||||
```
|
||||
"Python异步编程是一种编程范式,旨在提高程序的并发性和性能。这里是一些关于Python异步编程的基础知识和实践指南。"
|
||||
```
|
||||
该示例展示了函数可能返回的答案内容,实际返回的内容将根据查询内容和搜索引擎返回的结果而有所不同。
|
||||
## ClassDef SearchInternetInput
|
||||
**SearchInternetInput**: SearchInternetInput类的功能是定义一个用于互联网搜索的输入模型。
|
||||
|
||||
**属性**:
|
||||
- location: 用于互联网搜索的查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
SearchInternetInput类继承自BaseModel,这意味着它是一个模型类,通常用于处理数据的验证、序列化和反序列化。在这个类中,定义了一个名为`location`的属性,该属性用于存储用户希望进行搜索的查询字符串。通过使用Pydantic库中的`Field`函数,为`location`属性提供了一个描述性文本,即"Query for Internet search",这有助于理解该属性的用途。
|
||||
|
||||
该类在项目中的作用是作为搜索互联网功能的输入数据模型。它的设计允许开发者在调用搜索互联网相关功能时,能够以结构化的方式提供必要的输入信息,即用户想要搜索的内容。这种方式提高了代码的可读性和易用性,同时也便于后续的数据验证和处理。
|
||||
|
||||
从项目结构来看,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`两个文件中没有直接提到SearchInternetInput类的使用,但可以推断,SearchInternetInput类可能会被项目中负责处理搜索请求的部分调用。具体来说,开发者可能会在处理搜索请求的函数或方法中,实例化SearchInternetInput类,然后根据用户的输入构造location属性,最后使用这个实例来执行搜索操作。
|
||||
|
||||
**注意**:
|
||||
- 在使用SearchInternetInput类时,开发者需要确保提供的`location`值是有效的搜索查询字符串,因为这将直接影响搜索结果的相关性和准确性。
|
||||
- 考虑到数据验证的需求,开发者在使用此类时应当熟悉Pydantic库的基本用法,以便充分利用模型验证等功能。
|
||||
202
markdown_docs/server/agent/tools/search_knowledgebase_complex.md
Normal file
@ -0,0 +1,202 @@
|
||||
## FunctionDef search_knowledge_base_iter(database, query)
|
||||
**search_knowledge_base_iter**: 该函数用于异步迭代地搜索知识库并获取相关信息。
|
||||
|
||||
**参数**:
|
||||
- `database`: 字符串类型,指定要搜索的知识库名称。
|
||||
- `query`: 字符串类型,用户的查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_knowledge_base_iter` 函数是一个异步函数,它接受两个参数:`database` 和 `query`。这个函数主要通过调用 `knowledge_base_chat` 函数来实现与知识库的交互。在调用 `knowledge_base_chat` 时,会传入相关参数,包括知识库名称、查询字符串、模型名称、温度参数、历史记录、向量搜索的 top_k 值、最大 token 数、prompt 名称、分数阈值以及是否以流的形式输出。这些参数的具体值部分来自于全局变量或函数外部的变量。
|
||||
|
||||
函数内部通过异步迭代 `response.body_iterator` 来逐个处理返回的数据。每次迭代得到的数据是一个 JSON 字符串,包含了回答和相关文档信息。函数将这些回答累加起来,并在最后返回累加后的字符串。
|
||||
|
||||
**注意**:
|
||||
- 该函数是异步的,因此在调用时需要使用 `await` 关键字。
|
||||
- 函数内部处理了 JSON 数据,因此需要导入 `json` 模块。
|
||||
- 在使用该函数之前,需要确保 `knowledge_base_chat` 函数及其所需的环境和参数已经正确配置和初始化。
|
||||
|
||||
**输出示例**:
|
||||
调用 `search_knowledge_base_iter` 函数可能返回的字符串示例:
|
||||
```
|
||||
"这是根据您的查询生成的回答。出处 [1] [文档名称](文档链接) \n\n文档内容\n\n未找到相关文档,该回答为大模型自身能力解答!"
|
||||
```
|
||||
该字符串包含了所有回答的累加结果,如果有相关文档,还会包含文档的链接和内容。如果没有找到相关文档,会有相应的提示信息。
|
||||
## FunctionDef search_knowledge_multiple(queries)
|
||||
**search_knowledge_multiple**: 该函数用于异步地搜索多个知识库并获取相关信息。
|
||||
|
||||
**参数**:
|
||||
- `queries`: 一个列表,包含多个元组,每个元组包含一个数据库名称和一个查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_knowledge_multiple` 函数是一个异步函数,它接收一个包含多个(数据库名称,查询字符串)元组的列表作为参数。函数内部首先会为列表中的每个查询创建一个异步任务,这些任务是通过调用 `search_knowledge_base_iter` 函数实现的,该函数负责与指定的知识库进行交互并获取查询结果。之后,使用 `asyncio.gather` 函数并行执行这些异步任务,并等待所有任务完成,收集它们的结果。
|
||||
|
||||
对于每个查询的结果,函数会生成一个包含自定义消息和查询结果的字符串。这个自定义消息包括了知识库的名称,以及一个提示信息,表明这些信息是从哪个知识库查询到的。所有这些生成的字符串会被收集到一个列表中,并作为函数的返回值。
|
||||
|
||||
**注意**:
|
||||
- 由于 `search_knowledge_multiple` 是一个异步函数,因此在调用它时需要使用 `await` 关键字。
|
||||
- 函数的执行依赖于 `search_knowledge_base_iter` 函数,后者需要正确配置和初始化,包括知识库的访问设置和查询参数。
|
||||
- 该函数的设计使得可以同时对多个知识库进行查询,提高了查询效率。
|
||||
|
||||
**输出示例**:
|
||||
调用 `search_knowledge_multiple` 函数可能返回的列表示例:
|
||||
```
|
||||
[
|
||||
"\n查询到 database1 知识库的相关信息:\n这是根据您的查询生成的回答。出处 [1] [文档名称](文档链接) \n\n文档内容\n\n未找到相关文档,该回答为大模型自身能力解答!",
|
||||
"\n查询到 database2 知识库的相关信息:\n这是根据您的查询生成的回答。出处 [1] [文档名称](文档链接) \n\n文档内容\n\n未找到相关文档,该回答为大模型自身能力解答!"
|
||||
]
|
||||
```
|
||||
该输出示例展示了当对两个不同的知识库进行查询时,每个查询结果前都会添加一个指明知识库来源的自定义消息,随后是查询到的具体信息。
|
||||
## FunctionDef search_knowledge(queries)
|
||||
Doc is waiting to be generated...
|
||||
## ClassDef LLMKnowledgeChain
|
||||
Doc is waiting to be generated...
|
||||
### ClassDef Config
|
||||
**Config**: Config 类的功能是定义一个严格的配置模式,用于pydantic对象。
|
||||
|
||||
**属性**:
|
||||
- `extra`: 控制额外字段的处理方式。
|
||||
- `arbitrary_types_allowed`: 允许使用任意类型的字段。
|
||||
|
||||
**代码描述**:
|
||||
Config 类是一个配置类,专门用于在使用pydantic库时定义模型的配置。在这个类中,定义了两个重要的配置项:
|
||||
|
||||
1. `extra = Extra.forbid`:这个配置项用于指定当传入的数据包含模型未声明的字段时应如何处理。通过设置为`Extra.forbid`,表示禁止传入额外的字段,如果尝试传入未在模型中声明的字段,将会引发错误。这有助于确保数据的严格匹配和类型安全,避免因数据错误或不匹配而导致的问题。
|
||||
|
||||
2. `arbitrary_types_allowed = True`:这个配置项允许在模型中使用任意类型的字段。默认情况下,pydantic要求所有字段的类型都是预先定义好的,但开启这个选项后,可以使用任何类型的字段,包括自定义类型。这提供了更大的灵活性,允许开发者根据需要在模型中使用各种复杂或自定义的数据类型。
|
||||
|
||||
**注意**:
|
||||
- 使用`extra = Extra.forbid`时,需要确保所有传入的数据严格匹配模型定义的字段,否则会引发错误。这要求开发者在设计模型和处理数据时需要更加小心和精确。
|
||||
- 开启`arbitrary_types_allowed = True`可以提高模型的灵活性,但同时也需要开发者确保自定义类型的正确使用和处理,以避免类型错误或其他潜在问题。
|
||||
***
|
||||
### FunctionDef raise_deprecation(cls, values)
|
||||
**raise_deprecation**: 此函数的功能是在使用已弃用方法实例化LLMKnowledgeChain时发出警告,并在适当的情况下自动转换为推荐的实例化方法。
|
||||
|
||||
**参数**:
|
||||
- `cls`: 类方法的第一个参数,表示类本身。
|
||||
- `values`: 一个字典,包含实例化LLMKnowledgeChain时传递的参数。
|
||||
|
||||
**代码描述**:
|
||||
`raise_deprecation` 函数首先检查传入的 `values` 字典中是否包含键 `"llm"`。如果存在,这意味着尝试使用已弃用的方法直接通过 `llm` 参数实例化 `LLMKnowledgeChain`。此时,函数会发出一个警告,提示开发者这种实例化方法已弃用,并建议使用 `llm_chain` 参数或 `from_llm` 类方法作为替代。
|
||||
|
||||
如果在 `values` 中同时不存在 `"llm_chain"` 键,且 `"llm"` 键对应的值不为 `None`,函数会进一步处理。它会尝试从 `values` 中获取 `"prompt"` 键的值,如果不存在,则使用全局变量 `PROMPT` 的值。然后,利用 `llm` 和 `prompt` 的值创建一个 `LLMChain` 实例,并将这个实例赋值给 `values` 字典中的 `"llm_chain"` 键。
|
||||
|
||||
最后,函数返回更新后的 `values` 字典。
|
||||
|
||||
**注意**:
|
||||
- 使用此函数时,应确保传入的 `values` 字典中的 `"llm"` 键(如果存在)对应的值是有效的,因为这将影响到 `LLMChain` 实例的创建。
|
||||
- 应避免直接使用已弃用的实例化方法,以免在未来的版本中遇到兼容性问题。
|
||||
|
||||
**输出示例**:
|
||||
假设传入的 `values` 字典为 `{"llm": some_llm_object}`,且 `PROMPT` 为默认提示文本,函数可能返回如下的字典:
|
||||
```python
|
||||
{
|
||||
"llm": some_llm_object,
|
||||
"llm_chain": LLMChain(llm=some_llm_object, prompt=默认提示文本)
|
||||
}
|
||||
```
|
||||
这表明,即使最初尝试使用已弃用的方法实例化,函数也会自动调整,确保以推荐的方式实例化 `LLMKnowledgeChain`。
|
||||
***
|
||||
### FunctionDef input_keys(self)
|
||||
**函数功能**: `input_keys` 的功能是返回期望的输入键列表。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `input_keys` 函数是 `LLMKnowledgeChain` 类的一个方法,它的主要作用是返回一个包含单个元素的列表,这个元素是该实例的 `input_key` 属性。这个方法被标记为私有,意味着它仅在 `LLMKnowledgeChain` 类的内部使用,不建议在类的外部直接调用这个方法。这种设计通常用于封装和隐藏类的内部实现细节,确保类的公共接口的简洁性和稳定性。
|
||||
|
||||
**注意**: 由于 `input_keys` 方法被标记为私有(通过 `:meta private:` 注释指示),在使用 `LLMKnowledgeChain` 类时,应避免直接调用此方法。相反,应通过类提供的其他公共方法来间接访问或修改 `input_key` 的值。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
["example_input_key"]
|
||||
```
|
||||
在这个示例中,假设 `LLMKnowledgeChain` 实例的 `input_key` 属性值为 `"example_input_key"`,那么调用 `input_keys` 方法将返回一个包含这个字符串的列表。这表明该实例期望的输入键仅有一个,即 `"example_input_key"`。
|
||||
***
|
||||
### FunctionDef output_keys(self)
|
||||
**output_keys**: 此函数的功能是返回一个包含输出键的列表。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `output_keys` 函数是 `LLMKnowledgeChain` 类的一个成员方法,它的作用是返回一个列表,这个列表中包含了一个元素,即 `self.output_key`。这里的 `self.output_key` 是 `LLMKnowledgeChain` 实例的一个属性,代表了某种输出的关键字。此函数被标记为私有方法(通过 `:meta private:` 注释),这意味着它主要供类内部其他方法调用,而不是设计给外部使用。
|
||||
|
||||
**注意**: 由于此函数被标记为私有,因此在使用 `LLMKnowledgeChain` 类时,应避免直接调用 `output_keys` 方法,而是通过类提供的其他公共接口来间接获取所需的输出键信息。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
['desired_output_key']
|
||||
```
|
||||
在这个示例中,`'desired_output_key'` 是 `self.output_key` 的值,表示此实例期望得到的输出键。返回值是一个列表,即使只有一个输出键,也会以列表的形式返回,这样做可以保持接口的一致性和扩展性。
|
||||
***
|
||||
### FunctionDef _evaluate_expression(self, queries)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _process_llm_result(self, llm_output, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _aprocess_llm_result(self, llm_output, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _call(self, inputs, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _acall(self, inputs, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _chain_type(self)
|
||||
**函数名**: _chain_type
|
||||
|
||||
**函数功能**: 返回链类型的字符串表示。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `_chain_type`函数是`LLMKnowledgeChain`类的一个私有方法,用于返回表示链类型的字符串。在这个上下文中,链类型被固定定义为`"llm_knowledge_chain"`,这意味着该函数返回的字符串用于标识或表示一个基于长期记忆模型(Long-term Language Model,简称LLM)的知识链。这个标识符可以被用来在处理不同类型的知识链时,区分出是基于LLM的知识链。由于这是一个私有方法,它主要被类内部的其他方法调用,而不是被类的外部直接调用。
|
||||
|
||||
**注意**: 由于`_chain_type`是一个私有方法,它应该只在`LLMKnowledgeChain`类的内部被使用。尝试从类的外部直接调用这个方法可能会导致访问控制错误或不被期待的行为。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
"llm_knowledge_chain"
|
||||
```
|
||||
此输出示例展示了调用`_chain_type`方法时会返回的字符串。这个字符串可以被视为一个标识符,用于在可能存在多种类型的知识链时,识别出特定的基于LLM的知识链。
|
||||
***
|
||||
### FunctionDef from_llm(cls, llm, prompt)
|
||||
**from_llm**: 此函数的功能是从语言模型创建一个知识链对象。
|
||||
|
||||
**参数**:
|
||||
- `cls`: 类方法的第一个参数,指代当前类,用于创建类的实例。
|
||||
- `llm`: BaseLanguageModel的实例,代表要使用的语言模型。
|
||||
- `prompt`: BasePromptTemplate的实例,默认为PROMPT,用于生成查询时的提示模板。
|
||||
- `**kwargs`: 接受任意数量的关键字参数,这些参数将传递给LLMKnowledgeChain的构造函数。
|
||||
|
||||
**代码描述**:
|
||||
`from_llm`是一个类方法,它接受一个语言模型实例和可选的提示模板,以及其他任意关键字参数。此方法首先创建一个`LLMChain`实例,该实例封装了语言模型和提示模板的细节。然后,它使用这个`LLMChain`实例和任何其他提供的关键字参数来创建并返回一个`LLMKnowledgeChain`实例。这个过程允许将语言模型和相关配置封装为一个可用于执行复杂知识搜索任务的链式对象。
|
||||
|
||||
在项目中,`from_llm`方法被`search_knowledgebase_complex`函数调用。在这个调用中,它使用从模型容器中获取的模型实例和一个`verbose`关键字参数来创建一个`LLMKnowledgeChain`实例。然后,这个实例被用来对一个查询执行运行操作,以获取答案。这展示了`from_llm`方法如何允许灵活地构建知识链,以便在复杂的知识搜索任务中使用。
|
||||
|
||||
**注意**:
|
||||
- 确保传递给`from_llm`的`llm`参数是一个有效的`BaseLanguageModel`实例,因为它是执行知识搜索所必需的。
|
||||
- `prompt`参数虽然是可选的,但正确设置它可以显著影响知识搜索的效果,因此建议根据具体的应用场景进行适当配置。
|
||||
- 通过`**kwargs`传递的任何额外参数应该与`LLMKnowledgeChain`的构造函数兼容,以确保它们可以正确地被使用。
|
||||
|
||||
**输出示例**:
|
||||
假设`from_llm`方法被正确调用,它可能返回如下的`LLMKnowledgeChain`实例:
|
||||
```
|
||||
LLMKnowledgeChain(llm_chain=LLMChain(llm=<BaseLanguageModel实例>, prompt=<BasePromptTemplate实例>), verbose=True)
|
||||
```
|
||||
这个实例随后可以用于执行具体的知识搜索任务。
|
||||
***
|
||||
## FunctionDef search_knowledgebase_complex(query)
|
||||
Doc is waiting to be generated...
|
||||
## ClassDef KnowledgeSearchInput
|
||||
**KnowledgeSearchInput**: KnowledgeSearchInput类的功能是定义一个用于搜索知识库的输入模型。
|
||||
|
||||
**属性**:
|
||||
- location: 用于搜索的查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
KnowledgeSearchInput类继承自BaseModel,这表明它是一个模型类,用于定义数据结构和类型。在这个类中,定义了一个名为`location`的属性,该属性被标记为一个字符串类型。通过使用`Field`函数,为`location`属性提供了额外的描述信息,即“要被搜索的查询”。这样的设计使得KnowledgeSearchInput类不仅仅是一个数据容器,还通过属性描述增强了代码的可读性和易用性。
|
||||
|
||||
在项目中,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`这两个对象中没有直接提到KnowledgeSearchInput类的使用,但可以推断,KnowledgeSearchInput类作为一个数据模型,可能会被项目中负责搜索知识库功能的部分调用。具体来说,它可能被用于封装用户输入的搜索查询,然后这个封装好的查询被传递给执行搜索的函数或方法,以便根据`location`属性中的值来检索相关的知识库条目。
|
||||
|
||||
**注意**:
|
||||
- 在使用KnowledgeSearchInput类时,需要确保传递给`location`属性的值是一个合法的字符串,因为这将直接影响到搜索的结果。
|
||||
- 由于KnowledgeSearchInput类继承自BaseModel,因此可以利用Pydantic库提供的数据验证功能来确保输入数据的有效性。这意味着在实例化KnowledgeSearchInput对象时,如果传递的数据类型不符合预期,将会抛出错误,从而帮助开发者及早发现并修正问题。
|
||||
218
markdown_docs/server/agent/tools/search_knowledgebase_once.md
Normal file
@ -0,0 +1,218 @@
|
||||
## FunctionDef search_knowledge_base_iter(database, query)
|
||||
**search_knowledge_base_iter**: 该函数用于异步迭代地搜索知识库并获取相关回答。
|
||||
|
||||
**参数**:
|
||||
- `database`: 知识库的名称,类型为字符串。
|
||||
- `query`: 用户的查询语句,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_knowledge_base_iter` 函数是一个异步函数,它接收两个参数:`database` 和 `query`。这个函数首先调用 `knowledge_base_chat` 函数,向指定的知识库发送查询请求,并设置了一系列参数,如模型名称、温度值、历史记录、向量搜索的 top_k 值、最大 token 数、提示名称、分数阈值以及是否以流的形式输出。这些参数的设置是为了精确控制知识库搜索和回答生成的行为。
|
||||
|
||||
函数内部,通过异步迭代 `response.body_iterator`,处理每一块返回的数据。每一块数据被假定为一个 JSON 字符串,其中包含了回答和相关文档的信息。函数解析这些 JSON 数据,提取出回答内容,并将它们拼接起来。同时,也会处理相关文档的信息,但在当前代码实现中,文档信息 (`docs`) 被提取出来之后并没有被进一步使用。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保 `database` 参数指定的知识库存在,否则可能无法正常获取回答。
|
||||
- 由于函数内部涉及异步操作,调用此函数时需要使用 `await` 关键字。
|
||||
- 函数返回的是拼接后的回答内容,如果需要获取更详细的信息(如相关文档信息),可能需要对函数进行适当的修改。
|
||||
|
||||
**输出示例**:
|
||||
调用 `search_knowledge_base_iter` 函数可能返回的示例:
|
||||
```json
|
||||
"这是根据您的查询生成的回答。"
|
||||
```
|
||||
这个输出示例仅展示了回答内容的一部分。实际返回的回答内容将根据查询语句和知识库的内容而有所不同。
|
||||
## ClassDef LLMKnowledgeChain
|
||||
Doc is waiting to be generated...
|
||||
### ClassDef Config
|
||||
**Config**: Config 类的功能是定义一个严格的配置对象模型。
|
||||
|
||||
**属性**:
|
||||
- `extra`: 控制额外字段的处理方式。
|
||||
- `arbitrary_types_allowed`: 允许使用任意类型的字段。
|
||||
|
||||
**代码描述**:
|
||||
Config 类是一个配置对象,它使用 Pydantic 库来定义。Pydantic 是一个数据验证和设置管理的库,它允许开发者以标准的Python类型提示方式来定义数据结构,同时提供强大的数据验证功能。
|
||||
|
||||
在这个 Config 类中,有两个关键的配置项被设置:
|
||||
|
||||
1. `extra = Extra.forbid`:这个设置指定了如果传入的数据包含了模型未声明的字段,则会抛出错误。这是一种严格的数据验证方式,确保了数据对象的纯净性和一致性,防止了意外的数据被接受进来。
|
||||
|
||||
2. `arbitrary_types_allowed = True`:这个设置允许模型字段使用任意类型。默认情况下,Pydantic 要求所有的字段类型都是标准的Python类型或者是 Pydantic 定义的类型。通过启用这个选项,开发者可以使用更加灵活的类型定义,比如自定义类或者其他复杂的数据结构。
|
||||
|
||||
**注意**:
|
||||
- 使用 Config 类时,需要注意数据的严格性和类型的灵活性之间的平衡。虽然允许任意类型可以提供更大的灵活性,但也可能增加数据处理的复杂性。
|
||||
- 在实际应用中,应当根据具体需求来决定是否启用 `arbitrary_types_allowed` 选项。如果项目中使用了大量自定义类型,那么启用这个选项可能是有益的。反之,如果项目主要使用标准类型,可能不需要启用这个选项。
|
||||
- `extra = Extra.forbid` 的设置使得 Config 类非常适合用于需要高数据一致性和安全性的场景。开发者应当在设计API或数据交互接口时考虑到这一点。
|
||||
***
|
||||
### FunctionDef raise_deprecation(cls, values)
|
||||
**raise_deprecation**: 此函数的功能是在使用已弃用的方式实例化LLMKnowledgeChain时发出警告,并在适当的情况下自动转换为推荐的实例化方式。
|
||||
|
||||
**参数**:
|
||||
- `cls`: 类方法的第一个参数,指代当前类。
|
||||
- `values`: 一个字典,包含实例化LLMKnowledgeChain时传入的参数。
|
||||
|
||||
**代码描述**:
|
||||
此函数检查`values`字典中是否包含键`llm`。如果存在,首先会发出一个警告,提示用户直接使用`llm`参数实例化LLMKnowledgeChain已被弃用,并建议使用`llm_chain`参数或`from_llm`类方法进行实例化。接着,如果`values`中不存在`llm_chain`键且`llm`键对应的值不为`None`,函数会从`values`中获取`prompt`键的值(如果不存在,则使用默认提示`PROMPT`),并使用`llm`和`prompt`的值创建一个`LLMChain`实例,将其赋值给`values`字典中的`llm_chain`键。最后,函数返回更新后的`values`字典。
|
||||
|
||||
**注意**:
|
||||
- 使用此函数时,应确保传入的`values`字典中的`llm`键(如果存在)对应的值是预期的,因为该函数会基于该值创建`LLMChain`实例。
|
||||
- 调用此函数后,应检查返回的`values`字典,以确认是否已按照推荐方式更新了实例化参数。
|
||||
|
||||
**输出示例**:
|
||||
假设传入的`values`字典为`{"llm": some_llm_object, "prompt": "Example prompt"}`,且`PROMPT`为默认提示,则函数可能返回的`values`字典为:
|
||||
```
|
||||
{
|
||||
"llm": some_llm_object,
|
||||
"prompt": "Example prompt",
|
||||
"llm_chain": LLMChain(llm=some_llm_object, prompt="Example prompt")
|
||||
}
|
||||
```
|
||||
在这个示例中,`llm_chain`键被添加到字典中,其值为一个使用`some_llm_object`和`"Example prompt"`实例化的`LLMChain`对象。
|
||||
***
|
||||
### FunctionDef input_keys(self)
|
||||
**input_keys**: 此函数的功能是返回一个包含单个输入键的列表。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**函数描述**: `input_keys` 函数是一个私有方法,设计用于内部使用,不建议在类的外部直接调用。它的主要作用是提供一个包含单个元素的列表,该元素是此实例的 `input_key` 属性值。这个方法的存在可能是为了与其他需要返回多个键的方法保持一致的接口,或者为了将来的扩展保留空间。
|
||||
|
||||
**注意**: 由于此方法被标记为私有(通过 `:meta private:` 注释),它主要用于类的内部逻辑,而不是作为类的公共接口的一部分。因此,在类的外部调用此方法时应当谨慎,因为它的行为或签名在未来的版本中可能会改变,而不会有任何向后兼容性的保证。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
['example_input_key']
|
||||
```
|
||||
在这个示例中,假设实例的 `input_key` 属性被设置为 `'example_input_key'`,那么调用 `input_keys` 方法将会返回一个只包含字符串 `'example_input_key'` 的列表。
|
||||
***
|
||||
### FunctionDef output_keys(self)
|
||||
**output_keys**: 此函数的功能是返回一个包含输出键的列表。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `output_keys`函数是`LLMKnowledgeChain`类的一个方法,它被标记为私有方法,意味着它主要供类内部使用,而不是设计给外部调用。此方法的目的是提供一个包含单个输出键的列表。这里的`self.output_key`是`LLMKnowledgeChain`类的一个属性,此方法通过将该属性包装在列表中返回,提供了对输出键的访问。这种设计允许将来的扩展性,例如,如果需要返回多个输出键,可以在不改变方法签名的情况下进行调整。
|
||||
|
||||
**注意**: 由于此方法被标记为私有(通过`:meta private:`标记),它主要用于类的内部逻辑,不建议在类的外部直接调用此方法。在使用时应注意,尽管它目前返回的是单个输出键的列表,但设计上允许返回多个键,这意味着在处理返回值时应考虑到可能的未来变化。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
['output_key_value']
|
||||
```
|
||||
在这个示例中,`output_key_value`代表`self.output_key`属性的值。实际的值将取决于`LLMKnowledgeChain`实例在其生命周期中对`self.output_key`属性的赋值。
|
||||
***
|
||||
### FunctionDef _evaluate_expression(self, dataset, query)
|
||||
**_evaluate_expression**: 该函数的功能是基于给定的数据集和查询语句,异步搜索知识库并返回搜索结果。
|
||||
|
||||
**参数**:
|
||||
- `dataset`: 数据集名称,类型为字符串。它指定了要搜索的知识库。
|
||||
- `query`: 查询语句,类型为字符串。它是用户希望在知识库中搜索的问题或关键词。
|
||||
|
||||
**代码描述**:
|
||||
`_evaluate_expression` 函数首先尝试调用 `search_knowledge_base_iter` 函数,以异步方式搜索知识库。该函数接收两个参数:`dataset` 和 `query`,分别代表知识库的名称和用户的查询语句。如果搜索成功,`search_knowledge_base_iter` 函数将返回搜索到的结果;如果在搜索过程中遇到任何异常(例如,知识库不存在或查询语句有误),则会捕获这些异常,并将输出设置为“输入的信息有误或不存在知识库”。最终,函数返回搜索结果或错误信息。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,需要确保提供的 `dataset`(知识库名称)是存在的,否则可能会导致搜索失败。
|
||||
- 由于 `search_knowledge_base_iter` 是一个异步函数,`_evaluate_expression` 函数内部使用了 `asyncio.run` 来运行它。这意味着 `_evaluate_expression` 函数本身是同步的,但它内部执行了异步操作。
|
||||
|
||||
**输出示例**:
|
||||
调用 `_evaluate_expression` 函数可能返回的示例:
|
||||
```
|
||||
"这是根据您的查询生成的回答。"
|
||||
```
|
||||
这个示例展示了一个简单的回答内容。实际返回的内容将根据查询语句和知识库的内容而有所不同。如果遇到错误,可能会返回:
|
||||
```
|
||||
"输入的信息有误或不存在知识库"
|
||||
```
|
||||
这表示提供的信息有误,或者指定的知识库不存在。
|
||||
***
|
||||
### FunctionDef _process_llm_result(self, llm_output, llm_input, run_manager)
|
||||
**_process_llm_result**: 此函数的功能是处理语言模型的输出结果,并返回格式化的答案。
|
||||
|
||||
**参数**:
|
||||
- `llm_output`: 字符串类型,表示语言模型的原始输出。
|
||||
- `llm_input`: 字符串类型,表示传递给语言模型的原始输入。
|
||||
- `run_manager`: `CallbackManagerForChainRun`类型,用于管理回调函数的执行。
|
||||
|
||||
**代码描述**:
|
||||
`_process_llm_result` 函数首先通过 `run_manager` 的 `on_text` 方法以绿色文本输出语言模型的原始输出,并设置是否详细输出。接着,函数尝试通过正则表达式匹配输出中的文本块。如果匹配成功,将提取文本块内容,并调用 `_evaluate_expression` 函数处理这部分内容和原始输入,生成最终的答案。如果原始输出以 "Answer:" 开头,或包含 "Answer:",则直接将其作为答案。如果以上条件都不满足,则返回一个错误信息,指出输入格式不正确。最后,函数返回一个字典,包含处理后的答案或错误信息。
|
||||
|
||||
**注意**:
|
||||
- `_process_llm_result` 函数依赖于 `_evaluate_expression` 函数来处理提取的文本块内容。因此,确保 `_evaluate_expression` 函数能正确执行是使用此函数的前提。
|
||||
- 此函数处理的输出格式特定于语言模型的输出结构,因此在不同的模型输出中可能需要调整正则表达式或处理逻辑。
|
||||
- 函数返回的字典中包含的键由 `self.output_key` 决定,这意味着在使用此函数之前,需要确保 `self.output_key` 已经被正确设置。
|
||||
|
||||
**输出示例**:
|
||||
调用 `_process_llm_result` 函数可能返回的示例之一:
|
||||
```
|
||||
{"output_key": "Answer: 这是根据您的查询生成的回答。"}
|
||||
```
|
||||
如果输入的格式不正确,可能会返回:
|
||||
```
|
||||
{"output_key": "输入的格式不对: 原始语言模型输出内容"}
|
||||
```
|
||||
这个示例展示了函数如何根据不同的情况返回不同的处理结果。实际返回的内容将根据语言模型的输出和输入的处理逻辑而有所不同。
|
||||
***
|
||||
### FunctionDef _aprocess_llm_result(self, llm_output, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _call(self, inputs, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _acall(self, inputs, run_manager)
|
||||
Doc is waiting to be generated...
|
||||
***
|
||||
### FunctionDef _chain_type(self)
|
||||
**函数名称**: _chain_type
|
||||
|
||||
**函数功能**: 返回链类型的字符串表示。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `_chain_type`函数是`LLMKnowledgeChain`类的一个私有方法,用于返回表示链类型的字符串。在这个上下文中,链类型被固定定义为`"llm_knowledge_chain"`,这意味着该函数返回的字符串用于标识或表示一个基于长期记忆模型(Long-term Language Model,LLM)的知识链。这种类型的知识链可能涉及到使用大型语言模型来处理和链接知识库中的信息。由于这是一个私有方法,它主要用于`LLMKnowledgeChain`类内部,可能用于日志记录、调试或者在类的其他方法中区分处理不同类型的知识链。
|
||||
|
||||
**注意**: 由于`_chain_type`是一个私有方法,它不应该直接从类的实例外部调用。它的设计初衷是为了类内部使用,以提供一种一致的方式来引用链类型。如果需要在类外部获取链类型信息,应该通过类提供的公共接口或方法来实现。
|
||||
|
||||
**输出示例**: 调用`_chain_type`方法将返回字符串`"llm_knowledge_chain"`。
|
||||
***
|
||||
### FunctionDef from_llm(cls, llm, prompt)
|
||||
**from_llm**: 此函数的功能是从语言模型创建一个知识链对象。
|
||||
|
||||
**参数**:
|
||||
- `cls`: 类方法的传统参数,表示要实例化的类本身。
|
||||
- `llm`: `BaseLanguageModel`类型,代表要使用的语言模型。
|
||||
- `prompt`: `BasePromptTemplate`类型,默认为`PROMPT`,代表用于语言模型的提示模板。
|
||||
- `**kwargs`: 接受任意额外的关键字参数,这些参数将传递给`LLMKnowledgeChain`的构造函数。
|
||||
|
||||
**代码描述**:
|
||||
`from_llm`函数是`LLMKnowledgeChain`类的一个类方法,它接受一个语言模型实例`llm`和一个可选的提示模板`prompt`作为输入。此函数首先使用提供的语言模型和提示模板创建一个`LLMChain`实例。然后,它使用这个`LLMChain`实例和任何其他提供的关键字参数来创建并返回一个`LLMKnowledgeChain`实例。这个过程允许`LLMKnowledgeChain`对象直接从一个语言模型实例化,简化了使用语言模型进行知识搜索和处理的流程。
|
||||
|
||||
在项目中,`from_llm`函数被`search_knowledgebase_once`函数调用。在这个调用中,`model`(一个语言模型实例)和`PROMPT`(一个提示模板)被传递给`from_llm`,同时还传递了`verbose=True`作为关键字参数。这表明在创建`LLMKnowledgeChain`实例时,会启用详细模式。然后,`search_knowledgebase_once`函数使用返回的`LLMKnowledgeChain`实例来执行对给定查询的搜索,展示了如何在实际应用中利用`from_llm`方法来处理和搜索知识。
|
||||
|
||||
**注意**:
|
||||
- 确保传递给`from_llm`的`llm`参数是一个有效的`BaseLanguageModel`实例,以保证知识链的正确构建和操作。
|
||||
- 在使用`**kwargs`传递额外参数时,应确保这些参数是`LLMKnowledgeChain`构造函数所支持的,以避免运行时错误。
|
||||
|
||||
**输出示例**:
|
||||
由于`from_llm`返回的是一个`LLMKnowledgeChain`实例,因此输出示例将取决于`LLMKnowledgeChain`类的具体实现和初始化时传递的参数。假设`LLMKnowledgeChain`有一个方法`run`,可以接受一个查询并返回相关的答案,一个可能的使用示例可能如下:
|
||||
```python
|
||||
llm_knowledge_chain = LLMKnowledgeChain.from_llm(model, prompt=PROMPT, verbose=True)
|
||||
answer = llm_knowledge_chain.run("这是一个查询示例")
|
||||
print(answer) # 输出将展示查询的答案
|
||||
```
|
||||
***
|
||||
## FunctionDef search_knowledgebase_once(query)
|
||||
Doc is waiting to be generated...
|
||||
## ClassDef KnowledgeSearchInput
|
||||
**KnowledgeSearchInput**: KnowledgeSearchInput类的功能是定义一个搜索知识库的输入模型。
|
||||
|
||||
**属性**:
|
||||
- location: 表示要搜索的查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
KnowledgeSearchInput类继承自BaseModel,这表明它是一个模型类,用于定义数据结构。在这个类中,定义了一个名为`location`的属性,该属性用于存储要在知识库中搜索的查询字符串。通过使用`Field`函数,为`location`属性提供了描述信息,即"The query to be searched",这有助于理解该属性的用途。
|
||||
|
||||
此类在项目中的作用是作为搜索知识库操作的输入数据模型。它通过定义必要的输入字段(在本例中为查询位置),使得其他部分的代码可以构建基于这些输入的搜索请求。尽管在提供的信息中没有直接的调用示例,但可以推断,该类的实例将被创建并填充相应的搜索查询,然后传递给执行搜索操作的函数或方法。
|
||||
|
||||
**注意**:
|
||||
- 在使用KnowledgeSearchInput类时,需要确保`location`属性被正确赋值,因为它是执行搜索操作所必需的。
|
||||
- 由于这个类继承自BaseModel,可以利用Pydantic库提供的数据验证功能来确保输入数据的有效性。例如,如果有特定格式或值范围的要求,可以通过修改Field函数的参数来实现。
|
||||
- 在实际应用中,可能需要根据知识库的具体结构和搜索需求,对KnowledgeSearchInput类进行扩展,添加更多的属性和验证逻辑。
|
||||
@ -0,0 +1,45 @@
|
||||
## FunctionDef search_knowledge_base_iter(database, query)
|
||||
**search_knowledge_base_iter**: 该函数用于异步迭代地搜索知识库并获取回答。
|
||||
|
||||
**参数**:
|
||||
- `database`: 知识库的名称,类型为字符串。
|
||||
- `query`: 用户的查询内容,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_knowledge_base_iter` 函数是一个异步函数,它接受两个参数:`database` 和 `query`。这个函数首先调用 `knowledge_base_chat` 函数,传入相应的参数,包括知识库名称、查询内容、模型名称、温度参数、历史记录、向量搜索的 top_k 值、最大 token 数量、prompt 名称、分数阈值以及是否流式输出的标志。`knowledge_base_chat` 函数负责处理用户的查询请求,并与知识库进行交互,返回一个响应对象。
|
||||
|
||||
函数内部通过异步迭代 `response.body_iterator` 来处理响应体中的数据。每次迭代得到的 `data` 是一个 JSON 字符串,表示一部分的查询结果。函数使用 `json.loads` 方法将 JSON 字符串解析为字典对象,然后从中提取出答案和相关文档信息。最终,函数返回最后一次迭代得到的答案内容。
|
||||
|
||||
**注意**:
|
||||
- 由于 `search_knowledge_base_iter` 是一个异步函数,因此在调用时需要使用 `await` 关键字。
|
||||
- 函数返回的是最后一次迭代得到的答案内容,如果需要处理每一次迭代得到的数据,需要在迭代过程中添加相应的处理逻辑。
|
||||
- 确保传入的知识库名称在系统中已经存在,否则可能无法正确处理查询请求。
|
||||
|
||||
**输出示例**:
|
||||
调用 `search_knowledge_base_iter` 函数可能返回的示例:
|
||||
```json
|
||||
"这是根据您的查询生成的回答。"
|
||||
```
|
||||
此输出示例仅表示函数可能返回的答案内容的格式,实际返回的内容将根据查询内容和知识库中的数据而有所不同。
|
||||
## FunctionDef search_knowledgebase_simple(query)
|
||||
**search_knowledgebase_simple**: 此函数用于简化地搜索知识库并获取回答。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户的查询内容,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_knowledgebase_simple` 函数是一个简化的接口,用于对知识库进行搜索。它接受一个参数 `query`,即用户的查询内容。函数内部通过调用 `search_knowledge_base_iter` 函数来实现对知识库的搜索。`search_knowledge_base_iter` 是一个异步函数,负责异步迭代地搜索知识库并获取回答。`search_knowledgebase_simple` 函数通过使用 `asyncio.run` 方法来运行异步的 `search_knowledge_base_iter` 函数,从而实现同步调用的效果。
|
||||
|
||||
由于 `search_knowledge_base_iter` 函数需要数据库名称和查询内容作为参数,但在 `search_knowledgebase_simple` 函数中只提供了查询内容 `query`,这意味着在 `search_knowledge_base_iter` 函数的实现中,数据库名称可能是预设的或通过其他方式获取。
|
||||
|
||||
**注意**:
|
||||
- `search_knowledgebase_simple` 函数提供了一个简化的接口,使得开发者可以不必直接处理异步编程的复杂性,而是通过一个简单的同步函数调用来搜索知识库。
|
||||
- 由于内部调用了异步函数 `search_knowledge_base_iter`,确保在使用此函数时,相关的异步环境和配置已正确设置。
|
||||
- 考虑到 `search_knowledge_base_iter` 函数的异步特性和可能的迭代处理,调用 `search_knowledgebase_simple` 函数时应注意可能的延迟或异步执行的影响。
|
||||
|
||||
**输出示例**:
|
||||
调用 `search_knowledgebase_simple` 函数可能返回的示例:
|
||||
```
|
||||
"这是根据您的查询生成的回答。"
|
||||
```
|
||||
此输出示例表示函数可能返回的答案内容的格式,实际返回的内容将根据查询内容和知识库中的数据而有所不同。
|
||||
39
markdown_docs/server/agent/tools/search_youtube.md
Normal file
@ -0,0 +1,39 @@
|
||||
## FunctionDef search_youtube(query)
|
||||
**search_youtube**: 此函数的功能是根据提供的查询字符串搜索YouTube视频。
|
||||
|
||||
**参数**:
|
||||
- query: 字符串类型,表示要在YouTube上搜索的查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
`search_youtube`函数接受一个名为`query`的参数,这个参数是一个字符串,代表用户希望在YouTube上进行搜索的关键词或短语。函数内部首先创建了一个`YouTubeSearchTool`的实例,命名为`tool`。然后,它调用了`tool`的`run`方法,将`query`作为输入参数传递给这个方法。最终,函数返回`run`方法的执行结果。
|
||||
|
||||
此函数是项目中用于与YouTube API交互的一部分,特别是在`server/agent/tools`路径下。它被设计为一个轻量级的接口,允许其他项目部分,如`server/agent/tools_select.py`,通过简单地调用此函数并传递相应的查询字符串,来实现YouTube搜索功能的集成。这种设计使得在不同的项目部分之间共享功能变得简单,同时也保持了代码的模块化和可维护性。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用此函数之前,`YouTubeSearchTool`类已经正确实现,并且其`run`方法能够接受一个字符串类型的输入参数并返回搜索结果。
|
||||
- 此函数的性能和返回结果直接依赖于`YouTubeSearchTool`类的实现细节以及YouTube API的响应。
|
||||
|
||||
**输出示例**:
|
||||
假设`YouTubeSearchTool`的`run`方法返回的是一个包含搜索结果视频标题和URL的列表,那么`search_youtube`函数的一个可能的返回值示例为:
|
||||
```python
|
||||
[
|
||||
{"title": "如何使用Python搜索YouTube", "url": "https://www.youtube.com/watch?v=example1"},
|
||||
{"title": "Python YouTube API教程", "url": "https://www.youtube.com/watch?v=example2"}
|
||||
]
|
||||
```
|
||||
这个返回值展示了一个包含两个搜索结果的列表,每个结果都是一个字典,包含视频的标题和URL。
|
||||
## ClassDef YoutubeInput
|
||||
**YoutubeInput**: YoutubeInput类的功能是定义用于YouTube视频搜索的输入参数模型。
|
||||
|
||||
**属性**:
|
||||
- location: 用于视频搜索的查询字符串。
|
||||
|
||||
**代码描述**:
|
||||
YoutubeInput类继承自BaseModel,这表明它是一个模型类,用于定义数据结构。在这个类中,定义了一个名为`location`的属性,该属性用于存储用户进行YouTube视频搜索时输入的查询字符串。通过使用`Field`函数,为`location`属性提供了一个描述,即"Query for Videos search",这有助于理解该属性的用途。
|
||||
|
||||
在项目中,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`两个文件中并没有直接提到`YoutubeInput`类的使用,但可以推断,`YoutubeInput`类作为一个数据模型,可能会在处理YouTube视频搜索请求的过程中被用到。具体来说,它可能被用于解析和验证用户的搜索请求参数,确保传递给YouTube API的查询字符串是有效和格式正确的。
|
||||
|
||||
**注意**:
|
||||
- 在使用`YoutubeInput`类时,需要确保传递给`location`属性的值是一个有效的字符串,因为这将直接影响到YouTube视频搜索的结果。
|
||||
- 由于`YoutubeInput`类继承自`BaseModel`,可以利用Pydantic库提供的数据验证和序列化功能,以简化数据处理流程。
|
||||
- 虽然当前文档中没有提到`YoutubeInput`类在项目中的具体调用情况,开发者在实际使用时应考虑如何将此类集成到视频搜索功能中,以及如何处理可能出现的数据验证错误。
|
||||
34
markdown_docs/server/agent/tools/shell.md
Normal file
@ -0,0 +1,34 @@
|
||||
## FunctionDef shell(query)
|
||||
**shell**: shell函数的功能是执行一个shell查询并返回结果。
|
||||
|
||||
**参数**:
|
||||
- query: 字符串类型,表示要执行的shell查询命令。
|
||||
|
||||
**代码描述**:
|
||||
该shell函数定义在`server/agent/tools/shell.py`文件中,是项目中用于执行shell命令的核心函数。函数接收一个名为`query`的字符串参数,该参数是需要执行的shell命令。函数内部首先创建了一个`ShellTool`类的实例`tool`,然后调用这个实例的`run`方法执行传入的`query`命令。最终,函数返回`run`方法的执行结果。
|
||||
|
||||
在项目的结构中,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`这两个文件中没有直接的代码示例或文档说明如何调用`shell`函数,但可以推断,`shell`函数作为工具模块中的一部分,可能会被项目中的其他部分调用以执行特定的shell命令。这种设计使得执行shell命令的逻辑被封装在一个单独的函数中,便于维护和重用。
|
||||
|
||||
**注意**:
|
||||
- 在使用`shell`函数时,需要确保传入的`query`命令是安全的,避免执行恶意代码。
|
||||
- 该函数的执行结果取决于`ShellTool`类的`run`方法如何实现,因此需要了解`ShellTool`的具体实现细节。
|
||||
|
||||
**输出示例**:
|
||||
假设`ShellTool`的`run`方法简单地返回执行命令的输出,如果调用`shell("echo Hello World")`,那么可能的返回值为:
|
||||
```
|
||||
Hello World
|
||||
```
|
||||
## ClassDef ShellInput
|
||||
**ShellInput**: ShellInput类的功能是定义一个用于封装Shell命令的数据模型。
|
||||
|
||||
**属性**:
|
||||
- query: 一个字符串类型的属性,用于存储可以在Linux命令行中执行的Shell命令。该属性通过Field方法定义,其中包含一个描述信息,说明这是一个可执行的Shell命令。
|
||||
|
||||
**代码描述**:
|
||||
ShellInput类继承自BaseModel,这表明它是一个基于Pydantic库的模型,用于数据验证和管理。在这个类中,定义了一个名为`query`的属性,这个属性必须是一个字符串。通过使用Field方法,为`query`属性提供了一个描述,即“一个能在Linux命令行运行的Shell命令”,这有助于理解该属性的用途和功能。
|
||||
|
||||
在项目的上下文中,虽然当前提供的信息没有直接展示ShellInput类如何被其他对象调用,但可以推断,ShellInput类可能被用于封装用户输入或者其他来源的Shell命令,之后这些封装好的命令可能会在项目的其他部分,如服务器的代理工具中被执行。这样的设计使得Shell命令的处理更加模块化和安全,因为Pydantic模型提供了一层数据验证,确保只有合法和预期的命令才会被执行。
|
||||
|
||||
**注意**:
|
||||
- 使用ShellInput类时,需要确保传入的`query`字符串是有效且安全的Shell命令。考虑到Shell命令的强大功能和潜在的安全风险,应当避免执行来自不可信源的命令。
|
||||
- 由于ShellInput类基于Pydantic库,使用该类之前需要确保项目中已经安装了Pydantic。此外,熟悉Pydantic库的基本使用和数据验证机制将有助于更有效地利用ShellInput类。
|
||||
62
markdown_docs/server/agent/tools/weather_check.md
Normal file
@ -0,0 +1,62 @@
|
||||
## FunctionDef weather(location, api_key)
|
||||
**weather**: 此函数的功能是获取指定地点的当前天气信息。
|
||||
|
||||
**参数**:
|
||||
- location: 字符串类型,表示查询天气信息的地点。
|
||||
- api_key: 字符串类型,用于访问天气API的密钥。
|
||||
|
||||
**代码描述**:
|
||||
`weather` 函数通过构造一个请求URL,使用 `requests.get` 方法向 `seniverse.com` 的天气API发送请求,以获取指定地点的当前天气信息。此URL包含了API密钥(api_key)、地点(location)、语言设置(默认为简体中文)和温度单位(摄氏度)。如果请求成功(HTTP状态码为200),函数将解析响应的JSON数据,提取温度和天气描述信息,然后以字典形式返回这些信息。如果请求失败,则抛出异常,异常信息包含了失败的HTTP状态码。
|
||||
|
||||
在项目中,`weather` 函数被 `weathercheck` 函数调用。`weathercheck` 函数接受一个地点作为参数,并使用项目中预定义的 `SENIVERSE_API_KEY` 作为API密钥来调用 `weather` 函数。这表明 `weather` 函数是项目中用于获取天气信息的核心功能,而 `weathercheck` 函数提供了一个更简便的接口,使得其他部分的代码无需直接处理API密钥即可请求天气信息。
|
||||
|
||||
**注意**:
|
||||
- 确保提供的 `api_key` 是有效的,否则请求将失败。
|
||||
- 由于网络请求的性质,此函数的执行时间可能受到网络状况的影响。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
{
|
||||
"temperature": "22",
|
||||
"description": "多云"
|
||||
}
|
||||
```
|
||||
此示例展示了函数返回值的可能外观,其中包含了温度和天气描述信息。
|
||||
## FunctionDef weathercheck(location)
|
||||
**weathercheck**: 此函数的功能是使用预定义的API密钥获取指定地点的当前天气信息。
|
||||
|
||||
**参数**:
|
||||
- location: 字符串类型,表示查询天气信息的地点。
|
||||
|
||||
**代码描述**:
|
||||
`weathercheck` 函数是一个简化的接口,用于获取指定地点的天气信息。它接受一个地点名称作为参数,并内部调用了 `weather` 函数,后者是实际执行天气信息获取操作的函数。在调用 `weather` 函数时,`weathercheck` 使用了预定义的 `SENIVERSE_API_KEY` 作为API密钥参数。这意味着使用 `weathercheck` 函数时,用户无需直接处理API密钥,从而简化了获取天气信息的过程。
|
||||
|
||||
`weather` 函数负责构造请求URL,并通过HTTP GET请求向 `seniverse.com` 的天气API发送请求。如果请求成功,它将解析响应的JSON数据,并提取出温度和天气描述信息,然后以字典形式返回这些信息。如果请求失败,`weather` 函数将抛出异常,包含失败的HTTP状态码。
|
||||
|
||||
**注意**:
|
||||
- 使用 `weathercheck` 函数时,确保预定义的 `SENIVERSE_API_KEY` 是有效的。无效的API密钥将导致请求失败。
|
||||
- 获取天气信息的过程涉及网络请求,因此执行时间可能受到网络状况的影响。在网络状况不佳的情况下,响应时间可能会较长。
|
||||
|
||||
**输出示例**:
|
||||
由于 `weathercheck` 函数内部调用了 `weather` 函数并直接返回其结果,因此输出示例与 `weather` 函数的输出示例相同。以下是一个可能的返回值示例:
|
||||
```python
|
||||
{
|
||||
"temperature": "22",
|
||||
"description": "多云"
|
||||
}
|
||||
```
|
||||
此示例展示了函数返回值的可能外观,其中包含了温度和天气描述信息。
|
||||
## ClassDef WeatherInput
|
||||
**WeatherInput**: WeatherInput类的功能是定义一个用于天气查询的输入模型。
|
||||
|
||||
**属性**:
|
||||
- location: 表示查询天气的城市名称,包括城市和县。
|
||||
|
||||
**代码描述**:
|
||||
WeatherInput类继承自BaseModel,这是一个常见的做法,用于创建具有类型注解的数据模型。在这个类中,定义了一个名为`location`的属性,该属性用于存储用户希望查询天气的城市名称。通过使用`Field`函数,为`location`属性提供了额外的描述信息,即"City name, include city and county",这有助于理解该属性的用途和预期的值格式。
|
||||
|
||||
在项目的上下文中,尽管具体的调用情况未在提供的信息中明确,但可以推断WeatherInput类被设计为在天气查询功能中使用。它可能被用于从用户那里接收输入,然后这些输入将被用于查询特定城市的天气信息。这种设计允许天气查询功能以一种结构化和类型安全的方式处理用户输入。
|
||||
|
||||
**注意**:
|
||||
- 在使用WeatherInput类时,需要确保传递给`location`属性的值是一个格式正确的字符串,即包含城市和县的名称。这是因为该模型可能会被用于向天气API发送请求,而这些API通常要求准确的地理位置信息以返回正确的天气数据。
|
||||
- 由于WeatherInput类继承自BaseModel,因此可以利用Pydantic库提供的各种功能,如数据验证、序列化和反序列化等。这使得处理和转换用户输入变得更加容易和安全。
|
||||
35
markdown_docs/server/agent/tools/wolfram.md
Normal file
@ -0,0 +1,35 @@
|
||||
## FunctionDef wolfram(query)
|
||||
**wolfram**: 此函数的功能是执行对Wolfram Alpha API的查询并返回结果。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,表示要查询的内容。
|
||||
|
||||
**代码描述**:
|
||||
`wolfram`函数首先创建了一个`WolframAlphaAPIWrapper`对象,该对象是对Wolfram Alpha API的一个封装。在创建这个对象时,需要提供一个`wolfram_alpha_appid`,这是调用Wolfram Alpha服务所需的应用程序ID。随后,函数使用`run`方法执行传入的查询`query`。最后,函数返回查询结果。
|
||||
|
||||
在项目中,`wolfram`函数作为`server/agent/tools/wolfram.py`模块的一部分,虽然其被调用的具体情况在提供的文档中没有直接说明,但可以推断这个函数可能被设计为一个工具函数,供项目中其他部分调用以获取Wolfram Alpha查询的结果。这样的设计使得项目中的其他模块可以轻松地利用Wolfram Alpha提供的强大计算和知识查询功能,而无需关心API调用的具体细节。
|
||||
|
||||
**注意**:
|
||||
- 使用此函数前,需要确保已经获得了有效的Wolfram Alpha应用程序ID(`wolfram_alpha_appid`),并且该ID已经正确配置在创建`WolframAlphaAPIWrapper`对象时。
|
||||
- 查询结果的具体格式和内容将依赖于Wolfram Alpha API的返回值,可能包括文本、图像或其他数据类型。
|
||||
|
||||
**输出示例**:
|
||||
假设对Wolfram Alpha进行了一个查询“2+2”,函数可能返回如下的结果:
|
||||
```
|
||||
4
|
||||
```
|
||||
这只是一个简化的示例,实际返回的结果可能包含更多的信息和数据类型,具体取决于查询的内容和Wolfram Alpha API的响应。
|
||||
## ClassDef WolframInput
|
||||
**WolframInput**: WolframInput类的功能是封装了用于Wolfram语言计算的输入数据。
|
||||
|
||||
**属性**:
|
||||
- location: 表示需要进行计算的具体问题的字符串。
|
||||
|
||||
**代码描述**:
|
||||
WolframInput类继承自BaseModel,这表明它是一个用于数据验证和序列化的模型类。在这个类中,定义了一个名为`location`的属性,该属性用于存储一个字符串,这个字符串代表了需要使用Wolfram语言进行计算的具体问题。通过使用Pydantic库中的`Field`函数,为`location`属性提供了一个描述,增强了代码的可读性和易用性。
|
||||
|
||||
在项目的结构中,WolframInput类位于`server/agent/tools/wolfram.py`文件中,这意味着它是服务端代理工具中的一部分,专门用于处理与Wolfram语言相关的输入数据。尽管在提供的信息中,`server/agent/tools/__init__.py`和`server/agent/tools_select.py`两个文件中没有直接提到WolframInput类的调用情况,但可以推测,WolframInput类可能会被这些模块或其他相关模块中的代码所使用,以便于处理和传递需要用Wolfram语言解决的问题。
|
||||
|
||||
**注意**:
|
||||
- 在使用WolframInput类时,需要确保`location`属性中的问题描述是准确和有效的,因为这将直接影响到Wolfram语言计算的结果。
|
||||
- 由于WolframInput类继承自BaseModel,因此可以利用Pydantic提供的数据验证功能来确保输入数据的有效性。在实际应用中,可以根据需要对WolframInput类进行扩展,增加更多的属性和验证逻辑,以满足不同的计算需求。
|
||||
116
markdown_docs/server/api.md
Normal file
@ -0,0 +1,116 @@
|
||||
## FunctionDef document
|
||||
**document**: 此函数的功能是重定向到文档页面。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `document` 函数是一个异步函数,其主要作用是将用户的请求重定向到服务器上的文档页面。在这个项目中,当用户访问服务器的根路径("/")时,通过调用此函数实现自动跳转到文档页面。这是通过返回一个 `RedirectResponse` 对象实现的,该对象中包含了目标URL(即文档页面的URL)。在这个例子中,目标URL被硬编码为 "/docs",意味着当此函数被触发时,用户的浏览器将会被重定向到服务器的 "/docs" 路径,通常这个路径下托管着API的交互式文档,如Swagger UI或Redoc。
|
||||
|
||||
此函数被 `mount_app_routes` 函数调用,作为FastAPI应用的一部分,用于在应用启动时设置路由。在 `mount_app_routes` 函数中,`document` 函数被注册为处理根路径("/")请求的处理器。这样,当用户访问应用的根路径时,他们会被自动重定向到API文档页面,从而提供了一种用户友好的方式来探索和测试API。
|
||||
|
||||
**注意**: 使用此函数时,需要确保 "/docs" 路径下确实存在文档页面。在FastAPI中,默认情况下,API文档通常是自动生成的,并且可以通过 "/docs"(Swagger UI)或 "/redoc"(Redoc)路径访问。如果你更改了文档页面的路径或使用了自定义文档页面,需要相应地更新此函数中的URL。
|
||||
|
||||
**输出示例**: 由于此函数的作用是进行页面重定向,因此它不直接产生可视化的输出。但在浏览器中,当访问根路径("/")时,浏览器的地址栏将会显示为 "/docs",并展示相应的API文档页面。
|
||||
## FunctionDef create_app(run_mode)
|
||||
Doc is waiting to be generated...
|
||||
## FunctionDef mount_app_routes(app, run_mode)
|
||||
**mount_app_routes**: 该函数用于在FastAPI应用中挂载应用路由。
|
||||
|
||||
**参数**:
|
||||
- `app`: FastAPI应用实例,用于注册路由。
|
||||
- `run_mode`: 运行模式,用于区分应用的运行环境,例如开发环境或生产环境。
|
||||
|
||||
**代码描述**:
|
||||
`mount_app_routes`函数主要负责在FastAPI应用实例中注册各种API路由。这些路由包括对话、搜索引擎对话、聊天记录反馈、知识库管理、LLM模型管理、服务器状态查询等功能的接口。通过调用`app.get`和`app.post`方法,将特定的URL路径与处理函数绑定,从而实现API的路由功能。此外,函数还调用了`mount_knowledge_routes`和`mount_filename_summary_routes`两个函数,分别用于挂载知识库相关和文件名摘要相关的路由。在注册路由的过程中,为每个API接口设置了标签(tags)、摘要(summary)等信息,以便于在API文档中进行分类和说明。
|
||||
|
||||
**注意**:
|
||||
- 在使用`mount_app_routes`函数之前,需要确保已经创建了FastAPI应用实例,并且所有处理函数都已正确定义。
|
||||
- 该函数是API路由注册的入口点,通过它可以将应用的各种功能接口集成到FastAPI应用中。
|
||||
- 在实际部署和使用时,应注意API接口的安全性,避免未授权的访问和操作。
|
||||
- `run_mode`参数可以用于根据不同的运行环境调整API的行为,例如在开发环境中启用调试模式,在生产环境中优化性能。
|
||||
|
||||
**输出示例**:
|
||||
由于`mount_app_routes`函数的作用是注册路由而不直接返回数据,因此它没有直接的输出示例。函数执行成功后,FastAPI应用将能够响应对应路由的HTTP请求,并根据请求的URL路径调用相应的处理函数。例如,当用户通过HTTP POST请求访问`/chat/chat`路径时,FastAPI应用将调用`chat`函数处理该请求,并返回处理结果。
|
||||
### FunctionDef get_server_prompt_template(type, name)
|
||||
**get_server_prompt_template**: 该函数用于根据提供的类型和名称参数,动态加载并返回相应的模板内容。
|
||||
|
||||
**参数**:
|
||||
- type: 字面量类型,可选值为"llm_chat"、"knowledge_base_chat"、"search_engine_chat"、"agent_chat",用于指定模板的类型。默认值为"llm_chat"。
|
||||
- name: 字符串类型,用于指定模板的名称。默认值为"default"。
|
||||
|
||||
**代码描述**:
|
||||
`get_server_prompt_template`函数是API层面用于处理模板加载请求的入口。该函数接收两个参数:`type`和`name`,分别代表模板的类型和名称。函数内部调用了`get_prompt_template`函数,传入相同的`type`和`name`参数,以获取指定的模板内容。
|
||||
|
||||
`get_prompt_template`函数位于`server/utils.py`文件中,负责从配置中加载指定类型和名称的模板内容。它首先从`configs`模块导入`prompt_config`配置,然后使用`importlib.reload`方法重新加载`prompt_config`,以确保获取到最新的配置信息。通过`type`参数从`prompt_config.PROMPT_TEMPLATES`中索引到对应类型的模板字典,再使用`name`参数从该字典中获取具体的模板内容。如果指定的`name`在字典中不存在,则返回`None`。
|
||||
|
||||
在项目结构中,`get_server_prompt_template`函数位于`server/api.py/mount_app_routes`路径下,作为API接口的一部分,允许前端或其他服务通过HTTP请求动态获取不同类型和名称的模板内容,从而支持灵活的聊天模式或功能需求。
|
||||
|
||||
**注意**:
|
||||
- 调用`get_server_prompt_template`函数时,需要确保`type`和`name`参数的值正确无误,并且所请求的模板已经在`prompt_config`中定义。
|
||||
- 由于`get_prompt_template`函数依赖于外部的配置文件`prompt_config`,在修改配置文件后,可能需要重启服务或动态重新加载配置,以确保更改生效。
|
||||
|
||||
**输出示例**:
|
||||
假设存在以下模板配置:
|
||||
```python
|
||||
PROMPT_TEMPLATES = {
|
||||
"llm_chat": {
|
||||
"default": "你好,请问有什么可以帮助你的?"
|
||||
}
|
||||
}
|
||||
```
|
||||
当调用`get_server_prompt_template(type="llm_chat", name="default")`时,将返回字符串`"你好,请问有什么可以帮助你的?"`。
|
||||
***
|
||||
## FunctionDef mount_knowledge_routes(app)
|
||||
**mount_knowledge_routes**: 该函数的功能是在FastAPI应用中挂载知识库相关的路由。
|
||||
|
||||
**参数**: 该函数接受一个参数:
|
||||
- `app`: FastAPI应用实例,用于注册路由。
|
||||
|
||||
**代码描述**: `mount_knowledge_routes` 函数主要负责将知识库管理和操作相关的API接口注册到FastAPI应用中。通过导入不同的处理函数,如`knowledge_base_chat`、`upload_temp_docs`、`file_chat`、`agent_chat`等,并使用`app.post`或`app.get`方法将这些处理函数与特定的URL路径绑定,从而实现API的路由功能。此外,函数还为每个API接口设置了标签(tags)、摘要(summary)等信息,以便于在API文档中进行分类和说明。
|
||||
|
||||
该函数涵盖了知识库的创建、删除、文件上传、文件删除、文档搜索、文档更新、下载文档、重建向量库等多个功能。每个功能都通过特定的URL路径进行访问,例如,通过`/knowledge_base/create_knowledge_base`路径可以访问创建知识库的接口。
|
||||
|
||||
**注意**:
|
||||
- 在使用`mount_knowledge_routes`函数之前,需要确保已经创建了FastAPI应用实例,并且所有处理函数都已正确定义。
|
||||
- 该函数是知识库管理功能在FastAPI框架中的入口点,通过它可以将知识库相关的操作集成到FastAPI应用中。
|
||||
- 在实际部署和使用时,应注意API接口的安全性,避免未授权的访问和操作。
|
||||
## FunctionDef mount_filename_summary_routes(app)
|
||||
**mount_filename_summary_routes**: 此函数的功能是在FastAPI应用中挂载处理文件名摘要的路由。
|
||||
|
||||
**参数**:
|
||||
- `app`: FastAPI应用实例,用于注册路由。
|
||||
|
||||
**代码描述**:
|
||||
`mount_filename_summary_routes`函数主要负责在FastAPI应用中注册三个与文件名摘要相关的POST路由。这些路由分别用于处理单个知识库根据文件名称摘要、根据doc_ids摘要以及重建单个知识库文件摘要的请求。
|
||||
|
||||
1. `/knowledge_base/kb_summary_api/summary_file_to_vector_store`路由用于处理根据文件名称对单个知识库进行摘要,并将摘要结果存储到向量存储中。此路由使用`summary_file_to_vector_store`函数处理请求。
|
||||
|
||||
2. `/knowledge_base/kb_summary_api/summary_doc_ids_to_vector_store`路由用于处理根据文档ID列表生成单个知识库的文档摘要,并将摘要信息存储到向量存储中。此路由使用`summary_doc_ids_to_vector_store`函数处理请求,并指定`response_model`为`BaseResponse`,以规范化响应格式。
|
||||
|
||||
3. `/knowledge_base/kb_summary_api/recreate_summary_vector_store`路由用于处理重建单个知识库文件摘要的请求。此路由使用`recreate_summary_vector_store`函数处理请求。
|
||||
|
||||
每个路由都通过`app.post`方法注册,并指定了路由的路径、处理函数、标签(tags)和摘要(summary)。这些信息有助于生成自动化的API文档,提高API的可发现性和可理解性。
|
||||
|
||||
**注意**:
|
||||
- 在使用这些API接口之前,确保相关的处理函数已经正确实现,并且知识库服务已经配置妥当。
|
||||
- 通过指定`response_model`为`BaseResponse`,可以统一API的响应格式,使得响应数据更加规范化,便于客户端处理。
|
||||
- 这些路由主要用于处理知识库文件摘要的生成和管理,因此在调用这些API时,需要提供正确的知识库名称、文件名称或文档ID列表等信息。
|
||||
- 在项目中,`mount_filename_summary_routes`函数被`mount_app_routes`函数调用,意味着这些文件名摘要相关的路由是作为应用的一部分被自动挂载和注册的。这有助于保持路由注册的集中管理和应用结构的清晰。
|
||||
## FunctionDef run_api(host, port)
|
||||
**run_api**: 此函数的功能是启动API服务。
|
||||
|
||||
**参数**:
|
||||
- **host**: 服务器的主机名或IP地址。
|
||||
- **port**: 服务器监听的端口号。
|
||||
- **kwargs**: 关键字参数,可选,用于提供SSL证书文件路径。
|
||||
|
||||
**代码描述**:
|
||||
`run_api`函数负责启动API服务。它接受三个参数:`host`、`port`以及可选的关键字参数`kwargs`。这些参数用于指定服务器的监听地址和端口,以及配置SSL加密连接所需的证书文件路径。
|
||||
|
||||
函数首先检查`kwargs`中是否提供了`ssl_keyfile`和`ssl_certfile`这两个关键字参数。如果这两个参数都被提供,函数将使用这些证书文件启动一个支持SSL加密的API服务。这是通过调用`uvicorn.run`函数并传入相应的参数来实现的,包括应用实例`app`、主机名`host`、端口号`port`、SSL密钥文件路径`ssl_keyfile`和SSL证书文件路径`ssl_certfile`。
|
||||
|
||||
如果`kwargs`中没有提供SSL相关的参数,`run_api`函数将启动一个不使用SSL加密的API服务。这同样是通过调用`uvicorn.run`函数实现的,但此时只传入应用实例`app`、主机名`host`和端口号`port`作为参数。
|
||||
|
||||
**注意**:
|
||||
- 确保在启动支持SSL的API服务之前,已经正确生成并指定了SSL证书文件和密钥文件的路径。
|
||||
- 在没有提供SSL证书文件路径的情况下,API服务将以非加密模式运行,这可能不适合生产环境中处理敏感信息。
|
||||
- `uvicorn.run`是Uvicorn库的一部分,Uvicorn是一个轻量级、超快的ASGI服务器,用于Python异步web应用。确保在使用`run_api`函数之前已经安装了Uvicorn库。
|
||||
@ -0,0 +1,87 @@
|
||||
## ClassDef ConversationCallbackHandler
|
||||
**ConversationCallbackHandler**: ConversationCallbackHandler类的功能是在聊天过程中处理回调,特别是在使用大型语言模型(LLM)生成回应后更新消息内容。
|
||||
|
||||
**属性**:
|
||||
- `conversation_id`: 字符串类型,表示对话的唯一标识符。
|
||||
- `message_id`: 字符串类型,表示消息的唯一标识符。
|
||||
- `chat_type`: 字符串类型,表示聊天的类型。
|
||||
- `query`: 字符串类型,表示用户的查询或输入。
|
||||
- `start_at`: 初始化为None,可用于记录某些操作的开始时间。
|
||||
- `raise_error`: 布尔类型,默认为True,表示是否在处理过程中遇到错误时抛出异常。
|
||||
|
||||
**代码描述**:
|
||||
ConversationCallbackHandler继承自BaseCallbackHandler,是一个专门设计用于处理聊天应用中的回调逻辑的类。它通过接收对话ID、消息ID、聊天类型和用户查询等参数进行初始化。此类中定义了一个属性`always_verbose`,始终返回True,表示无论verbose参数如何设置,都会调用详细的回调函数。此外,它还包含两个方法`on_llm_start`和`on_llm_end`,这两个方法分别在大型语言模型(LLM)开始处理和结束处理时被调用。`on_llm_end`方法中,它会从LLM的响应中提取生成的文本,并调用`update_message`函数更新消息内容。
|
||||
|
||||
在项目中,ConversationCallbackHandler被用于`server/chat/chat.py/chat/chat_iterator`中,以处理和更新使用大型语言模型进行聊天时生成的回应。在聊天迭代器中,创建了ConversationCallbackHandler实例,并将其添加到回调列表中。这样,每当LLM处理完成,就会通过`on_llm_end`方法更新对应的消息内容。
|
||||
|
||||
**注意**:
|
||||
- 在使用ConversationCallbackHandler时,需要确保提供的`conversation_id`、`message_id`、`chat_type`和`query`参数正确无误,因为这些信息将用于消息更新和回调处理的关键环节。
|
||||
- `on_llm_start`方法目前留空,但可以根据需要进行扩展,以存储更多与LLM处理相关的信息。
|
||||
|
||||
**输出示例**:
|
||||
由于ConversationCallbackHandler主要负责回调处理,不直接产生输出,因此没有具体的输出示例。但在其作用下,一条消息的内容可能会从用户的原始查询更新为LLM生成的回应文本。
|
||||
### FunctionDef __init__(self, conversation_id, message_id, chat_type, query)
|
||||
**__init__**: __init__函数的功能是初始化ConversationCallbackHandler类的实例。
|
||||
|
||||
**参数**:
|
||||
- conversation_id: 会话ID,标识特定的对话。
|
||||
- message_id: 消息ID,用于标识对话中的特定消息。
|
||||
- chat_type: 聊天类型,描述聊天的性质(如私聊、群聊等)。
|
||||
- query: 查询字符串,用于处理或响应特定的查询请求。
|
||||
|
||||
**代码描述**:
|
||||
此__init__函数是ConversationCallbackHandler类的构造函数,用于创建类的实例时初始化其属性。在这个函数中,接收四个参数:conversation_id、message_id、chat_type和query,这些参数分别用于初始化实例的相应属性。此外,还有一个属性start_at,它在此函数中被初始化为None,可能用于记录会话开始的时间或其他与时间相关的信息,但具体用途取决于类的其他部分或方法如何使用它。
|
||||
|
||||
**注意**:
|
||||
- 在使用ConversationCallbackHandler类创建实例时,必须提供conversation_id、message_id、chat_type和query这四个参数,它们对于实例的功能至关重要。
|
||||
- start_at属性在初始化时没有设置具体值(设为None),这意味着如果需要使用到这个属性,应在类的其他方法中对其进行适当的设置。
|
||||
- 此构造函数不返回任何值,仅用于初始化实例的状态。
|
||||
***
|
||||
### FunctionDef always_verbose(self)
|
||||
**always_verbose**: 此函数的功能是决定是否在verbose模式为False时也调用verbose回调。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `always_verbose` 函数是 `ConversationCallbackHandler` 类的一个方法,旨在控制回调处理器的行为。具体来说,它指示回调处理器在处理回调时是否应始终采用详细模式,即使在全局设置中未启用详细(verbose)模式。该方法通过返回一个布尔值 `True` 来实现这一行为,表明无论全局的verbose设置如何,都应调用verbose回调。这对于开发者在调试或需要详尽日志信息的场景下非常有用,因为它允许单独的回调处理器忽略全局的verbose设置,始终以详细模式运行。
|
||||
|
||||
**注意**: 使用此功能时,开发者应当意识到,即使全局verbose设置为False,启用 `always_verbose` 方法的回调处理器仍将产生详细的日志输出。这可能会导致日志信息量显著增加,因此建议仅在调试或特定需要详细日志的情况下使用。
|
||||
|
||||
**输出示例**: 由于 `always_verbose` 方法返回的是一个布尔值 `True`,因此在调用此方法时,其输出示例将简单地为:
|
||||
|
||||
```python
|
||||
True
|
||||
```
|
||||
***
|
||||
### FunctionDef on_llm_start(self, serialized, prompts)
|
||||
**on_llm_start**: 该函数用于处理与大型语言模型(LLM)会话开始相关的逻辑。
|
||||
|
||||
**参数**:
|
||||
- `serialized`: 一个字典类型参数,包含了需要序列化的信息。其键值对的类型为`str`到`Any`,即键是字符串类型,而值可以是任何类型。
|
||||
- `prompts`: 一个字符串列表,包含了启动大型语言模型会话时的提示信息。
|
||||
- `**kwargs`: 接收任意额外的关键字参数。这些参数的类型不固定,可以根据实际需要传递给函数。
|
||||
|
||||
**代码描述**:
|
||||
`on_llm_start`函数的主要作用是在大型语言模型(LLM)会话开始时执行必要的逻辑处理。这包括但不限于初始化会话、设置会话参数、记录会话信息等。函数接收两个主要参数:`serialized`和`prompts`。`serialized`参数是一个字典,用于传递需要序列化的信息,这可能包括会话的配置信息、用户的身份信息等。`prompts`参数是一个字符串列表,提供了启动会话时的提示信息,这些信息可能用于引导语言模型生成回复。此外,函数还可以接收任意数量的关键字参数(`**kwargs`),这为函数提供了高度的灵活性,允许在不修改函数签名的情况下添加更多的功能或处理逻辑。
|
||||
|
||||
**注意**:
|
||||
- 在实际使用`on_llm_start`函数时,开发者需要注意`serialized`和`prompts`参数的内容和格式,确保它们符合大型语言模型处理的要求。
|
||||
- 函数中的注释提示“如果想存更多信息,则prompts也需要持久化”,这意味着如果在会话过程中需要记录额外的信息,那么开发者应考虑将这些信息添加到`prompts`中,并确保它们能够被适当地序列化和存储。
|
||||
- 由于函数目前的实现为空(`pass`),开发者在将其集成到项目中时需要根据具体需求完成相应的逻辑实现。
|
||||
***
|
||||
### FunctionDef on_llm_end(self, response)
|
||||
**on_llm_end**: 此函数的功能是在语言模型处理结束后,更新聊天记录的回复内容。
|
||||
|
||||
**参数**:
|
||||
- `response`: LLMResult类型,包含语言模型生成的结果。
|
||||
- `**kwargs`: 接受任意数量的关键字参数,提供额外的灵活性。
|
||||
|
||||
**代码描述**:
|
||||
`on_llm_end`方法首先从`response`对象中提取出语言模型生成的第一条回复文本。此文本是通过访问`response.generations[0][0].text`获得的,其中`generations`是一个嵌套列表,包含了所有生成的回复。随后,该方法调用`update_message`函数,将提取出的回复文本更新到数据库中对应的聊天记录里。在调用`update_message`时,传入的参数包括`self.message_id`和提取的回复文本`answer`。`self.message_id`是需要更新的聊天记录的唯一标识ID,而`answer`则是新的回复内容。
|
||||
|
||||
`update_message`函数是定义在`server/db/repository/message_repository.py`中的一个函数,其主要功能是更新数据库中已有的聊天记录。它通过`message_id`定位到特定的聊天记录,并根据提供的新回复内容或元数据进行更新。在`on_llm_end`方法中,`update_message`的调用实现了在语言模型处理结束后,将生成的回复内容及时更新到数据库中,确保聊天记录保持最新状态。
|
||||
|
||||
**注意**:
|
||||
- 确保`response`参数是有效的LLMResult对象,且至少包含一个生成的回复,以避免访问不存在的索引导致错误。
|
||||
- 在实际应用中,需要确保`self.message_id`对应的聊天记录存在于数据库中,以便`update_message`函数能够正确地找到并更新该记录。
|
||||
- `**kwargs`参数提供了额外的灵活性,但在当前的实现中未被直接使用。开发者可以根据需要在未来的版本中扩展该方法的功能,利用这些额外的参数。
|
||||
***
|
||||
71
markdown_docs/server/chat/agent_chat.md
Normal file
@ -0,0 +1,71 @@
|
||||
## FunctionDef agent_chat(query, history, stream, model_name, temperature, max_tokens, prompt_name)
|
||||
**agent_chat**: 该函数用于处理与代理的异步聊天对话。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的查询字符串,必填参数。
|
||||
- `history`: 历史对话列表,每个元素为一个`History`对象。
|
||||
- `stream`: 是否以流式输出的方式返回数据,默认为`False`。
|
||||
- `model_name`: 使用的LLM模型名称,默认为`LLM_MODELS`列表中的第一个模型。
|
||||
- `temperature`: LLM采样温度,用于调整生成文本的随机性,默认值由`TEMPERATURE`常量决定,取值范围为0.0到1.0。
|
||||
- `max_tokens`: 限制LLM生成Token的数量,默认为`None`,代表使用模型的最大值。
|
||||
- `prompt_name`: 使用的prompt模板名称,默认为"default"。
|
||||
|
||||
**代码描述**:
|
||||
`agent_chat`函数是一个异步函数,主要负责处理用户与代理的聊天对话。它首先将传入的历史对话列表`history`转换为`History`对象列表。然后,定义了一个异步迭代器`agent_chat_iterator`,用于生成聊天回复。在`agent_chat_iterator`中,根据传入的参数和配置,初始化相应的LLM模型和工具,处理历史对话记录,并根据用户的查询生成回复。
|
||||
|
||||
如果设置了`stream`参数为`True`,则函数以流式输出的方式返回数据,适用于需要实时更新聊天内容的场景。在流式输出模式下,函数会根据不同的状态(如工具调用开始、完成、错误等)生成不同的JSON格式数据块,并通过`yield`语句异步返回给调用者。
|
||||
|
||||
在非流式输出模式下,函数会收集所有生成的聊天回复,并在最终将它们整合为一个JSON格式的响应体返回。
|
||||
|
||||
**注意**:
|
||||
- 在使用`agent_chat`函数时,需要确保传入的`history`参数格式正确,即每个元素都应为`History`对象或能够转换为`History`对象的数据结构。
|
||||
- `stream`参数的设置会影响函数的返回方式,根据实际应用场景选择合适的模式。
|
||||
- 函数依赖于配置好的LLM模型和prompt模板,确保在调用前已正确配置这些依赖项。
|
||||
|
||||
**输出示例**:
|
||||
在非流式输出模式下,假设用户的查询得到了一系列的聊天回复,函数可能返回如下格式的JSON数据:
|
||||
```json
|
||||
{
|
||||
"answer": "这是聊天过程中生成的回复文本。",
|
||||
"final_answer": "这是最终的回复文本。"
|
||||
}
|
||||
```
|
||||
在流式输出模式下,函数会逐块返回数据,每块数据可能如下所示:
|
||||
```json
|
||||
{
|
||||
"tools": [
|
||||
"工具名称: 天气查询",
|
||||
"工具状态: 调用成功",
|
||||
"工具输入: 北京今天天气",
|
||||
"工具输出: 北京今天多云,10-14摄氏度"
|
||||
]
|
||||
}
|
||||
```
|
||||
或者在得到最终回复时:
|
||||
```json
|
||||
{
|
||||
"final_answer": "这是最终的回复文本。"
|
||||
}
|
||||
```
|
||||
### FunctionDef agent_chat_iterator(query, history, model_name, prompt_name)
|
||||
**agent_chat_iterator**: 此函数的功能是异步迭代生成代理聊天的响应。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,用户的查询或输入。
|
||||
- `history`: 可选的`List[History]`类型,表示对话历史记录。
|
||||
- `model_name`: 字符串类型,默认为`LLM_MODELS`列表中的第一个模型,用于指定使用的语言模型。
|
||||
- `prompt_name`: 字符串类型,用于指定提示模板的名称。
|
||||
|
||||
**代码描述**:
|
||||
`agent_chat_iterator`函数是一个异步生成器,用于处理代理聊天的逻辑。首先,函数检查`max_tokens`是否为整数且小于等于0,如果是,则将其设置为`None`。接着,使用`get_ChatOpenAI`函数初始化一个聊天模型实例,并通过`get_kb_details`函数获取知识库列表,将其存储在模型容器的数据库中。如果存在`Agent_MODEL`,则使用该模型初始化另一个聊天模型实例,并将其存储在模型容器中;否则,使用之前初始化的模型。
|
||||
|
||||
函数通过`get_prompt_template`函数获取指定的提示模板,并使用`CustomPromptTemplate`类创建一个自定义提示模板实例。然后,使用`CustomOutputParser`类创建一个输出解析器实例,并根据模型名称决定使用`initialize_glm3_agent`函数初始化GLM3代理执行器,或者使用`LLMSingleActionAgent`和`AgentExecutor`创建一个代理执行器。
|
||||
|
||||
在异步循环中,函数尝试创建一个任务,使用`wrap_done`函数包装代理执行器的调用,并在完成时通过回调通知。如果设置了`stream`参数,则函数会异步迭代回调处理器的输出,并根据状态生成不同的响应数据,最终以JSON格式产生输出。如果未设置`stream`参数,则会收集所有输出数据,并在最后生成一个包含答案和最终答案的JSON对象。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保提供的`history`参数格式正确,且每个历史记录项都应为`History`类的实例。
|
||||
- `model_name`和`prompt_name`参数应根据实际需要选择合适的模型和提示模板。
|
||||
- 函数内部使用了多个异步操作和自定义类,如`CustomAsyncIteratorCallbackHandler`、`CustomPromptTemplate`和`CustomOutputParser`,需要确保这些组件的正确实现和配置。
|
||||
- 此函数设计为与前端实现实时或异步的聊天交互,因此在集成到聊天系统时,应考虑其异步特性和对外部回调的处理方式。
|
||||
***
|
||||
57
markdown_docs/server/chat/chat.md
Normal file
@ -0,0 +1,57 @@
|
||||
## FunctionDef chat(query, conversation_id, history_len, history, stream, model_name, temperature, max_tokens, prompt_name)
|
||||
**chat**: 此函数用于实现与LLM模型的对话功能。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的查询字符串。
|
||||
- `conversation_id`: 对话框ID,用于标识一个对话会话。
|
||||
- `history_len`: 从数据库中取历史消息的数量。
|
||||
- `history`: 历史对话记录,可以是一个整数或一个历史记录列表。
|
||||
- `stream`: 是否以流式输出的方式返回对话结果。
|
||||
- `model_name`: LLM模型名称。
|
||||
- `temperature`: LLM采样温度,用于控制生成文本的随机性。
|
||||
- `max_tokens`: 限制LLM生成Token的数量。
|
||||
- `prompt_name`: 使用的prompt模板名称。
|
||||
|
||||
**代码描述**:
|
||||
此函数主要负责处理用户与LLM模型之间的对话。它首先通过`add_message_to_db`函数将用户的查询和对话信息保存到数据库中。然后,根据传入的参数,如历史对话记录、模型名称、温度等,构建一个适合LLM模型的输入提示(prompt)。接着,使用`LLMChain`对象发起对话请求,并通过`AsyncIteratorCallbackHandler`处理模型的异步响应。如果启用了流式输出,函数将逐个Token地返回响应结果;否则,会等待所有响应完成后,一次性返回整个对话结果。最后,通过`EventSourceResponse`将结果以服务器发送事件(SSE)的形式返回给客户端。
|
||||
|
||||
**注意**:
|
||||
- 在使用`history`参数时,可以直接传入历史对话记录的列表,或者传入一个整数,函数会从数据库中读取指定数量的历史消息。
|
||||
- `stream`参数控制输出模式,当设置为True时,对话结果将以流式输出,适用于需要实时显示对话过程的场景。
|
||||
- `max_tokens`参数用于限制LLM模型生成的Token数量,有助于控制生成文本的长度。
|
||||
|
||||
**输出示例**:
|
||||
假设函数以非流式模式运行,并且返回了一条简单的对话响应:
|
||||
```json
|
||||
{
|
||||
"text": "好的,我明白了。",
|
||||
"message_id": "123456"
|
||||
}
|
||||
```
|
||||
这表示LLM模型对用户的查询给出了回复“好的,我明白了。”,并且该对话消息在数据库中的ID为"123456"。
|
||||
### FunctionDef chat_iterator
|
||||
**chat_iterator**: 此函数的功能是异步迭代聊天过程,生成并流式传输聊天响应。
|
||||
|
||||
**参数**:
|
||||
- 无参数直接传递给此函数,但函数内部使用了多个外部定义的变量和对象。
|
||||
|
||||
**代码描述**:
|
||||
`chat_iterator`是一个异步生成器函数,用于处理聊天会话,生成聊天响应并以流的形式传输。函数首先定义了一个`callback`对象,该对象是`AsyncIteratorCallbackHandler`的实例,用于处理异步迭代的回调。接着,创建了一个回调列表`callbacks`,并将`callback`对象添加到其中。
|
||||
|
||||
函数通过调用`add_message_to_db`函数,将聊天请求添加到数据库中,并创建了一个`conversation_callback`对象,该对象是`ConversationCallbackHandler`的实例,用于处理聊天过程中的回调,并将其添加到回调列表中。
|
||||
|
||||
根据`max_tokens`的值调整生成文本的最大token数量,如果`max_tokens`为非正整数,则将其设置为`None`。
|
||||
|
||||
接下来,通过调用`get_ChatOpenAI`函数,初始化一个聊天模型`model`,并根据聊天历史(如果有)或会话ID(如果指定)来构建聊天提示`chat_prompt`。如果没有提供历史或会话ID,则使用默认的提示模板。
|
||||
|
||||
然后,创建了一个`LLMChain`对象`chain`,它负责将聊天提示传递给聊天模型,并开始一个异步任务,该任务使用`wrap_done`函数包装了`chain.acall`的调用,以便在任务完成时通过`callback.done`方法进行通知。
|
||||
|
||||
最后,根据`stream`变量的值决定是流式传输每个生成的token,还是等待所有token生成后一次性返回。在流式传输模式下,使用`json.dumps`将生成的token和消息ID封装成JSON格式并逐个yield返回;在非流式传输模式下,将所有生成的token拼接后一次性yield返回。
|
||||
|
||||
**注意**:
|
||||
- `chat_iterator`函数是异步的,因此在调用时需要使用`await`关键字或在其他异步函数中调用。
|
||||
- 函数内部使用了多个外部定义的变量和对象,如`history`、`max_tokens`等,这要求在调用`chat_iterator`之前,这些变量和对象必须已经被正确初始化和配置。
|
||||
- 函数依赖于多个外部定义的函数和类,如`AsyncIteratorCallbackHandler`、`add_message_to_db`、`ConversationCallbackHandler`、`get_ChatOpenAI`等,确保这些依赖项在项目中已正确实现。
|
||||
- 在处理聊天响应时,函数考虑了多种情况,包括有无聊天历史、是否从数据库获取历史消息等,这要求调用者根据实际情况提供正确的参数和配置。
|
||||
- 使用此函数时,应注意异常处理和资源管理,确保在聊天会话结束时释放所有资源。
|
||||
***
|
||||
50
markdown_docs/server/chat/completion.md
Normal file
@ -0,0 +1,50 @@
|
||||
## FunctionDef completion(query, stream, echo, model_name, temperature, max_tokens, prompt_name)
|
||||
**completion**: 此函数用于处理用户输入,生成并返回由LLM模型补全的文本。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的文本。
|
||||
- `stream`: 是否以流式输出结果。
|
||||
- `echo`: 是否在输出结果中回显输入文本。
|
||||
- `model_name`: 使用的LLM模型名称。
|
||||
- `temperature`: LLM模型采样温度,用于控制生成文本的随机性。
|
||||
- `max_tokens`: 限制LLM模型生成的Token数量。
|
||||
- `prompt_name`: 使用的prompt模板名称。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先定义了一个异步生成器`completion_iterator`,该生成器负责实际的文本生成逻辑。它使用`get_OpenAI`函数初始化一个LLM模型,并根据提供的参数配置模型。然后,它使用`get_prompt_template`函数获取指定的prompt模板,并将用户输入的`query`传递给LLM模型进行处理。根据`stream`参数的值,此函数可以以流式方式逐个返回生成的Token,或者等待所有Token生成完成后一次性返回结果。最后,使用`EventSourceResponse`包装`completion_iterator`生成器,以适合流式输出的HTTP响应格式返回结果。
|
||||
|
||||
在项目中,`completion`函数通过`/other/completion`路由在`server/api.py`文件中被注册为一个POST请求的处理器。这表明它设计用于处理来自客户端的文本补全请求,客户端可以通过发送POST请求到此路由,并在请求体中提供相应的参数,来获取LLM模型基于用户输入生成的补全文本。
|
||||
|
||||
**注意**:
|
||||
- 确保`model_name`参数对应的LLM模型已正确配置且可用。
|
||||
- `temperature`参数应在0.0到1.0之间,以控制生成文本的随机性。
|
||||
- 如果`max_tokens`设为负数或0,将不会限制Token数量。
|
||||
|
||||
**输出示例**:
|
||||
如果`stream`参数为`False`,并且用户输入为"今天天气如何",一个可能的返回值示例为:
|
||||
```
|
||||
"今天天气晴朗,适合外出。"
|
||||
```
|
||||
如果`stream`参数为`True`,则可能逐个返回上述文本中的每个字或词。
|
||||
### FunctionDef completion_iterator(query, model_name, prompt_name, echo)
|
||||
**completion_iterator**: 此函数的功能是异步迭代生成基于给定查询的完成文本。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,用户的查询输入。
|
||||
- `model_name`: 字符串类型,默认为LLM_MODELS列表中的第一个模型,指定使用的语言模型名称。
|
||||
- `prompt_name`: 字符串类型,指定使用的提示模板名称。
|
||||
- `echo`: 布尔类型,指示是否回显输入。
|
||||
|
||||
**代码描述**:
|
||||
`completion_iterator`函数是一个异步生成器,用于根据用户的查询输入生成文本。首先,函数检查`max_tokens`参数是否为整数且小于等于0,如果是,则将其设置为None。接着,通过`get_OpenAI`函数初始化一个配置好的OpenAI模型实例,其中包括模型名称、温度、最大令牌数、回调函数列表以及是否回显输入等参数。然后,使用`get_prompt_template`函数加载指定类型和名称的提示模板,并通过`PromptTemplate.from_template`方法创建一个`PromptTemplate`实例。之后,创建一个`LLMChain`实例,将提示模板和语言模型作为参数传入。
|
||||
|
||||
函数接下来创建一个异步任务,使用`asyncio.create_task`方法将`chain.acall`方法的调用包装起来,并通过`wrap_done`函数与一个回调函数关联,以便在任务完成时进行通知。根据`stream`变量的值,函数将以不同的方式生成文本。如果`stream`为真,则通过`callback.aiter()`异步迭代每个生成的令牌,并使用服务器发送事件(server-sent-events)来流式传输响应。如果`stream`为假,则将所有生成的令牌累加到一个字符串中,然后一次性生成整个答案。
|
||||
|
||||
最后,函数等待之前创建的异步任务完成,确保所有生成的文本都已处理完毕。
|
||||
|
||||
**注意**:
|
||||
- 使用此函数时,需要确保`query`参数正确无误,因为它直接影响生成文本的内容。
|
||||
- `model_name`和`prompt_name`参数应根据需要选择合适的模型和提示模板,以获得最佳的文本生成效果。
|
||||
- 在使用流式传输功能时,应考虑客户端如何处理流式数据,以确保用户体验。
|
||||
- 此函数依赖于`get_OpenAI`和`get_prompt_template`等函数,因此在使用前应确保相关配置和模板已正确设置。
|
||||
***
|
||||
32
markdown_docs/server/chat/feedback.md
Normal file
@ -0,0 +1,32 @@
|
||||
## FunctionDef chat_feedback(message_id, score, reason)
|
||||
**chat_feedback**: 此函数用于处理用户对聊天记录的反馈。
|
||||
|
||||
**参数**:
|
||||
- `message_id`: 聊天记录的唯一标识ID,用于定位需要反馈的聊天记录。此参数最大长度为32个字符。
|
||||
- `score`: 用户对聊天记录的评分,满分为100。评分越高表示用户对聊天记录的满意度越高。
|
||||
- `reason`: 用户提供的评分理由,例如聊天记录不符合事实等。
|
||||
|
||||
**代码描述**:
|
||||
`chat_feedback`函数首先尝试调用`feedback_message_to_db`函数,将用户的反馈信息(包括聊天记录ID、评分和评分理由)存储到数据库中。如果在执行过程中遇到任何异常,函数将捕获这些异常,并通过`logger.error`记录错误信息,同时返回一个包含错误信息的`BaseResponse`对象,状态码为500,表示服务器内部错误。如果没有发生异常,函数将返回一个状态码为200的`BaseResponse`对象,表示用户反馈已成功处理,并附带消息“已反馈聊天记录 {message_id}”。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的`message_id`是有效的,并且在数据库中存在对应的聊天记录。
|
||||
- `score`参数应在0到100之间,以确保评分的有效性。
|
||||
- 在实际应用中,可能需要对用户的评分理由`reason`进行长度或内容的校验,以避免存储无效或不恰当的信息。
|
||||
- 此函数通过捕获异常并记录错误信息,提高了代码的健壮性。开发者应关注日志输出,以便及时发现并处理潜在的问题。
|
||||
|
||||
**输出示例**:
|
||||
如果用户反馈成功处理,函数可能返回如下的`BaseResponse`对象示例:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "已反馈聊天记录 1234567890abcdef"
|
||||
}
|
||||
```
|
||||
如果处理过程中发生异常,函数可能返回如下的`BaseResponse`对象示例:
|
||||
```json
|
||||
{
|
||||
"code": 500,
|
||||
"msg": "反馈聊天记录出错:[异常信息]"
|
||||
}
|
||||
```
|
||||
148
markdown_docs/server/chat/file_chat.md
Normal file
@ -0,0 +1,148 @@
|
||||
## FunctionDef _parse_files_in_thread(files, dir, zh_title_enhance, chunk_size, chunk_overlap)
|
||||
**_parse_files_in_thread**: 该函数的功能是通过多线程将上传的文件保存到指定目录,并对文件内容进行处理。
|
||||
|
||||
**参数**:
|
||||
- `files`: 一个`UploadFile`对象的列表,表示需要处理的上传文件。
|
||||
- `dir`: 字符串,表示文件保存的目标目录。
|
||||
- `zh_title_enhance`: 布尔值,指示是否开启中文标题加强功能。
|
||||
- `chunk_size`: 整数,指定文本处理时单个块的大小。
|
||||
- `chunk_overlap`: 整数,指定文本处理时相邻块之间的重叠长度。
|
||||
|
||||
**代码描述**:
|
||||
该函数首先定义了一个内部函数`parse_file`,用于处理单个文件。`parse_file`尝试读取上传文件的内容,并将其保存到指定目录。如果目录不存在,则会创建该目录。之后,使用`KnowledgeFile`对象对文件内容进行处理,包括文本提取和可能的中文标题加强处理,根据`chunk_size`和`chunk_overlap`参数对文本进行分块处理。处理成功后,返回一个包含成功标志、文件名、成功消息和文档对象列表的元组;处理失败时,返回一个包含失败标志、文件名、错误消息和空列表的元组。
|
||||
|
||||
接下来,函数使用`run_in_thread_pool`函数并发地对`files`列表中的每个文件执行`parse_file`函数。`run_in_thread_pool`接受一个函数和一个参数列表,创建一个线程池并在其中并发执行该函数,最后以生成器的形式返回每个任务的结果。`_parse_files_in_thread`函数遍历这些结果,并将它们逐一返回。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`dir`路径存在或该函数有权限创建目录。
|
||||
- 由于使用了多线程,确保所有操作(特别是文件写入和文本处理)都是线程安全的。
|
||||
- 调用此函数时,应通过迭代来处理返回的生成器,以获取所有文件的处理结果。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
(True, "example.txt", "成功上传文件 example.txt", [<文档对象>]),
|
||||
(False, "error.txt", "error.txt 文件上传失败,报错信息为: 文件无法读取", [])
|
||||
]
|
||||
```
|
||||
该输出示例展示了函数处理两个文件的可能结果:第一个文件成功处理,返回成功标志、文件名、成功消息和文档对象列表;第二个文件处理失败,返回失败标志、文件名、错误消息和一个空列表。
|
||||
### FunctionDef parse_file(file)
|
||||
**parse_file**: 此函数的功能是保存单个文件,并将其内容转换为文本列表。
|
||||
|
||||
**参数**:
|
||||
- `file`: `UploadFile`类型,表示需要被解析和保存的上传文件。
|
||||
|
||||
**代码描述**:
|
||||
`parse_file`函数首先从上传的文件中提取文件名,并构建文件应该被保存到的路径。然后,它会检查这个路径所在的目录是否存在,如果不存在,则创建该目录。接下来,函数以二进制写入模式打开目标路径的文件,并将上传的文件内容写入其中。
|
||||
|
||||
在文件成功保存之后,函数创建一个`KnowledgeFile`实例,用于处理和转换文件内容。通过调用`KnowledgeFile`类的`file2text`方法,文件内容被转换为文本列表。这一过程支持中文标题增强、分块处理以及自定义文本分割器,便于后续的文本分析或处理任务。
|
||||
|
||||
如果文件处理和转换过程中出现任何异常,函数将捕获这些异常,并返回一个包含错误信息的响应,指示文件上传失败。
|
||||
|
||||
**注意**:
|
||||
- 确保上传的文件路径是有效的,并且服务器有足够的权限在指定位置创建文件和目录。
|
||||
- `KnowledgeFile`类的使用需要确保文件格式被支持,且相关的处理参数(如中文标题增强、分块大小等)已正确设置。
|
||||
- 异常处理部分对于识别和调试文件上传或处理过程中可能出现的问题非常重要。
|
||||
|
||||
**输出示例**:
|
||||
调用`parse_file`函数可能会返回以下形式的元组:
|
||||
```python
|
||||
(True, "example.txt", "成功上传文件 example.txt", ["文档内容示例"])
|
||||
```
|
||||
如果遇到错误,则返回的元组可能如下:
|
||||
```python
|
||||
(False, "example.txt", "example.txt 文件上传失败,报错信息为: 文件格式不支持", [])
|
||||
```
|
||||
这个返回值分别表示处理的成功与否、文件名、相关消息以及处理后的文本列表(或在失败时为空列表)。
|
||||
***
|
||||
## FunctionDef upload_temp_docs(files, prev_id, chunk_size, chunk_overlap, zh_title_enhance)
|
||||
**upload_temp_docs**: 该函数的功能是将文件保存到临时目录,并进行向量化处理。
|
||||
|
||||
**参数**:
|
||||
- `files`: 上传的文件列表,类型为`List[UploadFile]`。支持多文件上传。
|
||||
- `prev_id`: 前知识库ID,类型为`str`。用于指定之前的临时目录ID,如果提供,则尝试复用该目录。
|
||||
- `chunk_size`: 知识库中单段文本的最大长度,类型为`int`。用于在文本处理时指定单个块的大小。
|
||||
- `chunk_overlap`: 知识库中相邻文本的重合长度,类型为`int`。用于在文本处理时指定相邻块之间的重叠长度。
|
||||
- `zh_title_enhance`: 是否开启中文标题加强,类型为`bool`。用于指示是否对中文标题进行加强处理。
|
||||
|
||||
**代码描述**:
|
||||
函数首先检查`prev_id`是否存在,如果存在,则从`memo_faiss_pool`中移除对应的临时向量库。接着,初始化失败文件列表`failed_files`和文档列表`documents`。通过调用`get_temp_dir`函数,根据`prev_id`获取或创建临时目录的路径和ID。然后,使用`_parse_files_in_thread`函数并发处理上传的文件,该函数会将文件保存到指定的临时目录,并进行必要的文本处理和向量化。处理结果包括成功标志、文件对象、消息和文档列表。对于处理成功的文件,其文档列表会被添加到`documents`中;对于处理失败的文件,其文件名和错误消息会被添加到`failed_files`列表中。之后,通过`load_vector_store`函数加载或初始化临时向量库,并使用`acquire`上下文管理器确保线程安全。最后,将文档列表添加到向量库中,并返回包含临时目录ID和失败文件列表的`BaseResponse`对象。
|
||||
|
||||
**注意**:
|
||||
- 在上传文件时,应确保文件类型和大小符合要求,以避免上传失败。
|
||||
- 如果指定了`prev_id`,函数会尝试复用之前的临时目录,这可以减少不必要的目录创建操作。
|
||||
- 在处理大量文件或大型文件时,应注意函数的执行时间,可能需要较长的处理时间。
|
||||
- 使用`zh_title_enhance`参数可以针对中文标题进行加强处理,提高文本处理的质量。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"id": "临时目录ID",
|
||||
"failed_files": [
|
||||
{"file1": "错误消息1"},
|
||||
{"file2": "错误消息2"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
该输出示例展示了函数执行成功后的返回值,其中包含了临时目录的ID和失败文件列表。如果所有文件都成功处理,`failed_files`列表将为空。
|
||||
## FunctionDef file_chat(query, knowledge_id, top_k, score_threshold, history, stream, model_name, temperature, max_tokens, prompt_name)
|
||||
**file_chat**: 该函数用于处理用户通过文件聊天接口发送的查询,并返回相关的知识库文档内容以及基于这些内容的对话回复。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的查询内容,为字符串类型,必填项。
|
||||
- `knowledge_id`: 临时知识库ID,用于指定查询的知识库,为字符串类型,必填项。
|
||||
- `top_k`: 匹配向量数,指定返回的相关文档数量,为整数类型。
|
||||
- `score_threshold`: 知识库匹配相关度阈值,取值范围在0-1之间,用于筛选相关度高的文档,为浮点数类型。
|
||||
- `history`: 历史对话列表,包含用户和助手的对话历史,为列表类型。
|
||||
- `stream`: 是否流式输出,为布尔类型,指定是否以流的形式返回数据。
|
||||
- `model_name`: LLM 模型名称,用于指定生成回复时使用的语言模型,为字符串类型。
|
||||
- `temperature`: LLM 采样温度,用于调整生成文本的多样性,为浮点数类型。
|
||||
- `max_tokens`: 限制LLM生成Token数量,为整数类型,可选项。
|
||||
- `prompt_name`: 使用的prompt模板名称,用于指定生成回复时使用的模板,为字符串类型。
|
||||
|
||||
**代码描述**:
|
||||
该函数首先检查传入的`knowledge_id`是否存在于`memo_faiss_pool`中,如果不存在,则返回404错误。接着,将传入的历史对话列表转换为`History`对象列表。函数定义了一个异步生成器`knowledge_base_chat_iterator`,用于生成对话回复和相关文档内容。在这个生成器中,首先根据`max_tokens`的值调整Token数量限制,然后使用指定的LLM模型和温度参数创建一个聊天模型。通过`embed_func`将用户查询嵌入为向量,并使用`memo_faiss_pool`中的向量搜索功能找到最相关的文档。根据找到的文档和历史对话构建聊天提示,然后使用LLM模型生成回复。最后,根据`stream`参数的值决定是流式输出还是一次性返回所有数据。
|
||||
|
||||
**注意**:
|
||||
- 在使用该函数之前,需要确保`memo_faiss_pool`已经初始化,并且包含了至少一个知识库。
|
||||
- `history`参数中的历史对话记录应按照时间顺序排列,以便正确构建对话上下文。
|
||||
- 设置`score_threshold`可以帮助过滤掉相关度较低的文档,提高回复的准确性。
|
||||
- 如果`stream`参数设置为True,将以服务器发送事件(Server-Sent Events, SSE)的形式流式返回数据,适用于需要实时更新的场景。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"answer": "这是基于您的查询和相关文档生成的回复。",
|
||||
"docs": [
|
||||
"出处 [1] [source_document.pdf] \n\n这是相关文档的内容。\n\n"
|
||||
]
|
||||
}
|
||||
```
|
||||
如果`stream`参数为True,将分批次返回数据,每次返回一个包含回复片段的JSON对象,最后返回包含相关文档内容的JSON对象。
|
||||
### FunctionDef knowledge_base_chat_iterator
|
||||
**knowledge_base_chat_iterator**: 此函数的功能是异步迭代生成基于知识库的聊天回答。
|
||||
|
||||
**参数**:
|
||||
- 无参数直接传入此函数,但函数内部使用了多个全局变量和其他对象的方法。
|
||||
|
||||
**代码描述**:
|
||||
`knowledge_base_chat_iterator`函数是一个异步生成器,用于处理基于知识库的聊天回答。首先,它检查`max_tokens`是否为整数且小于等于0,如果是,则将`max_tokens`设置为None。接着,使用`get_ChatOpenAI`函数初始化一个ChatOpenAI实例,该实例用于生成聊天回答。此过程中,`model_name`、`temperature`、`max_tokens`等参数被用于配置模型,而`callbacks`参数中包含了一个`AsyncIteratorCallbackHandler`实例,用于处理异步回调。
|
||||
|
||||
函数继续通过`EmbeddingsFunAdapter`类的`aembed_query`方法异步获取查询文本的嵌入向量。然后,使用`memo_faiss_pool.acquire`方法安全地从缓存池中获取知识库向量存储对象,并执行相似度搜索,搜索结果存储在`docs`变量中。
|
||||
|
||||
根据搜索到的文档,函数构建聊天上下文`context`。如果没有找到相关文档,将使用`get_prompt_template`函数获取空模板;否则,根据`prompt_name`获取相应模板。接着,使用`History`类和`ChatPromptTemplate`构建聊天提示。
|
||||
|
||||
通过`LLMChain`类,函数将聊天提示和上下文传递给ChatOpenAI模型进行处理,生成的回答通过`wrap_done`函数包装的异步任务进行管理。
|
||||
|
||||
最后,函数根据是否启用流式传输(`stream`变量),以不同方式生成回答。如果启用流式传输,将通过`callback.aiter()`异步迭代回答并以服务器发送事件(server-sent-events)的形式逐个发送;如果未启用流式传输,将收集完整的回答后一次性返回。
|
||||
|
||||
**注意**:
|
||||
- 该函数是异步的,需要在支持异步的环境中运行。
|
||||
- 使用`knowledge_base_chat_iterator`函数时,需要确保相关的全局变量(如`model_name`、`temperature`等)已正确设置。
|
||||
- 函数内部使用了多个外部定义的对象和方法(如`get_ChatOpenAI`、`EmbeddingsFunAdapter`等),确保这些依赖项在调用此函数之前已正确初始化和配置。
|
||||
- 在处理大量或复杂的查询时,函数的执行时间可能较长,因此在设计用户界面和交互流程时应考虑到潜在的延迟。
|
||||
***
|
||||
64
markdown_docs/server/chat/knowledge_base_chat.md
Normal file
@ -0,0 +1,64 @@
|
||||
## FunctionDef knowledge_base_chat(query, knowledge_base_name, top_k, score_threshold, history, stream, model_name, temperature, max_tokens, prompt_name, request)
|
||||
**knowledge_base_chat**: 该函数用于处理用户与知识库的交互对话。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户的输入查询,类型为字符串。
|
||||
- `knowledge_base_name`: 知识库的名称,类型为字符串。
|
||||
- `top_k`: 匹配向量数,类型为整数。
|
||||
- `score_threshold`: 知识库匹配相关度阈值,取值范围在0-1之间,类型为浮点数。
|
||||
- `history`: 历史对话列表,每个元素为一个`History`对象。
|
||||
- `stream`: 是否以流式输出,类型为布尔值。
|
||||
- `model_name`: LLM模型名称,类型为字符串。
|
||||
- `temperature`: LLM采样温度,类型为浮点数。
|
||||
- `max_tokens`: 限制LLM生成Token数量,类型为整数或None。
|
||||
- `prompt_name`: 使用的prompt模板名称,类型为字符串。
|
||||
- `request`: 当前的请求对象,类型为`Request`。
|
||||
|
||||
**代码描述**:
|
||||
函数首先通过`KBServiceFactory.get_service_by_name`方法获取指定名称的知识库服务实例。如果未找到对应的知识库,将返回404状态码的响应。然后,将传入的历史对话数据转换为`History`对象列表。接下来,定义了一个异步生成器`knowledge_base_chat_iterator`,用于处理知识库查询和LLM模型生成回答的逻辑。在这个生成器中,首先根据条件调整`max_tokens`的值,然后创建LLM模型实例,并执行文档搜索。如果启用了重排序(reranker),则对搜索结果进行重排序处理。根据搜索结果构建上下文,并生成LLM模型的输入提示。最后,使用LLM模型生成回答,并根据`stream`参数决定是以流式输出还是一次性输出所有结果。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,需要确保传入的知识库名称在系统中已经存在,否则会返回404错误。
|
||||
- `history`参数允许传入空列表,表示没有历史对话。
|
||||
- `stream`参数控制输出模式,当设置为True时,将以流式输出回答和文档信息;否则,将一次性返回所有内容。
|
||||
- 函数内部使用了多个异步操作,因此在调用时需要使用`await`关键字。
|
||||
|
||||
**输出示例**:
|
||||
调用`knowledge_base_chat`函数可能返回的JSON格式示例:
|
||||
```json
|
||||
{
|
||||
"answer": "这是根据您的查询生成的回答。",
|
||||
"docs": [
|
||||
"出处 [1] [文档名称](文档链接) \n\n文档内容\n\n",
|
||||
"<span style='color:red'>未找到相关文档,该回答为大模型自身能力解答!</span>"
|
||||
]
|
||||
}
|
||||
```
|
||||
如果启用了流式输出,每个生成的回答片段和文档信息将作为独立的JSON对象逐个发送。
|
||||
### FunctionDef knowledge_base_chat_iterator(query, top_k, history, model_name, prompt_name)
|
||||
**knowledge_base_chat_iterator**: 此函数的功能是异步迭代生成基于知识库的聊天回答。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,用户的查询内容。
|
||||
- `top_k`: 整型,指定返回的最相关文档数量。
|
||||
- `history`: 可选的历史记录列表,每个历史记录是一个`History`对象。
|
||||
- `model_name`: 字符串类型,默认为`model_name`,指定使用的模型名称。
|
||||
- `prompt_name`: 字符串类型,默认为`prompt_name`,指定使用的提示模板名称。
|
||||
|
||||
**代码描述**:
|
||||
`knowledge_base_chat_iterator`函数是一个异步生成器,用于处理用户的查询请求,并基于知识库内容异步生成聊天回答。首先,函数检查`max_tokens`的有效性,并根据需要调整其值。接着,使用`get_ChatOpenAI`函数初始化一个聊天模型实例,该模型配置了模型名称、温度、最大token数和回调函数。
|
||||
|
||||
函数通过`run_in_threadpool`异步运行`search_docs`函数,根据用户的查询内容在知识库中搜索相关文档。如果启用了重排序功能(`USE_RERANKER`),则使用`LangchainReranker`类对搜索结果进行重排序,以提高结果的相关性。
|
||||
|
||||
根据搜索到的文档数量,函数选择相应的提示模板。如果没有找到相关文档,使用“empty”模板;否则,使用指定的`prompt_name`模板。然后,将历史记录和用户的查询请求转换为聊天提示模板。
|
||||
|
||||
使用`LLMChain`类创建一个聊天链,并通过`wrap_done`函数包装异步任务,以便在任务完成时进行回调处理。函数还生成了源文档的信息,包括文档的出处和内容。
|
||||
|
||||
最后,根据是否启用流式传输(`stream`),函数以不同方式异步生成聊天回答。如果启用流式传输,使用服务器发送事件(server-sent-events)逐个发送回答的token;否则,将所有token拼接后一次性返回。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保提供的`model_name`和`prompt_name`在系统中已配置且有效。
|
||||
- 当启用重排序功能时,需要确保`LangchainReranker`类的配置正确,包括模型路径和设备类型。
|
||||
- 函数的异步特性要求调用者使用`async`和`await`关键字进行调用,以确保异步操作的正确执行。
|
||||
- 在处理大量查询请求时,合理配置`top_k`和重排序参数可以有效提高处理效率和回答质量。
|
||||
***
|
||||
207
markdown_docs/server/chat/search_engine_chat.md
Normal file
@ -0,0 +1,207 @@
|
||||
## FunctionDef bing_search(text, result_len)
|
||||
**bing_search**: 此函数用于通过Bing搜索引擎进行文本搜索并返回搜索结果。
|
||||
|
||||
**参数**:
|
||||
- `text`: 需要搜索的文本内容。
|
||||
- `result_len`: 返回的搜索结果数量,默认为`SEARCH_ENGINE_TOP_K`。
|
||||
- `**kwargs`: 接受额外的关键字参数,用于扩展或自定义搜索行为。
|
||||
|
||||
**代码描述**:
|
||||
`bing_search`函数首先检查环境变量中是否设置了`BING_SEARCH_URL`和`BING_SUBSCRIPTION_KEY`。如果这两个环境变量未设置,函数将返回一个包含错误信息的字典,提示用户需要设置这些环境变量。错误信息包括一个提示信息、一个标题以及一个链接,该链接指向相关的帮助文档。
|
||||
|
||||
如果环境变量设置正确,函数将创建一个`BingSearchAPIWrapper`实例,使用提供的`BING_SUBSCRIPTION_KEY`和`BING_SEARCH_URL`。然后,使用此实例调用`results`方法,传入需要搜索的文本(`text`)和结果数量(`result_len`)。最后,返回搜索结果。
|
||||
|
||||
**注意**:
|
||||
- 确保在使用此函数之前已正确设置环境变量`BING_SEARCH_URL`和`BING_SUBSCRIPTION_KEY`,否则将无法执行搜索操作。
|
||||
- `result_len`参数允许调用者自定义返回的搜索结果数量,但实际返回结果也受Bing搜索API的限制。
|
||||
- 通过`**kwargs`参数,可以传递额外的搜索选项给Bing搜索API,但需要确保这些选项是API支持的。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
{
|
||||
"snippet": "这是搜索结果的摘要",
|
||||
"title": "搜索结果标题",
|
||||
"link": "https://example.com/search-result"
|
||||
},
|
||||
{
|
||||
"snippet": "这是另一个搜索结果的摘要",
|
||||
"title": "另一个搜索结果标题",
|
||||
"link": "https://example.com/another-search-result"
|
||||
}
|
||||
]
|
||||
```
|
||||
此示例展示了函数可能返回的搜索结果列表,每个结果包含`snippet`(摘要)、`title`(标题)和`link`(链接)。
|
||||
## FunctionDef duckduckgo_search(text, result_len)
|
||||
**duckduckgo_search**: 此函数用于通过DuckDuckGo搜索引擎执行文本搜索并返回结果。
|
||||
|
||||
**参数**:
|
||||
- `text`: 需要搜索的文本。
|
||||
- `result_len`: 返回结果的数量,默认值为`SEARCH_ENGINE_TOP_K`,这是一个预设的常量,用于指定默认的返回结果数量。
|
||||
- `**kwargs`: 接受额外的关键字参数,这些参数可以用于扩展或自定义搜索行为。
|
||||
|
||||
**代码描述**:
|
||||
`duckduckgo_search`函数首先创建了一个`DuckDuckGoSearchAPIWrapper`的实例,这是一个封装了DuckDuckGo搜索API调用的类。通过这个实例,函数使用`results`方法执行搜索。`text`参数是用户希望搜索的文本内容,而`result_len`参数指定了希望返回的搜索结果数量。如果调用时没有指定`result_len`,则会使用`SEARCH_ENGINE_TOP_K`作为默认值。此外,函数还接受任何额外的关键字参数(`**kwargs`),这提供了额外的灵活性,允许调用者根据需要传递更多的参数给搜索API。
|
||||
|
||||
**注意**:
|
||||
- 确保在使用此函数之前已正确设置和配置了`DuckDuckGoSearchAPIWrapper`类,包括任何必要的认证信息或API密钥。
|
||||
- `SEARCH_ENGINE_TOP_K`是一个预定义常量,需要在使用此函数之前定义。它决定了在未明确指定结果数量时返回的默认结果数量。
|
||||
- 由于`**kwargs`提供了额外的参数传递功能,使用时应注意只包含DuckDuckGo搜索API支持的参数,以避免发生错误。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
{"title": "DuckDuckGo", "snippet": "DuckDuckGo是一个注重隐私的搜索引擎。", "url": "https://duckduckgo.com"},
|
||||
{"title": "DuckDuckGo隐私政策", "snippet": "了解DuckDuckGo如何保护您的隐私。", "url": "https://duckduckgo.com/privacy"}
|
||||
]
|
||||
```
|
||||
此输出示例展示了一个可能的返回值,其中包含了搜索结果的列表。每个结果是一个字典,包含标题(`title`)、摘要(`snippet`)和URL(`url`)。实际返回的结果将根据搜索的文本和结果数量的指定而有所不同。
|
||||
## FunctionDef metaphor_search(text, result_len, split_result, chunk_size, chunk_overlap)
|
||||
**metaphor_search**: 此函数的功能是基于给定文本进行隐喻搜索,并返回搜索结果的列表。
|
||||
|
||||
**参数**:
|
||||
- `text`: 需要搜索的文本,类型为字符串。
|
||||
- `result_len`: 返回结果的最大数量,默认为`SEARCH_ENGINE_TOP_K`。
|
||||
- `split_result`: 是否将搜索结果分割成更小的文本块,默认为`False`。
|
||||
- `chunk_size`: 分割文本块的大小,默认为500个字符。
|
||||
- `chunk_overlap`: 分割文本块时的重叠字符数,默认为`OVERLAP_SIZE`。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先检查是否提供了`METAPHOR_API_KEY`,如果没有提供,则直接返回空列表。如果提供了,函数将使用此API密钥创建一个`Metaphor`客户端,并使用该客户端对给定的文本进行搜索。搜索结果的数量由`result_len`参数控制,且默认启用自动提示功能。
|
||||
|
||||
搜索结果中的每个条目都会通过`markdownify`函数转换其摘要部分,以便更好地展示。
|
||||
|
||||
如果`split_result`参数为`True`,函数将对每个搜索结果的内容进行分割,以生成更小的文本块。这些文本块通过`RecursiveCharacterTextSplitter`根据给定的分割符和`chunk_size`、`chunk_overlap`参数进行分割。然后,基于与原始搜索文本的相似度,选择相似度最高的`result_len`个文本块作为最终结果。
|
||||
|
||||
如果`split_result`为`False`,则直接返回搜索结果的摘要、链接和标题。
|
||||
|
||||
**注意**:
|
||||
- 确保在使用此函数之前已正确设置`METAPHOR_API_KEY`。
|
||||
- `SEARCH_ENGINE_TOP_K`和`OVERLAP_SIZE`需要根据实际情况预先定义。
|
||||
- 分割结果的功能适用于需要对长文本进行进一步分析的场景。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
{
|
||||
"snippet": "这是搜索结果的一个示例文本片段。",
|
||||
"link": "https://example.com/link-to-source",
|
||||
"title": "示例文本标题"
|
||||
},
|
||||
# 更多搜索结果...
|
||||
]
|
||||
```
|
||||
此输出示例展示了当`split_result`为`False`时,函数可能返回的搜索结果的格式。每个结果包含了文本片段(`snippet`)、源链接(`link`)和标题(`title`)。
|
||||
## FunctionDef search_result2docs(search_results)
|
||||
**search_result2docs**: 此函数的功能是将搜索结果转换为文档列表。
|
||||
|
||||
**参数**:
|
||||
- search_results: 搜索结果的列表,每个结果是一个包含至少一个“snippet”、“link”和“title”键的字典。
|
||||
|
||||
**代码描述**:
|
||||
`search_result2docs`函数接收一个搜索结果列表作为输入,遍历这个列表,并为每个结果创建一个`Document`对象。这个`Document`对象包含页面内容(由结果中的“snippet”键提供,如果不存在则为空字符串)、来源链接(由“link”键提供,如果不存在则为空字符串)和文件名(由“title”键提供,如果不存在则为空字符串)。这些信息被存储在`Document`对象的`page_content`和`metadata`属性中。最后,所有创建的`Document`对象被收集到一个列表中并返回。
|
||||
|
||||
在项目中,`search_result2docs`函数被`lookup_search_engine`函数调用,用于处理从特定搜索引擎返回的搜索结果。`lookup_search_engine`函数首先根据给定的查询参数和搜索引擎名称,通过搜索引擎获取搜索结果,然后调用`search_result2docs`函数将这些搜索结果转换为`Document`对象的列表,以便进一步处理或展示。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的搜索结果列表格式正确,每个结果字典至少包含“snippet”、“link”和“title”三个键。
|
||||
- 函数的输出依赖于输入的搜索结果的质量和完整性。
|
||||
|
||||
**输出示例**:
|
||||
假设`search_results`参数是以下列表:
|
||||
```python
|
||||
[
|
||||
{"snippet": "这是搜索结果的摘要", "link": "https://example.com", "title": "示例标题"},
|
||||
{"snippet": "第二个搜索结果的摘要", "link": "https://example2.com", "title": "第二个示例标题"}
|
||||
]
|
||||
```
|
||||
那么函数的返回值可能是一个包含两个`Document`对象的列表,每个对象的`page_content`分别是"这是搜索结果的摘要"和"第二个搜索结果的摘要",`metadata`包含相应的"source"和"filename"信息。
|
||||
## FunctionDef lookup_search_engine(query, search_engine_name, top_k, split_result)
|
||||
**lookup_search_engine**: 此函数的功能是异步查询指定搜索引擎并返回搜索结果转换后的文档列表。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,表示要在搜索引擎中查询的关键词。
|
||||
- `search_engine_name`: 字符串类型,指定要查询的搜索引擎的名称。
|
||||
- `top_k`: 整型,默认值为`SEARCH_ENGINE_TOP_K`,表示返回的搜索结果的最大数量。
|
||||
- `split_result`: 布尔类型,默认为`False`,指示是否拆分搜索结果。
|
||||
|
||||
**代码描述**:
|
||||
`lookup_search_engine`函数首先通过`search_engine_name`参数从`SEARCH_ENGINES`字典中获取对应的搜索引擎函数。然后,它使用`run_in_threadpool`函数异步运行该搜索引擎函数,传入`query`、`result_len=top_k`和`split_result=split_result`作为参数,以获取搜索结果。获取到的搜索结果随后被传递给`search_result2docs`函数,该函数将搜索结果转换为文档(`Document`)对象的列表。最终,这个文档列表被返回。
|
||||
|
||||
在项目中,`lookup_search_engine`函数被`search_engine_chat_iterator`函数调用,用于获取搜索引擎的查询结果,并将这些结果转换为文档列表,以便在聊天迭代器中生成基于搜索引擎结果的聊天回复。
|
||||
|
||||
**注意**:
|
||||
- 确保`search_engine_name`参数对应的搜索引擎已经在`SEARCH_ENGINES`字典中定义。
|
||||
- `top_k`参数控制返回的搜索结果数量,根据需要调整以获取最优的搜索体验。
|
||||
- `split_result`参数可以控制搜索结果是否需要被拆分,这取决于搜索引擎函数的具体实现和需求。
|
||||
|
||||
**输出示例**:
|
||||
假设搜索查询返回了两个结果,函数的返回值可能是如下格式的文档列表:
|
||||
```python
|
||||
[
|
||||
Document(page_content="这是搜索结果的摘要", metadata={"source": "https://example.com", "filename": "示例标题"}),
|
||||
Document(page_content="第二个搜索结果的摘要", metadata={"source": "https://example2.com", "filename": "第二个示例标题"})
|
||||
]
|
||||
```
|
||||
这个列表中的每个`Document`对象包含了搜索结果的摘要、来源链接和标题,可用于进一步的处理或展示。
|
||||
## FunctionDef search_engine_chat(query, search_engine_name, top_k, history, stream, model_name, temperature, max_tokens, prompt_name, split_result)
|
||||
**search_engine_chat**: 该函数用于通过搜索引擎检索信息,并结合历史对话和LLM模型生成回答。
|
||||
|
||||
**参数**:
|
||||
- `query`: 用户输入的查询内容,类型为字符串。
|
||||
- `search_engine_name`: 指定使用的搜索引擎名称,类型为字符串。
|
||||
- `top_k`: 检索结果的数量,类型为整数。
|
||||
- `history`: 历史对话列表,每个元素为一个`History`对象。
|
||||
- `stream`: 是否以流式输出结果,类型为布尔值。
|
||||
- `model_name`: 指定使用的LLM模型名称,类型为字符串。
|
||||
- `temperature`: LLM模型采样温度,用于控制生成文本的多样性,类型为浮点数。
|
||||
- `max_tokens`: 限制LLM生成Token的数量,类型为整数或None。
|
||||
- `prompt_name`: 使用的prompt模板名称,类型为字符串。
|
||||
- `split_result`: 是否对搜索结果进行拆分,主要用于metaphor搜索引擎,类型为布尔值。
|
||||
|
||||
**代码描述**:
|
||||
该函数首先检查指定的搜索引擎是否支持,如果不支持或需要的配置项未设置,将返回错误信息。然后,将历史对话列表中的数据转换为`History`对象列表。接着,定义了一个异步迭代器`search_engine_chat_iterator`,用于执行搜索操作和生成回答。在这个迭代器中,首先根据条件调整`max_tokens`的值,然后创建LLM模型实例,并执行搜索引擎查询。查询结果和历史对话将被用于构建LLM模型的输入提示,以生成回答。根据`stream`参数的值,函数将以不同的方式输出结果:如果为True,则以流式形式输出每个生成的Token和最终的文档列表;如果为False,则将所有生成的Token拼接成完整的回答后一次性输出,同时附上文档列表。最后,返回一个`EventSourceResponse`对象,包含异步迭代器的执行结果。
|
||||
|
||||
**注意**:
|
||||
- 在使用该函数时,需要确保指定的搜索引擎已经在项目中支持,并且相关配置项(如API密钥)已正确设置。
|
||||
- `history`参数应为`History`对象的列表,每个对象代表一条历史对话记录。
|
||||
- 该函数支持流式输出,适用于需要实时展示生成结果的场景。
|
||||
- 函数的执行依赖于外部的LLM模型和搜索引擎服务,因此执行时间可能受到网络状况和服务响应时间的影响。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"answer": "根据您的查询,这里是生成的回答。",
|
||||
"docs": [
|
||||
"出处 [1] [来源链接](http://example.com)\n\n相关文档内容。\n\n",
|
||||
"出处 [2] [来源链接](http://example.com)\n\n相关文档内容。\n\n"
|
||||
]
|
||||
}
|
||||
```
|
||||
如果`stream`为True,输出将以多个json字符串的形式逐步发送,每个字符串包含一个Token或文档列表。如果为False,将输出一个包含完整回答和文档列表的json字符串。
|
||||
### FunctionDef search_engine_chat_iterator(query, search_engine_name, top_k, history, model_name, prompt_name)
|
||||
**search_engine_chat_iterator**: 此函数的功能是异步迭代搜索引擎查询结果,并生成基于这些结果的聊天回复。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,用户的查询请求。
|
||||
- `search_engine_name`: 字符串类型,指定要查询的搜索引擎名称。
|
||||
- `top_k`: 整型,指定返回的搜索结果的最大数量。
|
||||
- `history`: 可选的`List[History]`类型,表示对话历史记录。
|
||||
- `model_name`: 字符串类型,默认为`LLM_MODELS[0]`,指定使用的语言模型名称。
|
||||
- `prompt_name`: 字符串类型,指定使用的提示模板名称。
|
||||
|
||||
**代码描述**:
|
||||
`search_engine_chat_iterator`函数首先检查`max_tokens`的值,如果为非正整数,则将其设置为`None`。接着,通过`get_ChatOpenAI`函数初始化一个`ChatOpenAI`实例,该实例用于生成基于语言模型的聊天回复。函数使用`lookup_search_engine`异步查询指定的搜索引擎,获取搜索结果,并将这些结果转换为文本形式的上下文。
|
||||
|
||||
接下来,函数通过`get_prompt_template`获取指定的提示模板,并结合对话历史记录,构造出完整的聊天提示。这个提示将作为语言模型的输入,以生成聊天回复。函数创建一个异步任务,使用`wrap_done`函数包装这个任务,以便在任务完成或发生异常时进行通知。
|
||||
|
||||
函数还处理了搜索结果的文档来源信息,将其格式化为特定的字符串列表。如果没有找到相关文档,会添加一条特定的消息表示未找到相关文档。
|
||||
|
||||
最后,根据`stream`变量的值,函数可能以流式传输的方式逐个生成聊天回复,或者将所有回复合并后一次性返回。在流式传输模式下,每个生成的回复都会被立即发送给客户端,而在非流式模式下,则会等待所有回复生成完成后统一返回。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保提供的`search_engine_name`对应于已配置的搜索引擎。
|
||||
- `history`参数允许包含对话的历史记录,这对于生成更加连贯和上下文相关的回复非常重要。
|
||||
- 函数利用了异步编程模式,因此在调用此函数时应注意使用`await`关键字。
|
||||
- 在处理大量或复杂的查询时,函数的执行时间可能较长,因此在设计用户界面和交互逻辑时应考虑到潜在的延迟。
|
||||
***
|
||||
102
markdown_docs/server/chat/utils.md
Normal file
@ -0,0 +1,102 @@
|
||||
## ClassDef History
|
||||
**History**: History 类用于表示对话历史记录。
|
||||
|
||||
**属性**:
|
||||
- `role`: 表示发言角色,类型为字符串。
|
||||
- `content`: 表示发言内容,类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
History 类继承自 BaseModel,用于封装对话中的单条历史记录,包括发言角色和发言内容。它提供了将历史记录转换为消息元组的方法 `to_msg_tuple`,以及将历史记录转换为消息模板的方法 `to_msg_template`。此外,还提供了一个类方法 `from_data`,用于从不同类型的数据结构(列表、元组、字典)创建 History 实例。
|
||||
|
||||
在项目中,History 类被广泛用于处理和存储对话历史记录。例如,在 `agent_chat` 和 `chat` 等功能中,通过将用户输入和历史对话记录作为参数传递给模型,以生成相应的回复。这些历史记录通过 History 类的实例来管理和传递,确保了数据的一致性和易用性。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `to_msg_tuple` 方法时,如果 `role` 属性为 "assistant",则返回的元组中角色部分为 "ai",否则为 "human",这有助于在处理对话时区分用户和助手的发言。
|
||||
- `to_msg_template` 方法支持根据是否需要原始内容(`is_raw` 参数)来调整内容的格式,这在需要对内容进行特定格式处理时非常有用。
|
||||
- `from_data` 类方法提供了灵活的数据转换功能,允许从多种数据源创建 History 实例,增加了代码的通用性和灵活性。
|
||||
|
||||
**输出示例**:
|
||||
假设有以下历史记录数据:
|
||||
```python
|
||||
data = {"role": "user", "content": "你好"}
|
||||
```
|
||||
使用 History 类创建实例并转换为消息元组:
|
||||
```python
|
||||
h = History.from_data(data)
|
||||
print(h.to_msg_tuple())
|
||||
```
|
||||
可能的输出为:
|
||||
```
|
||||
('human', '你好')
|
||||
```
|
||||
转换为消息模板时,假设不需要原始内容处理:
|
||||
```python
|
||||
print(h.to_msg_template(is_raw=False))
|
||||
```
|
||||
输出将根据实际的模板格式化内容,其中角色和内容将被相应地替换和处理。
|
||||
### FunctionDef to_msg_tuple(self)
|
||||
**to_msg_tuple**: 此函数的功能是将消息对象转换为一个包含角色和内容的元组。
|
||||
|
||||
**参数**: 此函数没有显式参数,但隐式使用了self参数,代表调用此函数的History对象实例。
|
||||
|
||||
**代码描述**: `to_msg_tuple`函数是History类的一个方法,用于将消息对象的角色和内容转换成一个元组。此函数首先检查消息对象的`role`属性。如果`role`属性值为"assistant",则元组的第一个元素为字符串"ai";否则,第一个元素为字符串"human"。元组的第二个元素是消息对象的`content`属性值,即消息的内容。这样,通过`to_msg_tuple`方法可以快速地获取消息的角色和内容信息,便于后续处理或显示。
|
||||
|
||||
**注意**: 使用此函数时,需要确保调用它的History对象实例已经正确设置了`role`和`content`属性,否则可能会遇到属性不存在的错误。
|
||||
|
||||
**输出示例**: 假设一个History对象实例的`role`属性为"assistant",`content`属性为"你好,我是AI助手。",那么调用`to_msg_tuple`方法的返回值将会是:
|
||||
|
||||
```python
|
||||
("ai", "你好,我是AI助手。")
|
||||
```
|
||||
|
||||
如果`role`属性为其他值,比如"user",并且`content`属性为"这是一个用户消息。",那么返回值将会是:
|
||||
|
||||
```python
|
||||
("human", "这是一个用户消息。")
|
||||
```
|
||||
|
||||
这种方式使得消息的角色和内容可以被快速地识别和使用,对于消息处理和展示非常有用。
|
||||
***
|
||||
### FunctionDef to_msg_template(self, is_raw)
|
||||
**to_msg_template**: 该函数的功能是将历史消息转换为特定的消息模板格式。
|
||||
|
||||
**参数**:
|
||||
- `is_raw`: 布尔值,指示是否将消息内容作为原始文本处理。默认为True。
|
||||
|
||||
**代码描述**:
|
||||
`to_msg_template`函数是`History`类的一个方法,用于将历史消息转换为`ChatMessagePromptTemplate`格式,以便进一步处理和使用。该函数首先定义了一个角色映射字典`role_maps`,将"ai"映射为"assistant",将"human"映射为"user"。然后,根据`History`对象的`role`属性查找相应的角色,如果找不到,则使用`role`属性的原始值。
|
||||
|
||||
根据`is_raw`参数的值,函数决定是否将消息内容包裹在"{% raw %}"和"{% endraw %}"标签中。这主要用于处理消息内容中可能包含的Jinja2模板标签,以避免在后续处理中被错误地解释或执行。如果`is_raw`为True,则消息内容被包裹;否则,保持原样不变。
|
||||
|
||||
最后,函数使用`ChatMessagePromptTemplate.from_template`方法,将处理后的内容、"jinja2"字符串(表示使用的模板类型)和角色作为参数,创建并返回一个`ChatMessagePromptTemplate`对象。
|
||||
|
||||
在项目中,`to_msg_template`方法被多个异步迭代器函数调用,这些函数负责处理不同类型的聊天会话,如`chat_iterator`、`knowledge_base_chat_iterator`和`search_engine_chat_iterator`等。在这些函数中,`to_msg_template`方法用于将历史消息或用户输入转换为适合模型处理的格式,进而生成聊天提示或查询模板。
|
||||
|
||||
**注意**:
|
||||
- 当使用`to_msg_template`方法时,需要注意`is_raw`参数的使用场景。如果消息内容中包含需要保留的模板标签,则应将`is_raw`设置为True。
|
||||
- 该方法依赖于`ChatMessagePromptTemplate.from_template`方法,因此需要确保`ChatMessagePromptTemplate`类及其方法的正确实现。
|
||||
|
||||
**输出示例**:
|
||||
假设有一个`History`对象,其`role`为"human",`content`为"Hello, AI!",调用`to_msg_template(False)`可能会返回如下`ChatMessagePromptTemplate`对象:
|
||||
```python
|
||||
ChatMessagePromptTemplate(content="Hello, AI!", template_type="jinja2", role="user")
|
||||
```
|
||||
***
|
||||
### FunctionDef from_data(cls, h)
|
||||
**from_data**: 该函数用于根据提供的数据创建一个History对象。
|
||||
|
||||
**参数**:
|
||||
- `h`: 可以是列表、元组或字典类型,用于初始化History对象的数据。
|
||||
|
||||
**代码描述**:
|
||||
`from_data`函数是一个类方法,用于根据不同类型的输入数据创建一个History对象。该函数接受一个参数`h`,这个参数可以是列表、元组或字典类型。如果`h`是列表或元组,并且长度至少为2,那么会使用列表或元组的前两个元素作为History对象的`role`和`content`属性进行初始化。如果`h`是字典类型,那么会将字典中的键值对作为参数通过解包的方式传递给History类的构造函数,从而创建History对象。无论输入数据的类型如何,该函数最终都会返回一个History对象。
|
||||
|
||||
在项目中,`from_data`函数被多个地方调用,用于将用户的输入或历史对话数据转换为History对象,以便后续处理。例如,在`agent_chat`、`chat_iterator`、`file_chat`、`knowledge_base_chat`和`search_engine_chat`等函数中,都可以看到`from_data`函数的调用,它们通过这个函数将传入的历史对话列表转换为History对象列表,以便进行进一步的处理和分析。
|
||||
|
||||
**注意**:
|
||||
- 当输入参数`h`为列表或元组时,至少需要包含两个元素,分别代表角色和内容,否则无法正确创建History对象。
|
||||
- 当输入参数`h`为字典时,需要确保字典中包含的键与History类的构造函数参数相匹配,以便正确初始化对象。
|
||||
|
||||
**输出示例**:
|
||||
假设输入参数`h`为列表`["user", "今天天气怎么样?"]`,则函数返回的History对象将具有属性`role="user"`和`content="今天天气怎么样?"`。如果输入参数`h`为字典`{"role": "assistant", "content": "今天是晴天。"}`,则返回的History对象将具有相同的属性值。
|
||||
***
|
||||
21
markdown_docs/server/db/models/base.md
Normal file
@ -0,0 +1,21 @@
|
||||
## ClassDef BaseModel
|
||||
**BaseModel**: BaseModel 的功能是提供一个数据库模型的基础结构。
|
||||
|
||||
**属性**:
|
||||
- `id`: 主键ID,用于唯一标识每个记录。
|
||||
- `create_time`: 记录的创建时间。
|
||||
- `update_time`: 记录的最后更新时间。
|
||||
- `create_by`: 记录的创建者。
|
||||
- `update_by`: 记录的最后更新者。
|
||||
|
||||
**代码描述**:
|
||||
BaseModel 类定义了一个数据库模型的基础结构,它包含了几个常见且重要的字段。这些字段包括:
|
||||
- `id` 字段使用 `Column` 函数定义,其类型为 `Integer`,并且被设置为主键(`primary_key=True`),同时启用索引(`index=True`),以便提高查询效率。此外,该字段还有一个注释(`comment="主键ID"`),用于说明字段的用途。
|
||||
- `create_time` 字段记录了数据被创建的时间,其类型为 `DateTime`。该字段的默认值通过 `datetime.utcnow` 函数设置,以确保使用的是创建记录时的UTC时间。此字段同样有一个注释(`comment="创建时间"`)。
|
||||
- `update_time` 字段记录了数据最后一次被更新的时间,类型也是 `DateTime`。不同的是,它的默认值设置为 `None`,并且通过 `onupdate=datetime.utcnow` 参数设置,当记录更新时,此字段会自动更新为当前的UTC时间。该字段也有相应的注释(`comment="更新时间"`)。
|
||||
- `create_by` 和 `update_by` 字段用于记录数据的创建者和最后更新者的信息,它们的类型都是 `String`。默认值为 `None`,并且各自有对应的注释(`comment="创建者"` 和 `comment="更新者"`),用于说明字段的用途。
|
||||
|
||||
**注意**:
|
||||
- 使用BaseModel时,需要注意`create_time`和`update_time`字段默认使用的是UTC时间,这意味着如果应用程序在不同的时区运行,可能需要进行相应的时区转换。
|
||||
- `id`字段被设置为主键和索引,这对于数据库性能优化是非常重要的。确保每个模型都有一个唯一的标识符。
|
||||
- `create_by` 和 `update_by` 字段的默认值为 `None`,在实际应用中,根据业务需求,可能需要在数据创建或更新时,显式地设置这些字段的值。
|
||||
41
markdown_docs/server/db/models/conversation_model.md
Normal file
@ -0,0 +1,41 @@
|
||||
## ClassDef ConversationModel
|
||||
**ConversationModel**: ConversationModel类的功能是定义一个聊天记录模型,用于数据库中存储聊天会话的详细信息。
|
||||
|
||||
**属性**:
|
||||
- `id`: 对话框ID,是每个对话框的唯一标识符,使用String类型。
|
||||
- `name`: 对话框名称,存储对话框的名称,使用String类型。
|
||||
- `chat_type`: 聊天类型,标识聊天的类型(如普通聊天、客服聊天等),使用String类型。
|
||||
- `create_time`: 创建时间,记录对话框创建的时间,使用DateTime类型,默认值为当前时间。
|
||||
|
||||
**代码描述**:
|
||||
ConversationModel类继承自Base类,是一个ORM模型,用于映射数据库中的`conversation`表。该模型包含四个字段:`id`、`name`、`chat_type`和`create_time`,分别用于存储对话框的唯一标识符、名称、聊天类型和创建时间。其中,`id`字段被设置为主键。此外,该类还重写了`__repr__`方法,以便在打印实例时能够清晰地显示出实例的主要信息。
|
||||
|
||||
在项目中,ConversationModel类被用于创建和管理聊天记录的数据。例如,在`server/db/repository/conversation_repository.py`中的`add_conversation_to_db`函数中,通过创建ConversationModel的实例并将其添加到数据库会话中,实现了聊天记录的新增功能。这显示了ConversationModel类在项目中用于处理聊天记录数据的重要角色。
|
||||
|
||||
**注意**:
|
||||
- 在使用ConversationModel进行数据库操作时,需要确保传入的参数类型与字段定义相匹配,避免类型不匹配的错误。
|
||||
- 创建ConversationModel实例时,`id`字段可以不传入,由数据库自动生成唯一标识符,但在`add_conversation_to_db`函数中,如果没有提供`conversation_id`,则会使用`uuid.uuid4().hex`生成一个。
|
||||
|
||||
**输出示例**:
|
||||
假设创建了一个ConversationModel实例,其属性值如下:
|
||||
- id: "1234567890abcdef"
|
||||
- name: "客服对话"
|
||||
- chat_type: "agent_chat"
|
||||
- create_time: "2023-04-01 12:00:00"
|
||||
|
||||
则该实例的`__repr__`方法输出可能如下:
|
||||
```
|
||||
<Conversation(id='1234567890abcdef', name='客服对话', chat_type='agent_chat', create_time='2023-04-01 12:00:00')>
|
||||
```
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 该函数的功能是生成并返回一个代表会话对象的字符串。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `__repr__` 方法是一个特殊方法,用于定义一个对象的“官方”字符串表示。在这个场景中,`__repr__` 被定义在 `ConversationModel` 类中,目的是为了提供一个清晰且易于理解的会话对象表示。当调用此方法时,它会返回一个格式化的字符串,其中包含了会话对象的几个关键属性:`id`、`name`、`chat_type` 和 `create_time`。这些属性通过 `self` 关键字访问,表示它们属于当前的会话实例。字符串使用 f-string 格式化,这是 Python 3.6 及以上版本中引入的一种字符串格式化机制,允许将表达式的值直接嵌入到字符串常量中。
|
||||
|
||||
**注意**: 使用 `__repr__` 方法的一个重要原则是,其返回的字符串应尽可能地反映出对象的重要信息,且最好能够通过执行这个字符串(假设环境中有正确的上下文)来重新创建出该对象。虽然在许多实际情况下,直接执行 `__repr__` 返回的字符串来复制对象并不是必需的,但这一原则仍然是一个很好的指导思想。此外,当你在调试过程中打印对象或在交互式环境中查看对象时,`__repr__` 方法返回的字符串将会被显示,这有助于快速识别对象的状态。
|
||||
|
||||
**输出示例**: 假设有一个会话对象,其 `id` 为 "123",`name` 为 "Test Conversation",`chat_type` 为 "group",`create_time` 为 "2023-04-01",则调用 `__repr__` 方法将返回如下字符串:
|
||||
`"<Conversation(id='123', name='Test Conversation', chat_type='group', create_time='2023-04-01')>"`
|
||||
***
|
||||
54
markdown_docs/server/db/models/knowledge_base_model.md
Normal file
@ -0,0 +1,54 @@
|
||||
## ClassDef KnowledgeBaseModel
|
||||
**KnowledgeBaseModel**: KnowledgeBaseModel 类的功能是定义知识库的数据模型,用于在数据库中存储和管理知识库的相关信息。
|
||||
|
||||
**属性**:
|
||||
- `id`: 知识库ID,是每个知识库的唯一标识。
|
||||
- `kb_name`: 知识库名称,用于标识和检索特定的知识库。
|
||||
- `kb_info`: 知识库简介,提供关于知识库的基本信息,用于Agent。
|
||||
- `vs_type`: 向量库类型,指定知识库使用的向量库的类型。
|
||||
- `embed_model`: 嵌入模型名称,指定用于知识库的嵌入模型。
|
||||
- `file_count`: 文件数量,记录知识库中包含的文件数目。
|
||||
- `create_time`: 创建时间,记录知识库被创建的时间。
|
||||
|
||||
**代码描述**:
|
||||
KnowledgeBaseModel 类继承自 Base 类,是一个ORM模型,用于映射数据库中的 `knowledge_base` 表。该类定义了知识库的基本属性,包括知识库ID、名称、简介、向量库类型、嵌入模型名称、文件数量和创建时间。通过这些属性,可以在数据库中有效地存储和管理知识库的相关信息。
|
||||
|
||||
在项目中,KnowledgeBaseModel 类被多个函数调用,以实现对知识库的增删查改操作。例如,在 `add_kb_to_db` 函数中,使用KnowledgeBaseModel 来创建新的知识库实例或更新现有知识库的信息。在 `list_kbs_from_db` 函数中,通过查询KnowledgeBaseModel 来获取满足特定条件的知识库列表。此外,`kb_exists`、`load_kb_from_db`、`delete_kb_from_db` 和 `get_kb_detail` 等函数也都涉及到对KnowledgeBaseModel 类的操作,以实现检查知识库是否存在、加载知识库信息、删除知识库和获取知识库详细信息等功能。
|
||||
|
||||
**注意**:
|
||||
在使用KnowledgeBaseModel 类进行数据库操作时,需要注意确保传入的参数类型和值符合定义的属性类型和业务逻辑要求,以避免数据类型错误或逻辑错误。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中有一个知识库实例,其属性值如下:
|
||||
```
|
||||
<KnowledgeBase(id='1', kb_name='技术文档库', kb_intro='存储技术相关文档', vs_type='ElasticSearch', embed_model='BERT', file_count='100', create_time='2023-04-01 12:00:00')>
|
||||
```
|
||||
这表示有一个ID为1的知识库,名称为“技术文档库”,简介为“存储技术相关文档”,使用的向量库类型为ElasticSearch,嵌入模型为BERT,包含100个文件,创建时间为2023年4月1日12点。
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: __repr__函数的功能是提供KnowledgeBaseModel对象的官方字符串表示。
|
||||
|
||||
**参数**: 此函数没有接受额外参数,它仅使用self来访问对象的属性。
|
||||
|
||||
**代码描述**:
|
||||
`__repr__`方法定义在KnowledgeBaseModel类中,用于生成该对象的官方字符串表示。这个字符串表示包含了对象的关键信息,使得开发者和调试者能够更容易地识别对象。具体来说,它返回一个格式化的字符串,其中包含了KnowledgeBaseModel对象的多个属性值,包括:
|
||||
- `id`:对象的唯一标识符。
|
||||
- `kb_name`:知识库的名称。
|
||||
- `kb_info`:知识库的简介。
|
||||
- `vs_type`:知识库的版本类型。
|
||||
- `embed_model`:嵌入模型的名称。
|
||||
- `file_count`:知识库中文件的数量。
|
||||
- `create_time`:知识库创建的时间。
|
||||
|
||||
这个方法通过f-string格式化字符串的方式,将对象属性嵌入到预定义的字符串模板中,从而生成易于阅读和理解的表示形式。
|
||||
|
||||
**注意**:
|
||||
- `__repr__`方法通常用于调试和日志记录,它应该返回一个明确且无歧义的对象表示。
|
||||
- 在Python中,当你尝试将对象转换为字符串时(例如使用`str()`函数或在打印时),如果没有定义`__str__`方法,Python会回退到使用`__repr__`方法。
|
||||
- 保证`__repr__`方法返回的字符串包含足够的信息,可以用来识别对象中的关键信息。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
<KnowledgeBase(id='1', kb_name='MyKnowledgeBase',kb_intro='This is a test knowledge base vs_type='v1.0', embed_model='BERT', file_count='100', create_time='2023-04-01')>
|
||||
```
|
||||
此示例展示了一个KnowledgeBaseModel对象的`__repr__`方法返回值的可能形式,其中包含了对象的id, kb_name, kb_intro, vs_type, embed_model, file_count, 和 create_time属性的值。
|
||||
***
|
||||
97
markdown_docs/server/db/models/knowledge_file_model.md
Normal file
@ -0,0 +1,97 @@
|
||||
## ClassDef KnowledgeFileModel
|
||||
**KnowledgeFileModel**: KnowledgeFileModel类用于表示知识库中的文件信息。
|
||||
|
||||
**属性**:
|
||||
- `id`: 知识文件的唯一标识ID。
|
||||
- `file_name`: 文件名。
|
||||
- `file_ext`: 文件扩展名。
|
||||
- `kb_name`: 所属知识库的名称。
|
||||
- `document_loader_name`: 文档加载器的名称。
|
||||
- `text_splitter_name`: 文本分割器的名称。
|
||||
- `file_version`: 文件版本。
|
||||
- `file_mtime`: 文件的最后修改时间。
|
||||
- `file_size`: 文件大小。
|
||||
- `custom_docs`: 标识是否为自定义文档。
|
||||
- `docs_count`: 切分文档的数量。
|
||||
- `create_time`: 文件的创建时间。
|
||||
|
||||
**代码描述**:
|
||||
KnowledgeFileModel类继承自Base类,是一个ORM模型,用于映射数据库中的`knowledge_file`表。该模型定义了与知识文件相关的各种属性,包括文件名、文件扩展名、所属知识库名称、文档加载器名称、文本分割器名称等。此外,还包括文件的版本、修改时间、大小、是否自定义文档、切分文档数量以及创建时间等信息。
|
||||
|
||||
在项目中,KnowledgeFileModel类被多个函数调用,主要涉及到知识文件的增删查改操作。例如,`count_files_from_db`函数用于统计某个知识库中的文件数量,`list_files_from_db`函数用于列出某个知识库中的所有文件名,`add_file_to_db`函数用于向数据库中添加新的知识文件或更新现有文件的信息,`delete_file_from_db`和`delete_files_from_db`函数用于从数据库中删除指定的文件或某个知识库中的所有文件,`file_exists_in_db`函数用于检查某个文件是否已存在于数据库中,`get_file_detail`函数用于获取某个文件的详细信息。
|
||||
|
||||
**注意**:
|
||||
- 在使用KnowledgeFileModel进行数据库操作时,需要确保传入的参数符合字段定义的类型和约束。
|
||||
- 对于文件版本、修改时间和大小等信息,在更新文件信息时应注意正确维护这些字段的值,以保证数据的准确性和一致性。
|
||||
|
||||
**输出示例**:
|
||||
由于KnowledgeFileModel是一个ORM模型,直接操作该类的实例不会产生简单的输出结果。但是,当使用`__repr__`方法打印KnowledgeFileModel的实例时,可能会得到如下格式的字符串表示:
|
||||
```
|
||||
<KnowledgeFile(id='1', file_name='example.pdf', file_ext='.pdf', kb_name='DefaultKB', document_loader_name='PDFLoader', text_splitter_name='SpacyTextSplitter', file_version='1', create_time='2023-04-01 12:00:00')>
|
||||
```
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是生成KnowledgeFileModel对象的官方字符串表示。
|
||||
|
||||
**参数**: 此函数不接受除self之外的任何参数。
|
||||
|
||||
**代码描述**: `__repr__`方法是Python中的一个特殊方法,用于定义对象的“官方”字符串表示。在这个上下文中,`__repr__`方法被用于KnowledgeFileModel类,这是一个数据库模型类,代表知识文件。当调用此方法时,它会返回一个格式化的字符串,其中包含了KnowledgeFileModel对象的关键信息,包括:id、file_name(文件名)、file_ext(文件扩展名)、kb_name(知识库名称)、document_loader_name(文档加载器名称)、text_splitter_name(文本分割器名称)、file_version(文件版本)和create_time(创建时间)。这种字符串表示形式非常有用,尤其是在调试和日志记录中,因为它提供了对象的快速概览。
|
||||
|
||||
**注意**: `__repr__`方法返回的字符串应该尽可能地反映对象的状态,同时保持简洁明了。在实际应用中,开发者可能会根据需要调整包含在`__repr__`返回值中的属性。此外,虽然`__repr__`的主要目的是为了调试和开发,但它也可以被用于用户界面显示,尤其是在需要快速展示对象信息的场景中。
|
||||
|
||||
**输出示例**: 假设有一个KnowledgeFileModel对象,其属性值如下:
|
||||
- id: 1
|
||||
- file_name: "example.pdf"
|
||||
- file_ext: ".pdf"
|
||||
- kb_name: "General Knowledge"
|
||||
- document_loader_name: "DefaultLoader"
|
||||
- text_splitter_name: "SimpleSplitter"
|
||||
- file_version: "v1.0"
|
||||
- create_time: "2023-04-01 12:00:00"
|
||||
|
||||
调用此对象的`__repr__`方法将返回以下字符串:
|
||||
`"<KnowledgeFile(id='1', file_name='example.pdf', file_ext='.pdf', kb_name='General Knowledge', document_loader_name='DefaultLoader', text_splitter_name='SimpleSplitter', file_version='v1.0', create_time='2023-04-01 12:00:00')>"`
|
||||
***
|
||||
## ClassDef FileDocModel
|
||||
**FileDocModel**: FileDocModel类用于表示文件与向量库文档之间的关系模型。
|
||||
|
||||
**属性**:
|
||||
- `id`: 唯一标识符,自增长的整数,用于唯一标识每个文档。
|
||||
- `kb_name`: 知识库名称,字符串类型,表示该文档所属的知识库。
|
||||
- `file_name`: 文件名称,字符串类型,表示该文档对应的原始文件名。
|
||||
- `doc_id`: 向量库文档ID,字符串类型,用于标识向量库中的文档。
|
||||
- `meta_data`: 元数据,JSON类型,默认为空字典,用于存储文档的额外信息。
|
||||
|
||||
**代码描述**:
|
||||
FileDocModel类继承自Base类,是一个ORM模型,用于映射数据库中的`file_doc`表。该模型定义了与文件和向量库文档相关的基本信息字段,包括知识库名称、文件名称、文档ID以及元数据。此外,通过定义`__repr__`方法,可以提供该模型实例的友好字符串表示,便于调试和日志记录。
|
||||
|
||||
在项目中,FileDocModel类被多个函数调用,主要用于处理与数据库中文档相关的操作,如添加、查询、删除文档信息。例如,在`add_docs_to_db`函数中,通过创建FileDocModel的实例并添加到数据库会话中,实现了将文档信息添加到数据库的功能。在`list_file_num_docs_id_by_kb_name_and_file_name`函数中,通过查询FileDocModel实例,实现了根据知识库名称和文件名称列出所有对应文档ID的功能。此外,`delete_docs_from_db`和`list_docs_from_db`等函数也展示了如何利用FileDocModel进行文档的查询和删除操作。
|
||||
|
||||
**注意**:
|
||||
- 在使用FileDocModel进行数据库操作时,需要确保传入的参数类型和字段约束条件符合定义,以避免数据类型错误或约束违反的问题。
|
||||
- 在处理元数据(meta_data)字段时,考虑到其为JSON类型,应当注意正确的数据格式和解析方法,以保证元数据的有效存储和查询。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中有一条记录,其字段值如下:
|
||||
- id: 1
|
||||
- kb_name: "知识库1"
|
||||
- file_name: "文件1.pdf"
|
||||
- doc_id: "doc123"
|
||||
- meta_data: {"author": "张三", "year": "2021"}
|
||||
|
||||
则该记录的`__repr__`方法输出可能为:
|
||||
`<FileDoc(id='1', kb_name='知识库1', file_name='文件1.pdf', doc_id='doc123', metadata='{'author': '张三', 'year': '2021'}')>`
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是生成对象的官方字符串表示。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `__repr__` 方法是 Python 中的一个特殊方法,用于定义对象的“官方”字符串表示。在这个特定的实现中,`__repr__` 方法被用于 `FileDocModel` 类,该类可能代表一个与知识库文件相关的模型。此方法返回一个格式化的字符串,其中包含了对象的几个关键属性:`id`、`kb_name`(知识库名称)、`file_name`(文件名)、`doc_id`(文档ID)以及`metadata`(元数据)。这种格式化的字符串表示使得开发者能够快速识别对象的主要属性,特别是在调试过程中或者将对象输出到控制台时非常有用。
|
||||
|
||||
**注意**: 使用 `__repr__` 方法时,应确保返回的字符串能够准确反映对象的关键信息。此外,虽然此方法主要用于调试和开发,但也应注意保持返回字符串的可读性。
|
||||
|
||||
**输出示例**: 假设有一个 `FileDocModel` 对象,其属性如下:`id=1`,`kb_name='KnowledgeBase1'`,`file_name='document1.pdf'`,`doc_id='12345'`,`metadata='{"author": "John Doe", "date": "2023-04-01"}'`。调用此对象的 `__repr__` 方法将返回以下字符串:
|
||||
|
||||
```
|
||||
<FileDoc(id='1', kb_name='KnowledgeBase1', file_name='document1.pdf', doc_id='12345', metadata='{"author": "John Doe", "date": "2023-04-01"}')>
|
||||
```
|
||||
***
|
||||
41
markdown_docs/server/db/models/knowledge_metadata_model.md
Normal file
@ -0,0 +1,41 @@
|
||||
## ClassDef SummaryChunkModel
|
||||
**SummaryChunkModel**: SummaryChunkModel 类的功能是用于存储和管理文档中每个文档标识符(doc_id)的摘要信息。
|
||||
|
||||
**属性**:
|
||||
- `id`: 唯一标识符,用于标识每个摘要信息的ID。
|
||||
- `kb_name`: 知识库名称,表示该摘要信息属于哪个知识库。
|
||||
- `summary_context`: 总结文本,存储自动生成或用户输入的文档摘要。
|
||||
- `summary_id`: 总结矢量id,用于后续的矢量库构建和语义关联。
|
||||
- `doc_ids`: 向量库id关联列表,存储与该摘要相关的文档标识符列表。
|
||||
- `meta_data`: 元数据,以JSON格式存储额外的信息,如页码信息等。
|
||||
|
||||
**代码描述**:
|
||||
SummaryChunkModel 类定义了一个用于存储文档摘要信息的数据模型。该模型包括了文档的基本信息如知识库名称、摘要文本、摘要矢量ID、相关文档ID列表以及额外的元数据。这些信息主要来源于用户上传文件时的描述或程序自动切分文档生成的摘要。此外,该模型还支持后续的矢量库构建和语义关联任务,通过对summary_context创建索引和计算语义相似度来实现。
|
||||
|
||||
在项目中,SummaryChunkModel 被 knowledge_metadata_repository.py 文件中的多个函数调用,包括添加、删除、列出和统计知识库中的摘要信息。这些函数通过操作 SummaryChunkModel 实例来实现对数据库中摘要信息的管理,如添加新的摘要信息、删除特定知识库的摘要信息、根据知识库名称列出摘要信息以及统计特定知识库的摘要数量。
|
||||
|
||||
**注意**:
|
||||
- 在使用 SummaryChunkModel 进行数据库操作时,需要确保传入的参数类型和格式正确,特别是 `meta_data` 字段,它应以正确的JSON格式存储。
|
||||
- 在进行矢量库构建和语义关联任务时,应注意 `summary_id` 和 `doc_ids` 字段的正确使用和关联。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中有一个摘要信息实例,其可能的表示如下:
|
||||
```
|
||||
<SummaryChunk(id='1', kb_name='技术文档', summary_context='这是一个关于AI技术的摘要', doc_ids='["doc1", "doc2"]', metadata='{}')>
|
||||
```
|
||||
这表示一个ID为1的摘要信息,属于“技术文档”知识库,摘要文本为“这是一个关于AI技术的摘要”,关联的文档标识符为doc1和doc2,没有额外的元数据信息。
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是生成并返回一个代表对象状态的字符串。
|
||||
|
||||
**参数**: 此函数不接受除`self`之外的任何参数。
|
||||
|
||||
**代码描述**: `__repr__`函数是`SummaryChunkModel`类的一个特殊方法,用于创建一个代表该对象实例状态的字符串。这个字符串包含了`SummaryChunkModel`实例的几个关键属性:`id`、`kb_name`、`summary_context`、`doc_ids`以及`metadata`。这些属性通过访问实例的相应属性并将它们格式化为一个特定格式的字符串来展示。这个字符串格式遵循`<SummaryChunk(id='...', kb_name='...', summary_context='...', doc_ids='...', metadata='...')>`的形式,其中每个`...`会被实例相应属性的实际值替换。这种表示方式便于开发者在调试过程中快速识别对象的状态。
|
||||
|
||||
**注意**: `__repr__`方法通常用于调试和日志记录,它应该返回一个明确且易于理解的对象状态描述。返回的字符串应该尽可能地反映出对象的关键属性。此外,虽然`__repr__`的主要目的不是被终端用户直接看到,但它的设计应确保在需要时能够提供足够的信息来识别对象的具体状态。
|
||||
|
||||
**输出示例**: 假设有一个`SummaryChunkModel`实例,其`id`为`123`,`kb_name`为`"KnowledgeBase1"`,`summary_context`为`"Context1"`,`doc_ids`为`"doc1, doc2"`,`metadata`为`"{'author': 'John Doe'}"`。调用此实例的`__repr__`方法将返回以下字符串:
|
||||
|
||||
```
|
||||
<SummaryChunk(id='123', kb_name='KnowledgeBase1', summary_context='Context1', doc_ids='doc1, doc2', metadata='{'author': 'John Doe'}')>
|
||||
```
|
||||
***
|
||||
44
markdown_docs/server/db/models/message_model.md
Normal file
@ -0,0 +1,44 @@
|
||||
## ClassDef MessageModel
|
||||
**MessageModel**: MessageModel类的功能是定义聊天记录的数据模型。
|
||||
|
||||
**属性**:
|
||||
- `id`: 聊天记录的唯一标识ID。
|
||||
- `conversation_id`: 对话框ID,用于标识一次会话。
|
||||
- `chat_type`: 聊天类型,如普通聊天、客服聊天等。
|
||||
- `query`: 用户的提问或输入。
|
||||
- `response`: 系统或模型的回答。
|
||||
- `meta_data`: 存储额外信息的JSON字段,如知识库ID等,便于后续扩展。
|
||||
- `feedback_score`: 用户对聊天回答的评分,满分为100。
|
||||
- `feedback_reason`: 用户评分的理由。
|
||||
- `create_time`: 记录的创建时间。
|
||||
|
||||
**代码描述**:
|
||||
MessageModel类继承自Base,用于定义聊天记录的数据结构。它包含了聊天记录的基本信息,如聊天ID、会话ID、聊天类型、用户问题、模型回答、元数据、用户反馈等。此类通过定义SQLAlchemy的Column字段来映射数据库中的`message`表结构。其中,`__tablename__`属性指定了数据库中对应的表名为`message`。每个属性都通过Column实例来定义,其中包括数据类型、是否为主键、默认值、索引创建、注释等信息。
|
||||
|
||||
在项目中,MessageModel类被用于server/db/repository/message_repository.py文件中的几个函数调用中,主要涉及到聊天记录的增加、查询和反馈。例如,`add_message_to_db`函数用于新增聊天记录,它创建了一个MessageModel实例并将其添加到数据库中。`get_message_by_id`函数通过聊天记录ID查询聊天记录。`feedback_message_to_db`函数用于更新聊天记录的用户反馈信息。`filter_message`函数则是根据对话框ID过滤聊天记录,并返回最近的几条记录。
|
||||
|
||||
**注意**:
|
||||
- 在使用MessageModel进行数据库操作时,需要确保传入的参数类型与定义的字段类型相匹配。
|
||||
- 对于`meta_data`字段,虽然默认值为一个空字典,但在实际使用中可以根据需要存储任意结构的JSON数据。
|
||||
- 在进行数据库操作如添加、查询、更新记录时,应确保操作在正确的数据库会话(session)上下文中执行。
|
||||
|
||||
**输出示例**:
|
||||
由于MessageModel是一个数据模型类,它本身不直接产生输出。但是,当它被实例化并用于数据库操作时,例如通过`add_message_to_db`函数添加一条新的聊天记录,可能会返回如下的聊天记录ID:
|
||||
```
|
||||
'1234567890abcdef1234567890abcdef'
|
||||
```
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是生成并返回一个代表消息对象的字符串。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `__repr__` 方法是一个特殊方法,用于定义对象的“官方”字符串表示。在这个具体的实现中,它返回一个格式化的字符串,该字符串包含了消息对象的多个属性,包括:`id`, `conversation_id`, `chat_type`, `query`, `response`, `meta_data`, `feedback_score`, `feedback_reason`, 以及 `create_time`。这些属性通过使用 `self` 关键字访问,表示它们是对象的实例变量。字符串使用了 f-string 格式化,这是 Python 3.6 及以上版本中引入的一种字符串格式化机制,允许将表达式的值直接嵌入到字符串常量中。
|
||||
|
||||
**注意**: `__repr__` 方法的返回值应该尽可能地返回一个明确的对象表示,以便于调试和日志记录。返回的字符串应该尽量遵循 Python 对象表示的惯例,即 `<type(name=value, ...)>` 的格式。此外,虽然这个方法主要用于调试和开发,但它也可以被用于日志记录或其他需要对象字符串表示的场景。
|
||||
|
||||
**输出示例**: 假设有一个消息对象,其属性值如下:`id=1`, `conversation_id=2`, `chat_type='group'`, `query='天气如何'`, `response='晴朗'`, `meta_data='{}'`, `feedback_score=5`, `feedback_reason='准确'`, `create_time='2023-04-01 12:00:00'`。调用此对象的 `__repr__` 方法将返回以下字符串:
|
||||
|
||||
```
|
||||
<message(id='1', conversation_id='2', chat_type='group', query='天气如何', response='晴朗',meta_data='{}',feedback_score='5',feedback_reason='准确', create_time='2023-04-01 12:00:00')>
|
||||
```
|
||||
***
|
||||
@ -0,0 +1,25 @@
|
||||
## FunctionDef add_conversation_to_db(session, chat_type, name, conversation_id)
|
||||
**add_conversation_to_db**: 此函数的功能是向数据库中新增一条聊天记录。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `chat_type`: 字符串,表示聊天的类型(例如普通聊天、客服聊天等)。
|
||||
- `name`: 字符串,聊天记录的名称,默认为空字符串。
|
||||
- `conversation_id`: 字符串,聊天记录的唯一标识符,默认为None,若未提供,则会自动生成。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先检查是否提供了`conversation_id`参数。如果没有提供,函数将使用`uuid.uuid4().hex`生成一个唯一的标识符。接着,函数创建一个`ConversationModel`实例,其中包含了聊天记录的ID、聊天类型、名称等信息。然后,通过`session.add(c)`将此实例添加到数据库会话中,准备将其保存到数据库。最后,函数返回新创建的聊天记录的ID。
|
||||
|
||||
此函数与`ConversationModel`类紧密相关,`ConversationModel`类定义了聊天记录的数据模型,包括聊天记录的ID、名称、聊天类型和创建时间等字段。`add_conversation_to_db`函数通过创建`ConversationModel`的实例并将其添加到数据库中,实现了聊天记录的新增功能。这体现了`ConversationModel`在项目中用于处理聊天记录数据的重要作用。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,需要确保`session`参数是一个有效的数据库会话实例,以便能够正确执行数据库操作。
|
||||
- `chat_type`参数是必需的,因为它定义了聊天记录的类型,这对于后续的数据处理和查询是非常重要的。
|
||||
- 如果在调用函数时没有提供`conversation_id`,则会自动生成一个。这意味着每条聊天记录都将拥有一个唯一的标识符,即使在未显式指定ID的情况下也是如此。
|
||||
|
||||
**输出示例**:
|
||||
假设调用`add_conversation_to_db`函数,并传入相应的参数,函数可能会返回如下的聊天记录ID:
|
||||
```
|
||||
"e4eaaaf2-d142-11e1-b3e4-080027620cdd"
|
||||
```
|
||||
这个返回值表示新创建的聊天记录的唯一标识符。
|
||||
130
markdown_docs/server/db/repository/knowledge_base_repository.md
Normal file
@ -0,0 +1,130 @@
|
||||
## FunctionDef add_kb_to_db(session, kb_name, kb_info, vs_type, embed_model)
|
||||
**add_kb_to_db**: 此函数的功能是向数据库中添加或更新知识库信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_name`: 知识库的名称,用作知识库的唯一标识。
|
||||
- `kb_info`: 知识库的简介信息,提供关于知识库的基本描述。
|
||||
- `vs_type`: 向量库类型,指定知识库使用的向量库的类型。
|
||||
- `embed_model`: 嵌入模型名称,指定用于知识库的嵌入模型。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先尝试查询数据库中是否存在与给定知识库名称相匹配的知识库实例。如果不存在,函数将创建一个新的`KnowledgeBaseModel`实例,并使用提供的参数填充其属性,然后将此新实例添加到数据库中。如果已存在具有相同名称的知识库,函数将更新该知识库的简介(`kb_info`)、向量库类型(`vs_type`)和嵌入模型(`embed_model`)信息。无论是添加新知识库还是更新现有知识库,此函数最终都会返回`True`,表示操作成功。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`是一个有效的数据库会话实例,以允许函数执行数据库操作。
|
||||
- 在调用此函数之前,应确保`kb_name`是唯一的,以避免不必要的知识库信息覆盖。
|
||||
- 此函数不负责提交数据库会话,调用者需要在调用此函数后,根据自己的需求决定是否提交会话。
|
||||
|
||||
**输出示例**:
|
||||
由于此函数的返回值是布尔类型,因此在成功执行添加或更新操作后,它将返回`True`。例如,无论是创建了一个新的知识库还是更新了现有的知识库信息,函数调用`add_kb_to_db(session, '技术文档库', '存储技术相关文档', 'ElasticSearch', 'BERT')`都将返回`True`。
|
||||
## FunctionDef list_kbs_from_db(session, min_file_count)
|
||||
**list_kbs_from_db**: 此函数的功能是从数据库中列出满足特定条件的知识库名称列表。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话对象,用于执行数据库查询。
|
||||
- `min_file_count`: 文件数量的最小值,默认为-1,表示不对文件数量做限制。
|
||||
|
||||
**代码描述**:
|
||||
`list_kbs_from_db` 函数通过传入的数据库会话对象 `session` 来查询 `KnowledgeBaseModel` 中的知识库名称。它使用了过滤条件,只有当知识库中的文件数量大于 `min_file_count` 参数指定的值时,该知识库才会被包含在结果列表中。查询结果首先是一个包含多个元组的列表,每个元组中的第一个元素是知识库名称。然后,通过列表推导式,将这些元组转换为仅包含知识库名称的列表。最终,函数返回这个知识库名称列表。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保传入的 `session` 对象是有效的数据库会话对象,并且已经正确配置了数据库连接。
|
||||
- `min_file_count` 参数允许调用者根据文件数量过滤知识库,可以根据实际需求调整其值。如果不需要基于文件数量过滤知识库,可以保留其默认值。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中有三个知识库,文件数量分别为0、10、20,且 `min_file_count` 参数的值为5,那么函数的返回值可能如下:
|
||||
```
|
||||
['知识库B', '知识库C']
|
||||
```
|
||||
这表示只有文件数量大于5的知识库B和知识库C被包含在了结果列表中。
|
||||
## FunctionDef kb_exists(session, kb_name)
|
||||
**kb_exists**: 此函数的功能是检查数据库中是否存在指定名称的知识库。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话对象,用于执行数据库查询。
|
||||
- `kb_name`: 要检查的知识库名称。
|
||||
|
||||
**代码描述**:
|
||||
`kb_exists` 函数通过接收一个数据库会话对象和一个知识库名称作为参数,来检查数据库中是否存在具有该名称的知识库。函数内部首先使用传入的会话对象执行一个查询,该查询利用`KnowledgeBaseModel`模型对数据库中的`knowledge_base`表进行过滤,查找名称与`kb_name`参数相匹配的知识库记录。这里使用`ilike`方法进行不区分大小写的匹配,以提高查询的灵活性。如果查询结果中存在至少一个匹配的记录,则函数返回`True`,表示指定名称的知识库存在;如果没有找到匹配的记录,则返回`False`,表示知识库不存在。
|
||||
|
||||
**注意**:
|
||||
- 在使用`kb_exists`函数时,需要确保传入的`session`对象是有效的数据库会话对象,并且已正确配置数据库连接。
|
||||
- 传入的`kb_name`应为字符串类型,且在调用此函数前,最好进行必要的格式化或验证,以确保查询的准确性。
|
||||
- 此函数的返回值是布尔类型,可以直接用于条件判断。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在一个名为"技术文档库"的知识库,调用`kb_exists(session, "技术文档库")`将返回`True`。如果查询一个不存在的知识库名称,如`kb_exists(session, "不存在的库")`,则会返回`False`。
|
||||
|
||||
此函数在项目中的应用场景包括,但不限于,在添加新的知识库之前检查同名知识库是否已存在,或在执行知识库相关操作前验证知识库的存在性,以确保数据的一致性和操作的有效性。
|
||||
## FunctionDef load_kb_from_db(session, kb_name)
|
||||
**load_kb_from_db**: 此函数的功能是从数据库中加载指定名称的知识库信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 要加载的知识库的名称。
|
||||
|
||||
**代码描述**: `load_kb_from_db` 函数通过接收一个数据库会话和一个知识库名称作为参数,利用这个会话来查询 `KnowledgeBaseModel` 表中名称与给定名称相匹配的第一个知识库记录。查询时忽略名称的大小写。如果找到相应的知识库记录,函数将从该记录中提取知识库的名称(`kb_name`)、向量库类型(`vs_type`)和嵌入模型名称(`embed_model`)。如果没有找到相应的记录,这三个变量将被设置为 `None`。最后,函数返回这三个值。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的 `session` 是有效的数据库会话实例,并且已经正确配置。
|
||||
- 传入的知识库名称 `kb_name` 应当是一个字符串,且在数据库中有对应的记录,否则函数将返回 `None` 值。
|
||||
- 此函数对知识库名称大小写不敏感,即不区分大小写。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在一个名为 "技术文档库" 的知识库,其向量库类型为 "ElasticSearch",嵌入模型名称为 "BERT",那么调用 `load_kb_from_db(session, "技术文档库")` 将返回:
|
||||
```
|
||||
("技术文档库", "ElasticSearch", "BERT")
|
||||
```
|
||||
如果数据库中不存在指定名称的知识库,调用 `load_kb_from_db(session, "不存在的库")` 将返回:
|
||||
```
|
||||
(None, None, None)
|
||||
```
|
||||
## FunctionDef delete_kb_from_db(session, kb_name)
|
||||
**delete_kb_from_db**: 此函数的功能是从数据库中删除指定的知识库。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_name`: 要删除的知识库的名称。
|
||||
|
||||
**代码描述**:
|
||||
`delete_kb_from_db` 函数首先通过传入的 `session` 参数和知识库名称 `kb_name`,使用 `query` 方法查询 `KnowledgeBaseModel` 表中是否存在指定名称的知识库。查询时,使用了 `ilike` 方法来实现不区分大小写的匹配,以提高用户体验和容错性。如果查询到了目标知识库,那么使用 `session.delete` 方法将其从数据库中删除。无论是否找到并删除了知识库,函数最终都会返回 `True`,表示操作已完成。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,需要确保传入的 `session` 是一个有效的数据库会话实例,且已正确配置数据库连接。
|
||||
- 传入的知识库名称 `kb_name` 应当是一个字符串类型,且在数据库中唯一标识一个知识库。
|
||||
- 函数执行后并不会自动提交数据库事务,调用方需要根据实际情况决定是否提交事务。
|
||||
|
||||
**输出示例**:
|
||||
由于此函数的返回值是固定的 `True`,因此不提供具体的输出示例。调用此函数后,可以根据返回值确认操作已被执行,但需要通过其他方式(如查询数据库)来验证知识库是否真的被成功删除。
|
||||
|
||||
此函数在项目中的应用场景包括,但不限于,在知识库管理服务中,当用户或管理员请求删除一个知识库时,会通过调用此函数来执行删除操作。例如,在 `KBService` 类的 `drop_kb` 方法中,就通过调用 `delete_kb_from_db` 函数来实现知识库的删除功能。这样的设计使得知识库的删除操作既可以独立使用,也可以轻松集成到更复杂的服务流程中。
|
||||
## FunctionDef get_kb_detail(session, kb_name)
|
||||
**get_kb_detail**: 此函数的功能是获取指定知识库的详细信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定要查询的知识库名称。
|
||||
|
||||
**代码描述**:
|
||||
`get_kb_detail` 函数通过接收一个数据库会话实例和一个知识库名称作为参数,利用这个会话实例查询 `KnowledgeBaseModel` 表中名称与给定知识库名称相匹配的记录。查询时忽略大小写,以提高查询的灵活性。如果找到匹配的知识库记录,则函数将返回一个包含知识库名称 (`kb_name`)、知识库简介 (`kb_info`)、向量库类型 (`vs_type`)、嵌入模型名称 (`embed_model`)、文件数量 (`file_count`) 和创建时间 (`create_time`) 的字典。如果没有找到匹配的记录,则返回一个空字典。
|
||||
|
||||
此函数在项目中被多个位置调用,包括但不限于加载知识库嵌入向量和获取知识库详情列表。这些调用场景表明 `get_kb_detail` 函数是连接数据库知识库信息与项目其他部分的重要桥梁。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `session` 参数是一个有效的数据库会话实例,且在调用此函数前已正确配置和连接到数据库。
|
||||
- 传入的 `kb_name` 应为字符串类型,且尽量确保其准确性,以便能够正确匹配数据库中的记录。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在一个名为 "技术文档库" 的知识库,其详细信息如下所示:
|
||||
```python
|
||||
{
|
||||
"kb_name": "技术文档库",
|
||||
"kb_info": "存储技术相关文档的知识库",
|
||||
"vs_type": "ElasticSearch",
|
||||
"embed_model": "BERT",
|
||||
"file_count": 100,
|
||||
"create_time": "2023-04-01T12:00:00"
|
||||
}
|
||||
```
|
||||
如果查询的知识库名称为 "技术文档库",则 `get_kb_detail` 函数将返回上述字典。如果没有找到匹配的知识库,则函数返回 `{}`。
|
||||
251
markdown_docs/server/db/repository/knowledge_file_repository.md
Normal file
@ -0,0 +1,251 @@
|
||||
## FunctionDef list_file_num_docs_id_by_kb_name_and_file_name(session, kb_name, file_name)
|
||||
**list_file_num_docs_id_by_kb_name_and_file_name**: 此函数的功能是列出某知识库中某文件对应的所有文档ID。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定知识库的名称。
|
||||
- `file_name`: 字符串类型,指定文件的名称。
|
||||
|
||||
**代码描述**:
|
||||
`list_file_num_docs_id_by_kb_name_and_file_name`函数通过接收数据库会话、知识库名称以及文件名称作为参数,利用这些参数对数据库中的`FileDocModel`表进行查询。查询的目的是找出所有与给定知识库名称和文件名称相匹配的文档ID。这些文档ID随后被转换为整数列表返回。此过程涉及到对`FileDocModel`模型的`doc_id`字段进行筛选,确保只有符合条件的记录被选中。最终,函数返回一个整数列表,包含了所有匹配文档的ID。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`是一个有效的数据库会话实例,且已正确配置以连接到目标数据库。
|
||||
- `kb_name`和`file_name`参数应准确无误,以匹配数据库中的记录。大小写敏感性取决于数据库配置。
|
||||
- 返回的文档ID列表是基于数据库中实际存在的记录,如果没有找到匹配的记录,则返回空列表。
|
||||
|
||||
**输出示例**:
|
||||
假设存在两个文档,它们的ID分别为1和2,且这两个文档都属于知识库"知识库A"中的"文件B.pdf",那么调用此函数并传入相应的知识库名称和文件名称后,将返回列表`[1, 2]`。
|
||||
|
||||
通过此函数,可以方便地根据知识库名称和文件名称获取相关文档的ID,进而支持进行进一步的文档管理或操作,如在`MilvusKBService`的`do_delete_doc`方法中,使用此函数获取到的文档ID列表用于指定删除向量库中相应的文档记录。
|
||||
## FunctionDef list_docs_from_db(session, kb_name, file_name, metadata)
|
||||
**list_docs_from_db**: 此函数的功能是列出某知识库某文件对应的所有文档。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定要查询的知识库名称。
|
||||
- `file_name`: 字符串类型,可选参数,默认为None,指定要查询的文件名称。
|
||||
- `metadata`: 字典类型,可选参数,默认为空字典,用于根据文档的元数据进行过滤查询。
|
||||
|
||||
**代码描述**:
|
||||
该函数首先根据知识库名称`kb_name`对`FileDocModel`进行查询,如果提供了`file_name`参数,则进一步根据文件名称进行过滤。随后,遍历`metadata`字典中的每一项,根据元数据的键和值对查询结果进行过滤。最终,函数返回一个列表,列表中的每个元素都是一个字典,包含文档的ID(`id`)和元数据(`metadata`)。
|
||||
|
||||
在实现上,`list_docs_from_db`函数通过ORM模型`FileDocModel`与数据库交互,利用SQLAlchemy的查询接口进行数据检索。`FileDocModel.kb_name.ilike(kb_name)`和`FileDocModel.file_name.ilike(file_name)`使用了`ilike`方法进行不区分大小写的模糊匹配,增强了查询的灵活性。对于元数据的查询,通过`FileDocModel.meta_data[k].as_string() == str(v)`实现了对JSON类型字段的条件过滤。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,应确保传入的`session`是一个有效的数据库会话实例。
|
||||
- 由于`metadata`参数默认为一个空字典,修改此默认值可能会影响到函数的预期行为。建议在调用函数时显式传入所需的`metadata`参数,避免直接修改函数定义中的默认值。
|
||||
- 在处理大量数据时,应考虑查询性能和优化,避免执行过多的过滤操作导致查询速度缓慢。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在两条记录,其字段值分别为:
|
||||
- id: 1, kb_name: "知识库A", file_name: "文件A.pdf", doc_id: "docA", metadata: {"author": "张三", "year": "2021"}
|
||||
- id: 2, kb_name: "知识库A", file_name: "文件B.pdf", doc_id: "docB", metadata: {"author": "李四", "year": "2022"}
|
||||
|
||||
调用`list_docs_from_db(session, "知识库A")`将返回以下列表:
|
||||
```python
|
||||
[
|
||||
{"id": "docA", "metadata": {"author": "张三", "year": "2021"}},
|
||||
{"id": "docB", "metadata": {"author": "李四", "year": "2022"}}
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数如何根据指定的知识库名称返回该知识库下所有文档的ID和元数据。
|
||||
## FunctionDef delete_docs_from_db(session, kb_name, file_name)
|
||||
**delete_docs_from_db**: 此函数的功能是删除某知识库某文件对应的所有文档,并返回被删除的文档信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_name`: 字符串类型,指定要删除文档的知识库名称。
|
||||
- `file_name`: 字符串类型,可选参数,默认为None,指定要删除文档的文件名称。
|
||||
|
||||
**代码描述**:
|
||||
`delete_docs_from_db`函数首先调用`list_docs_from_db`函数,根据知识库名称`kb_name`和文件名称`file_name`(如果提供)列出所有对应的文档。然后,构造一个查询对象,通过`session.query(FileDocModel)`获取`FileDocModel`的查询接口,并使用`filter`方法根据知识库名称进行过滤。如果提供了`file_name`参数,则进一步根据文件名称进行过滤。接下来,使用`query.delete(synchronize_session=False)`方法删除满足条件的所有文档记录,并通过`session.commit()`提交事务,确保更改被保存到数据库中。最后,函数返回之前通过`list_docs_from_db`获取的被删除文档的列表。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,应确保传入的`session`是一个有效的数据库会话实例,并且已经正确配置。
|
||||
- 删除操作是不可逆的,因此在执行此函数之前,请确保确实需要删除这些文档。
|
||||
- 由于此函数返回被删除的文档信息,可以用于记录日志或进行后续处理。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在两条文档记录,其知识库名称为"知识库A",文件名称分别为"文件A.pdf"和"文件B.pdf",调用`delete_docs_from_db(session, "知识库A", "文件A.pdf")`后,函数可能返回以下列表:
|
||||
```python
|
||||
[
|
||||
{"id": "docA", "metadata": {"author": "张三", "year": "2021"}}
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数如何返回被删除的文档的ID和元数据信息。
|
||||
## FunctionDef add_docs_to_db(session, kb_name, file_name, doc_infos)
|
||||
**add_docs_to_db**: 此函数的功能是将某知识库某文件对应的所有Document信息添加到数据库中。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_name`: 字符串类型,指定要添加文档信息的知识库名称。
|
||||
- `file_name`: 字符串类型,指定要添加文档信息的文件名称。
|
||||
- `doc_infos`: 文档信息列表,每个元素是一个字典,包含文档的ID和元数据。
|
||||
|
||||
**代码描述**:
|
||||
`add_docs_to_db`函数主要用于将文档信息批量添加到数据库中。它接收一个数据库会话、知识库名称、文件名称以及文档信息列表作为参数。文档信息列表`doc_infos`的格式为`[{"id": str, "metadata": dict}, ...]`,其中每个字典代表一个文档的信息,包括文档的ID和元数据。
|
||||
|
||||
函数首先检查`doc_infos`是否为`None`,如果是,则打印一条错误信息,并返回`False`表示添加失败。这是为了处理可能的错误情况,确保函数的健壮性。
|
||||
|
||||
接下来,函数遍历`doc_infos`列表,对于列表中的每个文档信息,创建一个`FileDocModel`实例。`FileDocModel`是一个ORM模型,用于映射数据库中的`file_doc`表,它包含了文档的基本信息字段,如知识库名称、文件名称、文档ID以及元数据。创建`FileDocModel`实例时,会将当前遍历到的文档信息填充到相应的字段中。
|
||||
|
||||
然后,使用`session.add(obj)`将`FileDocModel`实例添加到数据库会话中,这样就可以将文档信息保存到数据库中。遍历完成后,函数返回`True`表示所有文档信息已成功添加到数据库。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`是有效的数据库会话实例,且已正确配置数据库连接。
|
||||
- `doc_infos`参数不能为空,且其内部的字典需要包含`id`和`metadata`键。
|
||||
- 在实际应用中,可能需要处理`session.add(obj)`操作可能引发的异常,例如数据库约束违反等。
|
||||
|
||||
**输出示例**:
|
||||
此函数没有直接的输出示例,因为它的主要作用是影响数据库状态。但在成功执行后,可以预期数据库中的`file_doc`表将新增相应的记录,记录的字段值将反映函数调用时提供的参数值。
|
||||
## FunctionDef count_files_from_db(session, kb_name)
|
||||
**count_files_from_db**: 此函数的功能是统计指定知识库中的文件数量。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定要统计文件数量的知识库名称。
|
||||
|
||||
**代码描述**:
|
||||
`count_files_from_db`函数通过接收一个数据库会话实例和一个知识库名称作为参数,利用ORM模型`KnowledgeFileModel`来查询指定知识库中的文件数量。在这个过程中,函数首先构造一个查询,该查询针对`KnowledgeFileModel`模型,使用`filter`方法根据知识库名称(`kb_name`)进行筛选,这里使用`ilike`方法实现不区分大小写的匹配,以增强查询的灵活性。最后,使用`count`方法计算并返回符合条件的记录数,即指定知识库中的文件数量。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,确保传入的`session`参数是一个有效的数据库会话实例,且`kb_name`参数正确指定了目标知识库的名称。
|
||||
- 由于使用了`ilike`方法进行模糊匹配,可以灵活匹配知识库名称,但在使用时应注意名称的准确性,以避免错误的统计结果。
|
||||
|
||||
**输出示例**:
|
||||
如果指定知识库名称为"DefaultKB",并且该知识库中有10个文件,调用`count_files_from_db(session, "DefaultKB")`将返回整数`10`,表示"DefaultKB"知识库中的文件数量为10。
|
||||
|
||||
此函数在项目中的应用场景包括,但不限于,知识库服务(如`KBService`类中的`count_files`方法)调用此函数来获取特定知识库中的文件总数,以支持知识库管理和数据分析等功能。
|
||||
## FunctionDef list_files_from_db(session, kb_name)
|
||||
**list_files_from_db**: 此函数的功能是从数据库中列出属于特定知识库的所有文件名。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话对象,用于执行数据库查询。
|
||||
- `kb_name`: 知识库的名称,用于筛选特定知识库的文件。
|
||||
|
||||
**代码描述**:
|
||||
`list_files_from_db`函数通过接收一个数据库会话对象和一个知识库名称作为参数,利用这个会话对象执行一个查询操作。这个查询是基于`KnowledgeFileModel`模型,筛选出`kb_name`字段与传入的知识库名称相匹配的所有记录。这里使用了`ilike`方法,它允许在比较时不区分大小写,增加了查询的灵活性。查询结果是`KnowledgeFileModel`的实例列表,代表找到的所有文件。然后,函数遍历这个列表,提取每个实例的`file_name`属性,即文件名,将这些文件名收集到一个列表中。最后,返回这个列表,包含了所有符合条件的文件名。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`对象是有效的数据库会话实例,且已正确配置与数据库的连接。
|
||||
- 传入的知识库名称`kb_name`应确保其准确性,因为查询结果直接依赖于此参数。
|
||||
- 查询使用了`ilike`方法,对大小写不敏感,但这可能会影响查询性能,特别是在大型数据库中。
|
||||
|
||||
**输出示例**:
|
||||
如果数据库中存在属于名为"GeneralKB"的知识库的文件,且这些文件名分别为"document1.pdf"、"report2.docx",那么调用`list_files_from_db(session, "GeneralKB")`将返回以下列表:
|
||||
```
|
||||
["document1.pdf", "report2.docx"]
|
||||
```
|
||||
## FunctionDef add_file_to_db(session, kb_file, docs_count, custom_docs, doc_infos)
|
||||
**add_file_to_db**: 此函数的功能是将文件信息添加到数据库中,如果文件已存在,则更新该文件的信息和版本号。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_file`: `KnowledgeFile` 类型,表示要添加到数据库的知识文件。
|
||||
- `docs_count`: 整型,默认为0,表示文件中包含的文档数量。
|
||||
- `custom_docs`: 布尔型,默认为False,表示文件中的文档是否为自定义文档。
|
||||
- `doc_infos`: 文档信息列表,每个元素是一个字典,格式为`[{"id": str, "metadata": dict}, ...]`,包含文档的ID和元数据。
|
||||
|
||||
**代码描述**:
|
||||
`add_file_to_db` 函数首先查询数据库中是否存在指定的知识库,如果存在,则继续检查该知识库中是否已有同名文件。如果文件已存在,函数将更新该文件的最后修改时间、文件大小、文档数量、是否为自定义文档标志以及文件版本号。如果文件不存在,则创建一个新的 `KnowledgeFileModel` 实例,并设置相应的文件信息,包括文件名、文件扩展名、所属知识库名称、文档加载器名称、文本分割器名称、文件修改时间、文件大小、文档数量和自定义文档标志。然后,将新文件实例添加到数据库会话中,并增加知识库的文件计数。无论文件是否已存在,都会调用 `add_docs_to_db` 函数,将文件对应的所有文档信息添加到数据库中。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `session` 是有效的数据库会话实例。
|
||||
- `kb_file` 参数必须是 `KnowledgeFile` 类型的实例,且其属性应正确设置以反映文件的实际信息。
|
||||
- `doc_infos` 参数中的每个字典必须包含 `id` 和 `metadata` 键。
|
||||
- 在实际应用中,可能需要处理数据库操作可能引发的异常,例如违反唯一性约束等。
|
||||
|
||||
**输出示例**:
|
||||
此函数没有直接的输出示例,因为它的主要作用是影响数据库状态。但在成功执行后,可以预期数据库中的 `knowledge_file` 表将新增或更新相应的记录,记录的字段值将反映函数调用时提供的参数值。
|
||||
## FunctionDef delete_file_from_db(session, kb_file)
|
||||
**delete_file_from_db**: 此函数的功能是从数据库中删除指定的知识文件,并更新相关知识库的文件计数。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_file`: `KnowledgeFile`类型的对象,表示需要从数据库中删除的知识文件。
|
||||
|
||||
**代码描述**:
|
||||
`delete_file_from_db`函数首先通过传入的`session`和`kb_file`对象构造查询条件,查询目标知识文件是否存在于`KnowledgeFileModel`表中。如果存在,函数将执行以下操作:
|
||||
1. 使用`session.delete(existing_file)`方法从数据库中删除找到的文件记录。
|
||||
2. 调用`delete_docs_from_db`函数,根据知识文件的名称和所属知识库名称删除该文件对应的所有文档记录。
|
||||
3. 提交数据库事务,确保上述删除操作被保存到数据库中。
|
||||
4. 查询`KnowledgeBaseModel`表,找到该知识文件所属的知识库记录,并将该知识库的`file_count`(文件计数)减1,再次提交数据库事务以保存更改。
|
||||
|
||||
**注意**:
|
||||
- 在执行删除操作前,请确保传入的`session`是一个有效的数据库会话实例,并且已经正确配置。
|
||||
- 删除操作是不可逆的,因此在执行此函数之前,请确保确实需要删除指定的知识文件及其相关文档。
|
||||
- 函数在成功删除文件和相关文档后,会更新知识库的文件计数。这一步骤对于维护知识库的准确性非常重要。
|
||||
|
||||
**输出示例**:
|
||||
该函数没有直接的输出示例,因为它主要执行数据库的删除操作。函数执行成功后,会返回`True`,表示知识文件及其相关文档已被成功删除,并且相关知识库的文件计数已更新。如果需要验证操作结果,可以通过查询数据库来确认指定的知识文件和文档是否已被删除,以及相应知识库的文件计数是否已减少。
|
||||
## FunctionDef delete_files_from_db(session, knowledge_base_name)
|
||||
**delete_files_from_db**: 该函数的功能是从数据库中删除指定知识库的所有文件记录。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `knowledge_base_name`: 字符串类型,指定要删除文件的知识库名称。
|
||||
|
||||
**代码描述**:
|
||||
`delete_files_from_db` 函数首先查询 `KnowledgeFileModel` 表,删除与指定知识库名称匹配的所有文件记录。接着,该函数查询 `FileDocModel` 表,同样删除与指定知识库名称匹配的所有文档记录。这两个操作都使用了 `ilike` 方法来进行不区分大小写的匹配,确保能够匹配到所有相关记录。之后,函数查询 `KnowledgeBaseModel` 表,找到对应的知识库实例,如果找到了,就将该知识库的文件计数设置为0,表示知识库中不再包含任何文件。最后,函数提交所有更改到数据库,并返回 `True`,表示操作成功完成。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的 `session` 是有效的数据库会话实例,并且已经正确配置。
|
||||
- 该函数会永久删除指定知识库中的所有文件记录,此操作不可逆,请谨慎使用。
|
||||
- 在删除文件记录之后,相关联的知识库的文件计数会被重置为0,这意味着知识库将不再包含任何文件。
|
||||
|
||||
**输出示例**:
|
||||
由于该函数的返回值是布尔类型,所以在成功执行删除操作后,它会返回 `True`。例如:
|
||||
```
|
||||
操作成功完成后返回值: True
|
||||
```
|
||||
## FunctionDef file_exists_in_db(session, kb_file)
|
||||
**file_exists_in_db**: 该函数用于检查指定的文件是否已存在于数据库中。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_file`: `KnowledgeFile` 类型的对象,表示要检查的知识库文件。
|
||||
|
||||
**代码描述**:
|
||||
`file_exists_in_db` 函数通过接收一个数据库会话 (`session`) 和一个 `KnowledgeFile` 对象 (`kb_file`) 作为参数,来检查指定的文件是否已经存在于数据库中。它首先使用 `session.query` 方法构造一个查询,该查询针对 `KnowledgeFileModel` 表进行,通过 `filter` 方法筛选出文件名 (`file_name`) 和知识库名称 (`kb_name`) 与传入的 `kb_file` 对象相匹配的记录。这里使用了 `ilike` 方法来进行不区分大小写的匹配。如果查询的结果中存在至少一条记录,即 `first()` 方法返回非空值,则认为文件已存在于数据库中,函数返回 `True`;否则,返回 `False`。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `session` 参数是一个有效的数据库会话实例,且已正确配置数据库连接。
|
||||
- 传入的 `kb_file` 对象应包含有效的 `filename` 和 `kb_name` 属性,这两个属性将用于数据库查询中的匹配条件。
|
||||
- 该函数不对数据库进行任何修改操作,仅用于检查文件的存在性。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中已存在文件名为 "example.pdf",知识库名称为 "DefaultKB" 的记录,当传入一个 `kb_file` 对象,其 `filename` 属性值为 "example.pdf",`kb_name` 属性值为 "DefaultKB" 时,函数将返回 `True`。如果数据库中不存在满足条件的记录,函数将返回 `False`。
|
||||
## FunctionDef get_file_detail(session, kb_name, filename)
|
||||
**get_file_detail**: 此函数用于获取指定知识库中特定文件的详细信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定要查询的知识库名称。
|
||||
- `filename`: 字符串类型,指定要查询的文件名。
|
||||
|
||||
**代码描述**:
|
||||
`get_file_detail`函数首先通过传入的`session`参数,使用SQLAlchemy的查询接口,根据`kb_name`(知识库名称)和`filename`(文件名)作为过滤条件,查询`KnowledgeFileModel`模型。查询条件使用了`ilike`方法,这意味着查询是大小写不敏感的,提高了查询的灵活性。如果查询到了指定的文件,函数将从查询结果中提取文件的详细信息,并以字典形式返回。这些信息包括知识库名称、文件名、文件扩展名、文件版本、文档加载器名称、文本分割器名称、创建时间、文件的最后修改时间、文件大小、是否为自定义文档、文档数量等。如果没有查询到指定的文件,函数将返回一个空字典。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保传入的`session`是一个有效的数据库会话实例。
|
||||
- 查询条件`kb_name`和`filename`是大小写不敏感的,这意味着无论传入的是大写还是小写,都可以正确查询到结果。
|
||||
- 返回的字典中包含了文件的多个属性,这些属性的值直接来源于数据库中的记录,因此在使用这些值时应注意它们的数据类型和含义。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"kb_name": "SampleKB",
|
||||
"file_name": "example.pdf",
|
||||
"file_ext": ".pdf",
|
||||
"file_version": 1,
|
||||
"document_loader": "PDFLoader",
|
||||
"text_splitter": "SpacyTextSplitter",
|
||||
"create_time": "2023-04-01 12:00:00",
|
||||
"file_mtime": 1617184000,
|
||||
"file_size": 1024,
|
||||
"custom_docs": false,
|
||||
"docs_count": 10
|
||||
}
|
||||
```
|
||||
此示例展示了当查询到文件时,`get_file_detail`函数返回的信息字典。包含了文件所属的知识库名称、文件名、文件扩展名、文件版本、文档加载器名称、文本分割器名称、文件的创建时间、最后修改时间、文件大小、是否为自定义文档以及文档数量等信息。
|
||||
@ -0,0 +1,108 @@
|
||||
## FunctionDef list_summary_from_db(session, kb_name, metadata)
|
||||
**list_summary_from_db**: 该函数的功能是列出某知识库中的chunk summary信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定要查询的知识库名称。
|
||||
- `metadata`: 字典类型,默认为空字典,用于过滤具有特定元数据的summary。
|
||||
|
||||
**代码描述**:
|
||||
`list_summary_from_db` 函数通过接收一个数据库会话、知识库名称以及可选的元数据字典作为参数,来查询特定知识库中的summary信息。首先,函数使用传入的知识库名称对`SummaryChunkModel`模型进行过滤查询,以获取该知识库下的所有summary信息。如果提供了元数据字典,函数将进一步根据元数据的键值对过滤这些summary信息。最终,函数将查询结果格式化为一个列表,每个元素是一个字典,包含summary的id、summary_context、summary_id、doc_ids以及metadata,然后返回这个列表。
|
||||
|
||||
**注意**:
|
||||
- 在使用`list_summary_from_db`函数时,确保传入的`session`是一个有效的数据库会话实例。
|
||||
- `kb_name`参数应确保与数据库中存储的知识库名称匹配,该参数支持大小写不敏感的匹配。
|
||||
- 当使用`metadata`参数进行过滤查询时,确保字典中的键和值与`SummaryChunkModel`中的`meta_data`字段中存储的键值对相匹配。
|
||||
|
||||
**输出示例**:
|
||||
调用`list_summary_from_db`函数可能返回如下格式的列表:
|
||||
```
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"summary_context": "这是一个关于AI技术的摘要",
|
||||
"summary_id": "summary123",
|
||||
"doc_ids": "['doc1', 'doc2']",
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"summary_context": "这是第二个摘要的示例文本",
|
||||
"summary_id": "summary456",
|
||||
"doc_ids": "['doc3', 'doc4']",
|
||||
"metadata": {"page": "1-2"}
|
||||
}
|
||||
]
|
||||
```
|
||||
这个示例展示了两个summary的信息,每个summary包含id、摘要内容(summary_context)、摘要ID(summary_id)、关联的文档ID列表(doc_ids)以及额外的元数据信息(metadata)。
|
||||
## FunctionDef delete_summary_from_db(session, kb_name)
|
||||
**delete_summary_from_db**: 该函数的功能是删除指定知识库的chunk summary,并返回被删除的chunk summary信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_name`: 字符串类型,指定要删除summary的知识库名称。
|
||||
|
||||
**代码描述**:
|
||||
`delete_summary_from_db` 函数首先调用 `list_summary_from_db` 函数,根据传入的知识库名称 `kb_name` 列出该知识库中所有的chunk summary信息。接着,函数构造一个查询,通过 `session.query` 方法和 `SummaryChunkModel` 模型,使用 `filter` 方法对知识库名称进行过滤,匹配大小写不敏感的知识库名称。然后,使用 `query.delete` 方法删除匹配的所有记录,并通过 `session.commit` 方法提交更改到数据库。最后,函数返回之前通过 `list_summary_from_db` 函数获取的被删除的chunk summary信息列表。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的 `session` 是一个有效的数据库会话实例,并且已经正确配置。
|
||||
- `kb_name` 参数应确保与数据库中存储的知识库名称匹配,且该参数支持大小写不敏感的匹配,以确保能正确找到目标知识库。
|
||||
- 函数执行删除操作后会立即提交更改,因此请谨慎使用,以避免误删除重要数据。
|
||||
|
||||
**输出示例**:
|
||||
调用 `delete_summary_from_db` 函数可能返回如下格式的列表:
|
||||
```
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"summary_context": "这是一个关于AI技术的摘要",
|
||||
"doc_ids": "['doc1', 'doc2']"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"summary_context": "这是第二个摘要的示例文本",
|
||||
"doc_ids": "['doc3', 'doc4']"
|
||||
}
|
||||
]
|
||||
```
|
||||
这个示例展示了两个被删除的summary的信息,每个summary包含id、摘要内容(summary_context)以及关联的文档ID列表(doc_ids)。
|
||||
## FunctionDef add_summary_to_db(session, kb_name, summary_infos)
|
||||
**add_summary_to_db**: 此函数的功能是将总结信息添加到数据库中。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `kb_name`: 字符串类型,指定要添加摘要信息的知识库名称。
|
||||
- `summary_infos`: 字典列表,每个字典包含一个总结信息,包括总结文本、文档标识符等信息。
|
||||
|
||||
**代码描述**:
|
||||
`add_summary_to_db` 函数接收一个数据库会话、知识库名称以及一个包含多个总结信息的列表。每个总结信息是一个字典,包含了总结文本(`summary_context`)、总结ID(`summary_id`)、文档ID列表(`doc_ids`)以及额外的元数据(`metadata`)。函数遍历这个列表,为每个总结信息创建一个`SummaryChunkModel`实例,并将其添加到数据库会话中。完成所有总结信息的添加后,函数提交会话以保存更改,并返回`True`表示操作成功。
|
||||
|
||||
在这个过程中,`SummaryChunkModel`是用于映射数据库中的摘要信息表的模型,它定义了如何存储知识库名称、总结文本、总结ID、文档ID列表和元数据等信息。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`是一个有效的数据库会话实例,且在调用此函数之前已经正确配置。
|
||||
- `summary_infos`列表中的每个字典都必须包含`summary_context`、`summary_id`、`doc_ids`和`metadata`键。
|
||||
- `metadata`字段应以正确的JSON格式传入,以避免在序列化或反序列化时出现错误。
|
||||
- 函数执行后,需要检查返回值确保总结信息已成功添加到数据库。
|
||||
|
||||
**输出示例**:
|
||||
调用`add_summary_to_db`函数通常不直接返回具体的数据实例,而是返回一个布尔值`True`,表示所有总结信息已成功添加到数据库。
|
||||
## FunctionDef count_summary_from_db(session, kb_name)
|
||||
**count_summary_from_db**: 此函数的功能是统计指定知识库名称下的摘要信息数量。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `kb_name`: 字符串类型,指定要查询摘要数量的知识库名称。
|
||||
|
||||
**代码描述**:
|
||||
`count_summary_from_db` 函数通过接收一个数据库会话实例和一个知识库名称作为参数,利用这个会话实例来查询 `SummaryChunkModel` 表中与给定知识库名称相匹配的摘要信息数量。在查询过程中,使用了 `ilike` 方法来实现不区分大小写的匹配,这意味着无论传入的知识库名称的大小写如何,都能正确地匹配到相应的记录。此函数返回一个整数,表示匹配到的摘要信息数量。
|
||||
|
||||
在项目的层次结构中,`count_summary_from_db` 函数属于 `knowledge_metadata_repository.py` 文件,该文件作为数据库仓库层的一部分,主要负责处理与知识库元数据相关的数据操作。`count_summary_from_db` 函数通过查询 `SummaryChunkModel`,与之关联的 `knowledge_metadata_model.py` 中定义的 `SummaryChunkModel` 类直接交互。`SummaryChunkModel` 类定义了摘要信息的数据模型,包括知识库名称、摘要文本等字段,是数据库中存储摘要信息的表结构映射。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,确保传入的 `session` 参数是一个有效的数据库会话实例,且 `kb_name` 参数是一个非空字符串。
|
||||
- 由于使用了 `ilike` 方法进行模糊匹配,调用此函数时应考虑性能影响,特别是在处理大量数据时。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中有3条属于“技术文档”知识库的摘要信息,调用 `count_summary_from_db(session, "技术文档")` 将返回整数 `3`。
|
||||
126
markdown_docs/server/db/repository/message_repository.md
Normal file
@ -0,0 +1,126 @@
|
||||
## FunctionDef add_message_to_db(session, conversation_id, chat_type, query, response, message_id, metadata)
|
||||
**add_message_to_db**: 此函数的功能是向数据库中添加一条新的聊天记录。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `conversation_id`: 字符串类型,表示对话的唯一标识。
|
||||
- `chat_type`: 聊天类型,如普通聊天、客服聊天等。
|
||||
- `query`: 用户的提问或输入。
|
||||
- `response`: 系统或模型的回答,默认为空字符串。
|
||||
- `message_id`: 聊天记录的唯一标识ID,如果未提供,则会自动生成。
|
||||
- `metadata`: 字典类型,用于存储额外的信息,默认为空字典。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先检查是否提供了`message_id`,如果没有,则使用`uuid.uuid4().hex`生成一个唯一的ID。接着,创建一个`MessageModel`实例,其中包含聊天记录的所有相关信息,如聊天类型、用户问题、模型回答、会话ID和元数据。然后,使用提供的数据库会话(`session`)将此实例添加到数据库中,并提交更改。最后,函数返回新添加的聊天记录的ID。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,确保传入的`session`是一个有效的数据库会话实例。
|
||||
- `metadata`参数应为字典类型,可以包含任意结构的数据,但需注意保持数据结构的一致性,以便于后续处理。
|
||||
- 自动生成的`message_id`是基于UUID的,确保了每条聊天记录的唯一性。
|
||||
- 函数执行成功后,会提交数据库事务,因此调用此函数前应确保其他相关数据库操作已正确执行,以避免事务冲突。
|
||||
|
||||
**输出示例**:
|
||||
调用`add_message_to_db`函数可能会返回如下的聊天记录ID:
|
||||
```
|
||||
'4f5e8a7b9d314f5a8e7b9d2f4b8a9e2f'
|
||||
```
|
||||
|
||||
此函数在项目中的应用场景包括但不限于在用户与系统进行交互时记录聊天内容,以及在自动化测试或数据分析中记录和回溯聊天历史。通过将聊天记录持久化存储,项目可以提供更丰富的用户体验和更深入的数据洞察。
|
||||
## FunctionDef update_message(session, message_id, response, metadata)
|
||||
**update_message**: 此函数的功能是更新已有的聊天记录。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `message_id`: 想要更新的聊天记录的唯一标识ID。
|
||||
- `response`: (可选)新的回复内容,字符串类型。
|
||||
- `metadata`: (可选)新的元数据,字典类型。
|
||||
|
||||
**代码描述**:
|
||||
`update_message`函数首先通过调用`get_message_by_id`函数根据`message_id`查询对应的聊天记录。如果找到了对应的记录,函数将根据传入的参数更新聊天记录的回复内容(`response`)和元数据(`metadata`)。如果`response`参数非空,则更新记录的回复内容;如果`metadata`参数是字典类型,则更新记录的元数据。更新完成后,该记录会被添加到数据库会话中,并提交更改。如果更新成功,函数返回更新记录的ID。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`是一个有效的数据库会话实例,并且已经正确配置以连接到目标数据库。
|
||||
- `message_id`应确保为有效的ID,且该ID在数据库中存在,以便能够找到对应的聊天记录进行更新。
|
||||
- 在更新元数据(`metadata`)时,传入的参数必须是字典类型,否则不会进行更新。
|
||||
- 函数执行成功后,会返回更新记录的ID;如果未找到对应的聊天记录,则不会执行更新操作,也不会返回ID。
|
||||
|
||||
**输出示例**:
|
||||
假设有一条消息ID为`123`的聊天记录,调用`update_message(session, '123', response='新的回复内容', metadata={'key': 'value'})`后,如果更新成功,函数将返回`123`。这意味着ID为`123`的聊天记录的回复内容和元数据已被成功更新。
|
||||
|
||||
在项目中,`update_message`函数被`on_llm_end`方法调用,用于在语言模型处理结束后更新聊天记录的回复内容。这显示了`update_message`在实际应用场景中的一个重要用途,即在获取到新的回复或信息后,及时更新数据库中的聊天记录,以保持数据的最新状态。
|
||||
## FunctionDef get_message_by_id(session, message_id)
|
||||
**get_message_by_id**: 此函数的功能是根据消息ID查询聊天记录。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `message_id`: 想要查询的聊天记录的唯一标识ID。
|
||||
|
||||
**代码描述**:
|
||||
`get_message_by_id`函数通过接收一个数据库会话(`session`)和一个消息ID(`message_id`)作为参数,使用这个会话来查询`MessageModel`模型中的记录。它首先构造一个查询,该查询通过`filter_by`方法指定了消息ID作为过滤条件,然后调用`first()`方法尝试获取第一条匹配的记录。如果存在符合条件的记录,该记录将被返回;否则,返回`None`。这个过程允许调用者根据特定的消息ID快速检索聊天记录。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`session`是一个有效的数据库会话实例,且已正确配置以连接到目标数据库。
|
||||
- `message_id`应确保为有效的ID,且该ID在数据库中存在,以便查询能够成功返回结果。
|
||||
- 此函数返回的是一个`MessageModel`实例,或者在未找到匹配记录时返回`None`。因此,调用此函数后应检查返回值,以确定是否成功检索到记录。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在一条消息ID为`123`的聊天记录,调用`get_message_by_id(session, '123')`可能会返回如下的`MessageModel`实例:
|
||||
```
|
||||
<message(id='123', conversation_id='456', chat_type='普通聊天', query='用户的问题', response='模型的回答', meta_data='{}', feedback_score=80, feedback_reason='详细的反馈理由', create_time='2023-04-01 12:00:00')>
|
||||
```
|
||||
如果指定的`message_id`在数据库中不存在,函数将返回`None`。
|
||||
## FunctionDef feedback_message_to_db(session, message_id, feedback_score, feedback_reason)
|
||||
**feedback_message_to_db**: 此函数的功能是更新聊天记录的用户反馈信息。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库操作。
|
||||
- `message_id`: 聊天记录的唯一标识ID,用于定位需要更新反馈的聊天记录。
|
||||
- `feedback_score`: 用户对聊天回答的评分,满分为100。
|
||||
- `feedback_reason`: 用户评分的理由。
|
||||
|
||||
**代码描述**:
|
||||
`feedback_message_to_db`函数首先通过`session.query(MessageModel).filter_by(id=message_id).first()`查询到指定ID的聊天记录实例。如果该记录存在,函数将更新该记录的`feedback_score`和`feedback_reason`字段为传入的参数值。之后,通过`session.commit()`提交更改到数据库。如果更新成功,函数返回更新记录的ID。
|
||||
|
||||
此函数是与用户反馈相关的核心功能之一,它允许用户对聊天记录进行评分和反馈,进而可以用于改进聊天系统的回答质量或进行其他相关分析。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保`session`已正确初始化并且可以进行数据库操作。
|
||||
- 传入的`message_id`应确保在数据库中存在,否则无法进行更新操作。
|
||||
- `feedback_score`应在0到100之间,代表用户满意度的百分比。
|
||||
- 在实际应用中,可能需要对用户的反馈理由`feedback_reason`进行长度或内容的校验,以避免存储无效或不恰当的信息。
|
||||
|
||||
**输出示例**:
|
||||
如果更新操作成功,函数将返回聊天记录的ID,例如:
|
||||
```
|
||||
'1234567890abcdef1234567890abcdef'
|
||||
```
|
||||
此ID可用于后续操作或日志记录,以便跟踪反馈操作的结果。
|
||||
## FunctionDef filter_message(session, conversation_id, limit)
|
||||
**filter_message**: 此函数的功能是根据对话框ID过滤聊天记录,并返回最近的几条记录。
|
||||
|
||||
**参数**:
|
||||
- `session`: 数据库会话实例,用于执行数据库查询。
|
||||
- `conversation_id`: 字符串类型,指定要查询的对话框ID。
|
||||
- `limit`: 整型,可选参数,默认值为10,指定返回记录的最大数量。
|
||||
|
||||
**代码描述**:
|
||||
`filter_message`函数首先通过传入的`session`和`conversation_id`参数,使用SQLAlchemy的查询接口从`MessageModel`模型中筛选出与指定对话框ID匹配的聊天记录。在查询过程中,它还应用了两个过滤条件:
|
||||
1. 忽略响应为空的记录,即只选择那些系统或模型已经给出回答的聊天记录。
|
||||
2. 按照创建时间降序排列结果,并通过`limit`参数限制返回的记录数量。
|
||||
|
||||
查询完成后,函数不直接返回`MessageModel`对象列表,而是构建了一个新的列表`data`,其中每个元素都是一个字典,包含`query`和`response`两个键值对,分别对应每条记录的用户查询和系统回答。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保传入的`session`是一个有效的数据库会话实例,且`conversation_id`参数应为正确的对话框ID格式。
|
||||
- 函数返回的数据结构是为了简化记录的内容,仅包含查询和回答信息,如果需要更多的聊天记录信息,可能需要对函数进行相应的修改。
|
||||
|
||||
**输出示例**:
|
||||
调用`filter_message`函数可能会返回如下格式的数据列表:
|
||||
```
|
||||
[
|
||||
{"query": "用户的问题1", "response": "系统的回答1"},
|
||||
{"query": "用户的问题2", "response": "系统的回答2"},
|
||||
...
|
||||
]
|
||||
```
|
||||
此列表包含了最多`limit`条记录,每条记录都是一个包含用户查询和系统回答的字典。
|
||||
63
markdown_docs/server/db/session.md
Normal file
@ -0,0 +1,63 @@
|
||||
## FunctionDef session_scope
|
||||
**session_scope**: 该函数的功能是作为上下文管理器,用于自动管理数据库会话的生命周期,包括获取会话、提交事务、回滚事务以及关闭会话。
|
||||
|
||||
**参数**: 该函数不接受任何参数。
|
||||
|
||||
**代码描述**: `session_scope` 函数定义了一个上下文管理器,用于简化数据库会话(Session)的使用。它首先创建一个本地会话实例 `SessionLocal()`。当进入上下文管理器时,它会尝试执行用户代码块,并在执行结束后自动提交事务。如果在执行用户代码块期间发生任何异常,它会自动回滚事务,以确保数据库状态的一致性,然后重新抛出异常以便调用者可以处理。无论操作成功还是发生异常,最终都会确保会话被正确关闭,释放资源。
|
||||
|
||||
在项目中,`session_scope` 被多个地方调用,体现了其重要性和通用性。例如,在 `server/db/session.py/with_session/wrapper` 中,它被用于确保数据库操作在一个安全的会话中执行,自动处理事务的提交和回滚。在 `server/knowledge_base/migrate.py/import_from_db` 中,它被用于导入数据时管理数据库会话,确保数据的一致性和完整性。
|
||||
|
||||
**注意**: 使用 `session_scope` 可以大大简化数据库会话的管理,但开发者需要注意,任何在 `yield` 之后的代码块中对数据库进行的修改操作,都应该在没有异常的情况下自动提交。在异常情况下,会自动回滚,因此开发者不需要在每次数据库操作后手动提交或回滚事务,但仍需注意异常处理的逻辑,确保应用的健壮性。
|
||||
## FunctionDef with_session(f)
|
||||
**with_session**: 该函数的功能是为被装饰的函数自动管理数据库会话。
|
||||
|
||||
**参数**:
|
||||
- `f`: 被装饰的函数,该函数需要接受一个数据库会话对象作为第一个参数,后续可以接受任意数量的位置参数和关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`with_session` 是一个装饰器函数,旨在简化数据库操作中会话的管理。它通过自动处理会话的创建、提交和回滚来减少重复代码,并确保数据库操作的安全性。当装饰的函数被调用时,`with_session` 首先创建一个数据库会话,并将这个会话作为第一个参数传递给被装饰的函数。在被装饰的函数执行过程中,如果操作成功完成,则会话会被提交,以保存更改。如果在执行过程中遇到任何异常,则会话会被回滚,以撤销所有未提交的更改,然后异常会被重新抛出。这样,使用`with_session`装饰的函数可以专注于业务逻辑,而不必担心数据库会话的管理。
|
||||
|
||||
在项目中,`with_session` 被用于装饰多个数据库仓库层的函数,例如 `conversation_repository.py`、`knowledge_base_repository.py` 等文件中的函数。这表明项目中的数据库操作广泛采用了`with_session`装饰器来确保数据库会话的正确管理。这种做法有助于保持代码的干净和一致性,同时减少了错误处理和会话管理的重复代码。
|
||||
|
||||
**注意**:
|
||||
- 使用`with_session`装饰的函数必须接受一个数据库会话对象作为其第一个参数。
|
||||
- 被装饰的函数中的数据库操作应该在这个会话的上下文中执行。
|
||||
- 如果被装饰的函数中发生异常,会话将自动回滚,因此开发者需要确保任何调用这些函数的代码适当地处理这些异常。
|
||||
|
||||
**输出示例**:
|
||||
由于`with_session`是一个装饰器,它本身不直接产生输出。它的作用是修改被装饰的函数的行为。因此,输出示例将取决于被装饰函数的具体实现。例如,如果它被用于装饰一个查询数据库并返回查询结果的函数,那么该函数的输出可能是数据库查询结果的列表。
|
||||
### FunctionDef wrapper
|
||||
**wrapper**: 此函数的功能是在数据库会话中执行传入的函数,并自动处理事务的提交和回滚。
|
||||
|
||||
**参数**:
|
||||
- `*args`: 传递给内部函数 `f` 的位置参数。
|
||||
- `**kwargs`: 传递给内部函数 `f` 的关键字参数。
|
||||
|
||||
**代码描述**: `wrapper` 函数是一个装饰器内部使用的函数,它利用了 `session_scope` 上下文管理器来确保数据库操作的安全性和一致性。当调用 `wrapper` 函数时,首先会通过 `session_scope()` 创建一个数据库会话的上下文环境。在这个上下文环境中,`wrapper` 尝试执行传入的函数 `f`,并将创建的会话对象 `session` 作为第一个参数传递给 `f`,同时传递任何额外的位置参数和关键字参数。
|
||||
|
||||
如果函数 `f` 成功执行,会话会通过 `session.commit()` 方法提交事务,确保所有的数据库操作被正确保存。如果在执行 `f` 或提交事务过程中发生任何异常,会话会通过 `session.rollback()` 方法回滚事务,撤销所有未提交的数据库操作,以保持数据库状态的一致性。无论操作成功还是发生异常,`session_scope` 上下文管理器都会确保数据库会话被正确关闭。
|
||||
|
||||
这种模式允许开发者在执行数据库操作时不必直接管理事务的提交和回滚,从而简化了代码并减少了错误的可能性。
|
||||
|
||||
**注意**: 使用 `wrapper` 函数时,需要确保传入的函数 `f` 接受一个 `session` 参数,并且能够正确处理任何传递给它的位置参数和关键字参数。此外,开发者应当注意异常处理,确保在发生异常时能够正确响应,避免数据不一致的问题。
|
||||
|
||||
**输出示例**: 由于 `wrapper` 函数的输出取决于传入的函数 `f` 的返回值,因此没有固定的输出格式。如果 `f` 函数设计为查询数据库并返回查询结果,那么 `wrapper` 函数的输出将是这些查询结果;如果 `f` 函数执行数据库更新操作且不返回特定值,则 `wrapper` 函数可能没有输出或返回一个表示操作成功的标志。
|
||||
***
|
||||
## FunctionDef get_db
|
||||
**get_db**: 此函数的功能是创建并返回一个数据库会话实例,并确保其在使用后正确关闭。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `get_db` 函数首先创建一个 `SessionLocal` 类的实例,这是通过 SQLAlchemy ORM 实现的会话管理。函数体内部使用了 Python 的 `try` 语句来确保无论操作成功还是遇到异常,数据库会话都能被正确关闭。通过 `yield` 关键字,函数暂时返回数据库会话给调用者,允许调用者执行数据库操作。当调用者完成数据库操作后,控制权返回到 `get_db` 函数,执行 `finally` 块中的代码,即调用 `db.close()` 方法来关闭数据库会话。这种模式确保了数据库资源的有效管理和释放,避免了资源泄露。
|
||||
|
||||
**注意**: 使用此函数时,应当在依赖注入(Dependency Injection)的上下文中使用,特别是在使用 FastAPI 或类似框架时。这样可以确保每个请求都能获得一个独立的数据库会话,并且在请求处理完成后自动关闭会话。此外,由于使用了 `yield` 关键字,调用此函数时需要注意它返回的是一个生成器(Generator),而不是直接的 `SessionLocal` 实例。在实际使用中,通常会配合框架提供的依赖注入机制来使用此函数,以自动处理会话的创建和关闭。
|
||||
## FunctionDef get_db0
|
||||
**get_db0函数功能**: 创建并返回一个SessionLocal实例。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `get_db0`函数的主要作用是初始化并返回一个数据库会话实例。在函数内部,首先通过调用`SessionLocal()`创建了一个SessionLocal实例,该实例代表了与数据库的会话。这个会话可以用于数据库的增删改查操作。函数最后将这个会话实例返回。这种设计模式通常用于依赖注入,确保在处理请求时能够有效地管理数据库会话的生命周期。
|
||||
|
||||
**注意**: 使用`get_db0`函数时,需要确保`SessionLocal`已经被正确配置,包括数据库的连接参数等。此外,使用完毕后应确保会话被正确关闭,以避免资源泄露。
|
||||
|
||||
**输出示例**: 由于`get_db0`函数返回的是一个SessionLocal实例,其具体的输出取决于`SessionLocal`类的实现。通常,这个实例将允许执行数据库操作,但不会直接显示为具体的数据或值。例如,可以使用返回的会话实例执行查询操作,如`db.query(Model).filter(...)`,但函数本身的返回值不会直接显示查询结果。
|
||||
97
markdown_docs/server/embeddings_api.md
Normal file
@ -0,0 +1,97 @@
|
||||
## FunctionDef embed_texts(texts, embed_model, to_query)
|
||||
**embed_texts**: 该函数的功能是对文本进行向量化处理,并返回向量化结果。
|
||||
|
||||
**参数**:
|
||||
- `texts`: 需要进行向量化处理的文本列表。
|
||||
- `embed_model`: 使用的嵌入模型名称,默认为配置中指定的嵌入模型。
|
||||
- `to_query`: 布尔值,指示向量化的文本是否用于查询,默认为False。
|
||||
|
||||
**代码描述**:
|
||||
`embed_texts`函数首先检查指定的嵌入模型是否在本地嵌入模型列表中。如果是,它将使用`load_local_embeddings`函数加载本地嵌入模型,并对文本进行向量化处理,然后返回包含向量化结果的`BaseResponse`对象。如果指定的嵌入模型不在本地模型列表中,函数将检查模型是否在支持嵌入功能的在线模型列表中。对于在线模型,函数将根据模型配置创建相应的工作类实例,并调用其嵌入方法进行文本向量化,同样返回`BaseResponse`对象。如果指定的嵌入模型既不在本地模型列表中也不在在线模型列表中,函数将返回一个错误信息,指出指定的模型不支持嵌入功能。在整个过程中,如果遇到任何异常,函数将捕获异常并返回包含错误信息的`BaseResponse`对象。
|
||||
|
||||
**注意**:
|
||||
- 在使用`embed_texts`函数时,需要确保传入的`texts`参数是有效的文本列表。
|
||||
- `embed_model`参数应正确指定,以便函数能够找到并使用正确的嵌入模型进行文本向量化处理。
|
||||
- `to_query`参数应根据实际需求设置,以优化向量化结果的使用场景。
|
||||
- 函数的执行结果依赖于指定嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。
|
||||
|
||||
**输出示例**:
|
||||
调用`embed_texts(texts=["你好", "世界"], embed_model="example_model", to_query=False)`可能会返回如下`BaseResponse`对象:
|
||||
```python
|
||||
BaseResponse(code=200, msg="success", data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
|
||||
```
|
||||
这表示两个文本"你好"和"世界"被成功向量化,向量化结果分别为`[0.1, 0.2, 0.3]`和`[0.4, 0.5, 0.6]`。
|
||||
## FunctionDef aembed_texts(texts, embed_model, to_query)
|
||||
**aembed_texts**: 此函数的功能是对文本列表进行异步向量化处理,并返回一个包含向量化结果的BaseResponse对象。
|
||||
|
||||
**参数**:
|
||||
- `texts`: 需要进行向量化处理的文本列表,类型为List[str]。
|
||||
- `embed_model`: 使用的嵌入模型名称,默认值为配置中指定的嵌入模型,类型为str。
|
||||
- `to_query`: 布尔值,指示向量化的文本是否用于查询,默认为False。
|
||||
|
||||
**代码描述**:
|
||||
`aembed_texts`函数首先检查`embed_model`是否在本地嵌入模型列表中。如果是,则使用`load_local_embeddings`函数加载本地嵌入模型,并异步调用`aembed_documents`方法进行文本向量化处理,最后返回包含向量化结果的`BaseResponse`对象。如果`embed_model`在支持嵌入功能的在线模型列表中,则通过`run_in_threadpool`函数异步调用`embed_texts`函数进行文本向量化处理,并返回相应的`BaseResponse`对象。如果在向量化过程中出现异常,函数将捕获异常并返回一个包含错误信息的`BaseResponse`对象,状态码设为500。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,需要确保传入的`texts`参数是有效的文本列表。
|
||||
- `embed_model`参数应正确指定,以便函数能够找到并使用正确的嵌入模型进行文本向量化处理。如果未指定,将使用默认配置的嵌入模型。
|
||||
- `to_query`参数应根据实际需求设置。如果向量化的文本用于查询,应将此参数设置为True,以优化向量化结果的使用场景。
|
||||
- 函数的执行结果依赖于指定嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。
|
||||
|
||||
**输出示例**:
|
||||
调用`await aembed_texts(texts=["你好", "世界"], embed_model="example_model", to_query=False)`可能会返回如下`BaseResponse`对象:
|
||||
```python
|
||||
BaseResponse(code=200, msg="success", data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
|
||||
```
|
||||
这表示两个文本"你好"和"世界"被成功向量化,向量化结果分别为`[0.1, 0.2, 0.3]`和`[0.4, 0.5, 0.6]`。
|
||||
|
||||
在项目中,`aembed_texts`函数被用于处理需要异步进行文本向量化的场景,如在知识库服务中对文本进行异步向量化以支持快速的文本查询和相似度计算。此外,它也支持通过在线API进行文本向量化,为项目提供了灵活的向量化解决方案。
|
||||
## FunctionDef embed_texts_endpoint(texts, embed_model, to_query)
|
||||
**embed_texts_endpoint**: 该函数的功能是对文本列表进行向量化处理,并返回处理结果。
|
||||
|
||||
**参数**:
|
||||
- `texts`: 要嵌入的文本列表,是一个字符串列表。该参数是必需的。
|
||||
- `embed_model`: 使用的嵌入模型。这可以是本地部署的Embedding模型,也可以是在线API提供的嵌入服务。默认值为配置中指定的嵌入模型。
|
||||
- `to_query`: 布尔值,指示向量是否用于查询。有些模型如Minimax对存储/查询的向量进行了区分优化。默认值为False。
|
||||
|
||||
**代码描述**:
|
||||
`embed_texts_endpoint`函数首先接收一个文本列表、一个嵌入模型名称以及一个布尔值参数。它调用`embed_texts`函数,将这些参数传递给该函数进行处理。`embed_texts`函数根据指定的嵌入模型对文本进行向量化处理,并返回一个`BaseResponse`对象,其中包含了向量化的结果。如果在向量化过程中遇到任何异常,`embed_texts`函数会捕获这些异常并返回一个包含错误信息的`BaseResponse`对象。`embed_texts_endpoint`函数最终返回`embed_texts`函数的输出,即向量化处理的结果。
|
||||
|
||||
**注意**:
|
||||
- 在调用`embed_texts_endpoint`函数时,必须提供有效的文本列表。
|
||||
- `embed_model`参数应该准确指定,以确保函数能够找到并使用正确的嵌入模型进行处理。
|
||||
- 根据实际需求设置`to_query`参数,以优化向量化结果的使用场景。
|
||||
- 函数的执行结果依赖于指定嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。
|
||||
|
||||
**输出示例**:
|
||||
调用`embed_texts_endpoint(texts=["hello", "world"], embed_model="example_model", to_query=False)`可能会返回如下`BaseResponse`对象:
|
||||
```python
|
||||
BaseResponse(code=200, msg="success", data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
|
||||
```
|
||||
这表示两个文本"hello"和"world"被成功向量化,向量化结果分别为`[0.1, 0.2, 0.3]`和`[0.4, 0.5, 0.6]`。
|
||||
## FunctionDef embed_documents(docs, embed_model, to_query)
|
||||
**embed_documents**: 该函数的功能是将文档列表向量化,转化为向量存储系统可以接受的参数格式。
|
||||
|
||||
**参数**:
|
||||
- `docs`: 文档对象的列表,每个文档包含页面内容和元数据。
|
||||
- `embed_model`: 字符串类型,指定用于文档向量化的嵌入模型,默认使用预设的嵌入模型。
|
||||
- `to_query`: 布尔类型,指示向量化的结果是否用于查询,默认为False。
|
||||
|
||||
**代码描述**:
|
||||
`embed_documents`函数首先从文档列表中提取页面内容和元数据,分别存储在`texts`和`metadatas`列表中。接着,调用`embed_texts`函数对`texts`列表中的文本进行向量化处理,其中`embed_model`参数指定使用的嵌入模型,`to_query`参数指示向量化的目的。`embed_texts`函数返回一个包含向量化结果的数据结构。如果向量化成功,`embed_documents`函数将返回一个字典,包含原始文本列表`texts`、向量化结果`embeddings`和元数据列表`metadatas`。
|
||||
|
||||
**注意**:
|
||||
- 在调用`embed_documents`函数时,确保传入的`docs`参数是有效的文档对象列表。
|
||||
- `embed_model`参数应指向有效的嵌入模型,以确保文本能被正确向量化。
|
||||
- 根据使用场景选择`to_query`参数的值,以优化向量化结果的应用。
|
||||
|
||||
**输出示例**:
|
||||
假设调用`embed_documents(docs=[Document1, Document2], embed_model="example_model", to_query=False)`,可能会返回如下字典:
|
||||
```python
|
||||
{
|
||||
"texts": ["文档1的内容", "文档2的内容"],
|
||||
"embeddings": [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]],
|
||||
"metadatas": [{"title": "文档1标题"}, {"title": "文档2标题"}]
|
||||
}
|
||||
```
|
||||
这表示两个文档被成功向量化,其中`texts`包含了文档的原始内容,`embeddings`包含了对应的向量化结果,`metadatas`包含了文档的元数据信息。
|
||||
95
markdown_docs/server/knowledge_base/kb_api.md
Normal file
@ -0,0 +1,95 @@
|
||||
## FunctionDef list_kbs
|
||||
**list_kbs**: 此函数的功能是获取知识库列表。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `list_kbs` 函数是一个无参数函数,用于从数据库中获取知识库的列表。它通过调用 `list_kbs_from_db` 函数来实现这一功能。`list_kbs_from_db` 函数从数据库中查询满足特定条件的知识库名称列表,并返回这些名称。然后,`list_kbs` 函数将这些名称封装在 `ListResponse` 类的实例中返回。`ListResponse` 类是专门用于封装列表数据响应的类,它继承自 `BaseResponse` 类,能够提供状态码、状态消息以及数据列表。这样的设计使得 API 的响应格式保持一致,便于前端开发者理解和使用。
|
||||
|
||||
**注意**:
|
||||
- `list_kbs` 函数依赖于 `list_kbs_from_db` 函数正确地从数据库中获取知识库名称列表。因此,确保数据库连接和查询逻辑正确是使用此函数的前提。
|
||||
- 返回的 `ListResponse` 实例中包含的数据列表应正确反映数据库中的知识库情况。这要求 `list_kbs_from_db` 函数能准确地执行其查询逻辑。
|
||||
- 在实际部署和使用时,应注意数据库的性能和响应时间,尤其是在知识库数量较多的情况下,以保证良好的用户体验。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在三个知识库,名称分别为 "知识库A", "知识库B", "知识库C",则函数可能返回的 `ListResponse` 实例如下所示:
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": ["知识库A", "知识库B", "知识库C"]
|
||||
}
|
||||
```
|
||||
这表示 API 调用成功,且返回了包含三个知识库名称的列表。
|
||||
## FunctionDef create_kb(knowledge_base_name, vector_store_type, embed_model)
|
||||
**create_kb**: 此函数用于创建一个新的知识库。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库的名称,类型为字符串。通过示例参数可以提供默认示例值。
|
||||
- `vector_store_type`: 向量存储类型,类型为字符串,默认值为"faiss"。
|
||||
- `embed_model`: 嵌入模型的名称,类型为字符串,默认使用项目配置的嵌入模型。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先通过调用`validate_kb_name`函数验证知识库名称的合法性。如果名称不合法或为空,则分别返回403和404状态码的`BaseResponse`对象,提示错误信息。接下来,使用`KBServiceFactory.get_service_by_name`方法检查是否已存在同名的知识库,如果存在,则返回404状态码的`BaseResponse`对象,提示知识库已存在。如果验证通过,函数将通过`KBServiceFactory.get_service`方法获取对应的知识库服务实例,并调用该实例的`create_kb`方法创建知识库。如果在创建过程中发生异常,将记录错误信息并返回500状态码的`BaseResponse`对象。成功创建知识库后,返回200状态码的`BaseResponse`对象,提示已新增知识库。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数创建知识库之前,需要确保知识库名称不为空且不包含非法字符,以避免安全风险。
|
||||
- 向量存储类型和嵌入模型应根据项目需求和配置进行选择,以确保知识库的正确创建和后续操作的有效性。
|
||||
- 在处理异常时,应注意记录详细的错误信息,以便于问题的定位和解决。
|
||||
|
||||
**输出示例**:
|
||||
如果成功创建名为"技术文档库"的知识库,函数将返回以下`BaseResponse`对象:
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "已新增知识库 技术文档库"
|
||||
}
|
||||
```
|
||||
如果尝试创建一个已存在的知识库,例如名为"技术文档库",函数将返回:
|
||||
```
|
||||
{
|
||||
"code": 404,
|
||||
"msg": "已存在同名知识库 技术文档库"
|
||||
}
|
||||
```
|
||||
如果知识库名称不合法,将返回:
|
||||
```
|
||||
{
|
||||
"code": 403,
|
||||
"msg": "Don't attack me"
|
||||
}
|
||||
```
|
||||
## FunctionDef delete_kb(knowledge_base_name)
|
||||
**delete_kb**: 此函数的功能是删除指定的知识库。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 字符串类型,表示要删除的知识库的名称。此参数通过请求体传入,且提供了示例值 "samples"。
|
||||
|
||||
**代码描述**:
|
||||
`delete_kb` 函数首先验证知识库名称的合法性。如果名称不合法,即不通过 `validate_kb_name` 函数的验证,将返回一个状态码为403的 `BaseResponse` 对象,消息内容为 "Don't attack me",表示请求被拒绝。接着,函数对知识库名称进行URL解码,以确保名称的正确性。
|
||||
|
||||
通过 `KBServiceFactory.get_service_by_name` 方法,根据知识库名称获取对应的知识库服务实例。如果实例为 `None`,即知识库不存在,将返回一个状态码为404的 `BaseResponse` 对象,消息内容为 "未找到知识库 {knowledge_base_name}"。
|
||||
|
||||
若知识库服务实例获取成功,函数尝试调用知识库服务实例的 `clear_vs` 方法来清除知识库中的向量数据,然后调用 `drop_kb` 方法删除知识库。如果删除操作成功,将返回一个状态码为200的 `BaseResponse` 对象,消息内容为 "成功删除知识库 {knowledge_base_name}"。
|
||||
|
||||
如果在删除过程中发生异常,将捕获异常并记录错误日志,然后返回一个状态码为500的 `BaseResponse` 对象,消息内容为 "删除知识库时出现意外: {e}",其中 `{e}` 是异常信息。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的知识库名称是经过URL编码的。
|
||||
- 此函数依赖于 `validate_kb_name` 函数来验证知识库名称的合法性,以防止潜在的安全风险。
|
||||
- 删除知识库是一个不可逆的操作,一旦执行,知识库中的所有数据将被永久删除。
|
||||
|
||||
**输出示例**:
|
||||
如果尝试删除一个不存在的知识库 "unknown_kb",函数可能返回的 `BaseResponse` 对象如下:
|
||||
```
|
||||
{
|
||||
"code": 404,
|
||||
"msg": "未找到知识库 unknown_kb"
|
||||
}
|
||||
```
|
||||
如果成功删除名为 "samples" 的知识库,函数可能返回的 `BaseResponse` 对象如下:
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "成功删除知识库 samples"
|
||||
}
|
||||
```
|
||||
374
markdown_docs/server/knowledge_base/kb_cache/base.md
Normal file
@ -0,0 +1,374 @@
|
||||
## ClassDef ThreadSafeObject
|
||||
**ThreadSafeObject**: ThreadSafeObject 类的功能是提供一个线程安全的对象封装,用于在多线程环境中安全地访问和修改对象。
|
||||
|
||||
**属性**:
|
||||
- `_obj`: 存储实际对象的属性,可以是任何类型。
|
||||
- `_key`: 对象的键,用于标识对象,可以是字符串或元组。
|
||||
- `_pool`: 对象所属的缓存池,类型为 `CachePool`,默认为 None。
|
||||
- `_lock`: 一个重入锁(`threading.RLock`),用于确保线程安全。
|
||||
- `_loaded`: 一个事件(`threading.Event`),用于控制对象加载状态。
|
||||
|
||||
**代码描述**:
|
||||
ThreadSafeObject 类通过封装对象、键、所属缓存池以及同步机制(重入锁和事件),提供了一个线程安全的方式来访问和修改对象。通过 `acquire` 方法,可以安全地获取对象的引用,进行操作,并在操作完成后自动释放锁。此外,`start_loading` 和 `finish_loading` 方法允许控制对象的加载状态,而 `wait_for_loading` 方法可以阻塞当前线程,直到对象加载完成。
|
||||
|
||||
在项目中,ThreadSafeObject 类与 CachePool 类紧密相关,后者负责管理缓存中的 ThreadSafeObject 实例。例如,CachePool 的 `get` 方法在返回缓存对象之前会调用 `wait_for_loading` 方法,确保对象已经加载完成。`set` 和 `pop` 方法则用于向缓存中添加或移除 ThreadSafeObject 实例。此外,`acquire` 方法提供了一种机制,允许在执行操作前安全地获取对象的引用。
|
||||
|
||||
ThreadSafeObject 类还被用作其他特定类型对象的基类,例如 ThreadSafeFaiss 类,后者在 ThreadSafeObject 的基础上增加了与 FAISS 相关的功能,如文档计数和保存到磁盘等。
|
||||
|
||||
**注意**:
|
||||
- 在多线程环境中操作共享资源时,使用 ThreadSafeObject 可以避免数据竞争和其他并发问题。
|
||||
- 使用 `acquire` 方法时,应确保使用 `with` 语句或手动释放锁,以避免死锁。
|
||||
- 修改 `_obj` 属性时,应通过 `obj` 属性的 setter 方法,以确保线程安全。
|
||||
|
||||
**输出示例**:
|
||||
假设有一个 ThreadSafeObject 实例,其 `_key` 为 "example_key",`_obj` 为某个自定义对象。调用 `__repr__` 方法可能会返回如下字符串:
|
||||
`"<ThreadSafeObject: key: example_key, obj: <自定义对象的表示>>"`
|
||||
### FunctionDef __init__(self, key, obj, pool)
|
||||
**__init__**: 该函数用于初始化ThreadSafeObject对象。
|
||||
|
||||
**参数**:
|
||||
- `key`: 可以是字符串或元组,用于标识对象。
|
||||
- `obj`: 初始化时分配给ThreadSafeObject的对象,默认为None。
|
||||
- `pool`: 一个CachePool实例,用于存储缓存对象,默认为None。
|
||||
|
||||
**代码描述**:
|
||||
这个`__init__`方法是`ThreadSafeObject`类的构造函数,负责初始化一个线程安全的对象。它接收三个参数:`key`、`obj`和`pool`。`key`是一个标识符,可以是字符串或元组,用于唯一标识这个对象。`obj`参数是任意类型,代表需要被线程安全访问的数据对象,默认值为None。`pool`参数是一个`CachePool`类型的实例,它是一个可选参数,默认值为None,用于指定这个对象所属的缓存池。
|
||||
|
||||
在对象初始化过程中,首先将传入的`obj`、`key`和`pool`参数分别赋值给内部变量`_obj`、`_key`和`_pool`。接着,使用`threading.RLock()`创建一个可重入锁(Reentrant Lock),并将其赋值给`_lock`属性,这样可以确保对象的线程安全访问。最后,创建一个`threading.Event()`实例赋值给`_loaded`属性,这个事件对象用于控制对象加载状态的同步。
|
||||
|
||||
**注意**:
|
||||
- 在多线程环境下操作同一个`ThreadSafeObject`实例时,应确保正确使用`_lock`来避免数据竞争。
|
||||
- `key`参数是必须的,因为它用于唯一标识一个`ThreadSafeObject`实例。
|
||||
- 如果提供了`pool`参数,那么这个`ThreadSafeObject`实例将与指定的缓存池相关联,这在管理多个缓存对象时非常有用。
|
||||
***
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是返回对象的官方字符串表示。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `__repr__` 方法是一个特殊的方法,用于定义对象的“官方”字符串表示。在这个实现中,首先通过 `type(self).__name__` 获取对象的类名,然后结合对象的 `key` 属性和 `_obj` 属性构造并返回一个格式化的字符串。这个字符串以 `<类名: key: 键值, obj: 对象值>` 的格式展示,其中 `键值` 是通过调用对象的 `key` 方法获取的,而 `对象值` 直接访问的是对象的 `_obj` 属性。这种表示方式不仅提供了对象的基本信息,还包括了对象的关键数据,使得调试和日志记录更为方便。
|
||||
|
||||
从项目的结构来看,`__repr__` 方法与 `key` 方法有直接的调用关系。`key` 方法用于获取对象的键值,这是对象在缓存或其他数据结构中的唯一标识符。在 `__repr__` 方法中,通过调用 `key` 方法可以获取到这个键值,并将其包含在对象的字符串表示中。这样做有助于在日志记录或调试时快速识别对象。
|
||||
|
||||
**注意**: 在使用 `__repr__` 方法时,需要确保对象的 `_key` 和 `_obj` 属性已经被正确初始化,否则可能会导致错误。此外,考虑到 `__repr__` 方法的输出可能会被用于日志记录,应确保包含的信息既有用又不过于冗长。
|
||||
|
||||
**输出示例**: 假设对象的类名为 `ThreadSafeObject`,`_key` 属性的值为 `"example_key"`,`_obj` 属性的值为 `"example_object"`,那么调用 `__repr__` 方法将返回:
|
||||
```
|
||||
<ThreadSafeObject: key: example_key, obj: example_object>
|
||||
```
|
||||
***
|
||||
### FunctionDef key(self)
|
||||
**key**: 此函数的功能是获取对象的键值。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `key` 函数是一个简单但关键的部分,用于访问和返回对象的 `_key` 属性。这个属性通常代表了对象在缓存或其他数据结构中的唯一标识符。在多线程环境下,访问和管理这些键值是确保数据一致性和线程安全的重要机制。
|
||||
|
||||
从项目中的调用情况来看,`key` 函数被多个地方调用,显示其在对象表示(`__repr__` 方法)、资源获取(`acquire` 方法)、以及特定操作如保存和清空缓存(`save` 和 `clear` 方法)中的重要性。例如,在 `__repr__` 方法中,通过调用 `key` 函数来获取对象的键值,以构建并返回对象的字符串表示,这有助于调试和日志记录。在 `acquire` 方法中,`key` 函数的返回值用于日志记录,帮助追踪哪个线程正在操作哪个资源。在 `save` 和 `clear` 方法中,`key` 同样用于日志记录,提供操作的上下文信息。
|
||||
|
||||
**注意**: 使用此函数时,需要确保 `_key` 属性已经被正确初始化,否则可能会引发错误。此外,考虑到线程安全,访问 `_key` 属性时应当小心处理同步问题,尽管在此函数的实现中看似简单,但在多线程环境下使用时应当保持警惕。
|
||||
|
||||
**输出示例**: 假设 `_key` 属性的值为 `"example_key"`,那么调用 `key` 函数将返回:
|
||||
```
|
||||
"example_key"
|
||||
```
|
||||
***
|
||||
### FunctionDef acquire(self, owner, msg)
|
||||
**acquire**: 此函数的功能是安全地获取并操作对象资源。
|
||||
|
||||
**参数**:
|
||||
- `owner`: 字符串类型,默认为空字符串,表示资源的拥有者。如果未提供,则默认使用当前线程的ID。
|
||||
- `msg`: 字符串类型,默认为空字符串,用于附加额外的日志信息。
|
||||
|
||||
**代码描述**:
|
||||
`acquire` 函数是一个上下文管理器,用于在多线程环境中安全地获取和释放资源。它首先尝试获取一个锁,以确保在操作对象资源时的线程安全。如果提供了`owner`参数,则使用该参数值作为资源的拥有者;如果未提供,则默认使用当前线程的ID作为拥有者。此外,如果存在`_pool`属性且不为`None`,则会调用`_pool._cache.move_to_end(self.key)`方法,将当前对象的键值移动到缓存的末尾,这通常用于维护缓存的LRU(最近最少使用)策略。
|
||||
|
||||
在成功获取锁并进行资源操作的前后,如果`log_verbose`为真,则会记录日志信息,包括操作的开始和结束,以及提供的`msg`信息。这有助于追踪资源的使用情况和调试。
|
||||
|
||||
在`finally`块中,无论资源操作是否成功,都会释放之前获取的锁,确保资源的安全释放,避免死锁的发生。
|
||||
|
||||
**注意**:
|
||||
- 使用`acquire`函数时,需要确保`_lock`属性已经被正确初始化为一个锁对象,否则在尝试获取锁时会引发异常。
|
||||
- 在多线程环境下操作共享资源时,正确使用锁是非常重要的,以避免数据竞争和不一致的问题。
|
||||
- `acquire`函数设计为一个上下文管理器,推荐使用`with`语句进行调用,以确保资源的正确获取和释放。
|
||||
***
|
||||
### FunctionDef start_loading(self)
|
||||
**start_loading**: 此函数的功能是清除加载状态。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `start_loading` 函数是 `ThreadSafeObject` 类的一个方法,用于重置对象的加载状态。在这个方法中,通过调用 `self._loaded.clear()` 实现了这一功能。`_loaded` 是一个标志,用于指示对象的数据是否已经被加载。调用 `clear` 方法将这个标志重置,意味着对象的加载状态被清除,对象被视为未加载状态。这通常是为了在数据需要重新加载时准备对象,确保数据的最新状态可以被重新加载和使用。
|
||||
|
||||
**注意**: 使用 `start_loading` 方法时,需要确保任何依赖于对象加载状态的操作都能正确处理对象的未加载状态。此外,考虑到这是一个线程安全的对象,`start_loading` 方法的调用应该在适当的同步机制下进行,以避免并发访问导致的问题。
|
||||
***
|
||||
### FunctionDef finish_loading(self)
|
||||
**finish_loading**: 此函数的功能是标记对象加载完成。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `finish_loading` 函数是`ThreadSafeObject`类的一个方法,用于在对象的加载或初始化过程完成后,通过设置一个内部的线程安全标志(例如,使用`threading.Event`的`set`方法),来通知其他可能在等待此对象加载完成的线程。在本项目中,`finish_loading`方法被多个地方调用,主要用于标记嵌入模型(Embeddings)或向量存储(Vector Store)加载完成的状态。
|
||||
|
||||
在`load_embeddings`方法中,`finish_loading`被调用来标记一个嵌入模型对象加载完成。这个过程包括选择合适的嵌入模型,加载模型,并将模型对象赋值给`ThreadSafeObject`实例的`obj`属性,最后通过调用`finish_loading`方法来标记加载过程完成。
|
||||
|
||||
在`load_vector_store`方法中,无论是在`KBFaissPool`还是`MemoFaissPool`类中,`finish_loading`同样被用于标记向量存储加载完成。加载向量存储的过程可能包括从磁盘加载现有的向量存储,或者创建一个新的空向量存储,然后将这个向量存储对象赋值给`ThreadSafeFaiss`实例的`obj`属性,并通过`finish_loading`方法来标记加载完成。
|
||||
|
||||
**注意**: 使用`finish_loading`方法时,需要确保在对象的加载或初始化逻辑正确完成后调用此方法。此外,调用此方法前,通常会有线程锁的操作,以确保线程安全。在调用`finish_loading`之后,其他线程可以通过检查相应的线程安全标志来确定对象是否已经加载完成,从而进行后续操作。
|
||||
***
|
||||
### FunctionDef wait_for_loading(self)
|
||||
**wait_for_loading**: 此函数的功能是等待直到对象加载完成。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `wait_for_loading` 函数是 `ThreadSafeObject` 类的一个方法,用于在多线程环境中确保对象安全地完成加载。该方法通过调用 `_loaded` 属性(一个线程安全的事件对象)的 `wait` 方法来实现。当 `_loaded` 事件被设置时,表示对象已经完成加载,此时 `wait` 方法将停止阻塞,允许执行后续代码。如果 `_loaded` 事件尚未被设置,调用此方法的线程将被阻塞,直到事件被设置。这种机制确保了在对象未完全加载前,任何依赖于对象状态的操作都将被暂停,从而避免了潜在的数据不一致或竞态条件问题。
|
||||
|
||||
**注意**: 使用 `wait_for_loading` 方法时,需要确保 `_loaded` 事件在对象加载完成后被正确设置,否则调用此方法的线程可能会无限期地阻塞。此外,考虑到多线程编程的复杂性,开发者应当仔细管理线程间的同步和通信,以避免死锁或资源竞争等问题。
|
||||
***
|
||||
### FunctionDef obj(self)
|
||||
**obj**: 此函数的功能是获取ThreadSafeObject对象中的_obj属性。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `obj`函数是一个简单的访问器(accessor),用于返回ThreadSafeObject实例中的`_obj`属性。在多线程环境下,ThreadSafeObject对象提供了线程安全的访问方式,确保在并发访问时,对象的状态保持一致性。在项目中,`obj`函数被用于多个场景,主要是在加载嵌入向量(embeddings)和向量存储(vector store)时,获取已经加载或创建的对象实例。
|
||||
|
||||
例如,在`load_embeddings`方法中,首先检查是否已经加载了指定模型和设备的嵌入向量,如果没有,则创建一个新的ThreadSafeObject实例,并通过`obj`函数设置嵌入向量对象。在`load_vector_store`方法中,同样的逻辑被应用于加载或创建向量存储实例。这种使用方式确保了在并发环境下,对嵌入向量和向量存储的访问是线程安全的。
|
||||
|
||||
**注意**: 在使用`obj`函数时,需要确保ThreadSafeObject实例的`_obj`属性已经被正确初始化。否则,返回的将是`None`或者是初始状态的对象,这可能会导致后续操作中出现错误。
|
||||
|
||||
**输出示例**: 假设ThreadSafeObject实例的`_obj`属性被设置为了一个嵌入向量对象,那么调用`obj`函数将返回这个嵌入向量对象。例如:
|
||||
|
||||
```python
|
||||
embeddings = thread_safe_object_instance.obj()
|
||||
```
|
||||
|
||||
这里,`embeddings`将是之前存储在ThreadSafeObject实例中的嵌入向量对象。
|
||||
***
|
||||
### FunctionDef obj(self, val)
|
||||
**obj**: obj函数用于设置ThreadSafeObject实例的内部对象。
|
||||
|
||||
**参数**:
|
||||
- `val`: 任意类型,表示要设置的值。
|
||||
|
||||
**代码描述**:
|
||||
obj函数是ThreadSafeObject类的一个成员方法,其主要功能是将传入的参数`val`赋值给实例的`_obj`属性。这个方法是线程安全对象操作的基础,允许在多线程环境中安全地修改对象的状态。
|
||||
|
||||
在项目中,obj函数被用于不同的上下文中,主要涉及到加载和设置嵌入式对象或向量存储。例如,在`EmbeddingsPool`的`load_embeddings`方法中,obj函数用于将加载的嵌入式模型对象赋值给ThreadSafeObject实例。这样做可以确保在并发访问时,嵌入式模型对象的加载和访问是线程安全的。
|
||||
|
||||
同样,在`KBFaissPool`和`MemoFaissPool`的`load_vector_store`方法中,obj函数被用于设置加载或创建的向量存储对象。这些方法首先检查缓存中是否已存在所需的向量存储,如果不存在,则创建一个新的ThreadSafeFaiss实例,并通过obj函数将向量存储对象赋值给它。这确保了向量存储的加载和初始化过程是线程安全的。
|
||||
|
||||
**注意**:
|
||||
- 使用obj函数时,需要确保传入的`val`参数是正确的类型,因为函数内部不进行类型检查。
|
||||
- 在多线程环境中使用obj函数修改对象状态时,应注意同步和并发控制,以避免数据竞争和不一致性问题。虽然obj函数本身的操作是简单的赋值,但它在项目中的应用场景通常涉及到线程安全的上下文,因此正确的使用方式对于保持程序的稳定性和正确性至关重要。
|
||||
***
|
||||
## ClassDef CachePool
|
||||
**CachePool**: CachePool 类的功能是提供一个线程安全的缓存池,用于存储和管理缓存对象。
|
||||
|
||||
**属性**:
|
||||
- `_cache_num`: 缓存池中允许存储的最大缓存对象数量。如果设置为-1,则不限制数量。
|
||||
- `_cache`: 一个有序字典,用于存储缓存对象。
|
||||
- `atomic`: 一个线程锁,确保缓存操作的线程安全。
|
||||
|
||||
**代码描述**:
|
||||
CachePool 类提供了一个线程安全的缓存池实现,允许用户存储、获取和管理缓存对象。它使用了一个有序字典 `_cache` 来存储缓存对象,其中键是缓存对象的标识符,值是缓存对象本身。通过 `atomic` 线程锁确保了对缓存操作的线程安全性。
|
||||
|
||||
- `__init__` 方法初始化缓存池,可以指定缓存池中允许的最大缓存对象数量。
|
||||
- `keys` 方法返回当前缓存中所有键的列表。
|
||||
- `_check_count` 方法检查当前缓存的数量,如果超过了设定的最大值,则移除最早添加的缓存对象。
|
||||
- `get` 方法根据键获取缓存对象。如果对象存在,则等待对象加载完成后返回。
|
||||
- `set` 方法将一个对象添加到缓存中,并根据需要移除最早的缓存对象以保持在最大数量限制内。
|
||||
- `pop` 方法可以移除并返回指定键的缓存对象。如果没有指定键,则移除并返回最早添加的缓存对象。
|
||||
- `acquire` 方法尝试获取指定键的缓存对象,并对其进行加锁处理,确保在并发环境下的数据一致性。
|
||||
- `load_kb_embeddings` 方法用于加载知识库嵌入向量,它根据知识库名称、嵌入设备和默认嵌入模型加载嵌入向量。
|
||||
|
||||
CachePool 类在项目中被其他对象如 `EmbeddingsPool` 和 `_FaissPool` 调用,用于管理嵌入向量和向量存储的缓存。这些调用情况表明 CachePool 类在知识库嵌入向量和向量存储管理中起到了核心作用,为上层提供了缓存管理和线程安全的支持。
|
||||
|
||||
**注意**:
|
||||
- 在多线程环境下操作缓存时,应确保正确使用 `atomic` 锁来避免数据竞争。
|
||||
- 当设置 `_cache_num` 限制缓存数量时,需要注意缓存淘汰策略可能会影响到缓存对象的可用性。
|
||||
|
||||
**输出示例**:
|
||||
由于 CachePool 主要提供缓存管理功能,其输出依赖于存储在缓存中的对象类型。例如,如果缓存中存储的是嵌入向量对象,那么 `get` 方法可能返回一个嵌入向量对象的实例。
|
||||
### FunctionDef __init__(self, cache_num)
|
||||
**__init__**: 此函数的功能是初始化CachePool对象。
|
||||
|
||||
**参数**:
|
||||
- `cache_num`: 整型,表示缓存中允许的最大元素数量,默认值为-1,表示不限制数量。
|
||||
- `self._cache`: 使用`OrderedDict`初始化,用于存储缓存数据,保持插入顺序。
|
||||
- `self.atomic`: 使用`threading.RLock`初始化,提供一个基于线程的锁,用于控制对缓存数据的并发访问,确保线程安全。
|
||||
|
||||
**代码描述**:
|
||||
此函数是`CachePool`类的构造函数,用于初始化一个缓存池对象。它接受一个参数`cache_num`,该参数指定了缓存中可以存储的最大元素数量。如果`cache_num`的值为-1,则表示缓存大小不受限制。函数内部首先将`cache_num`参数的值赋给对象的`_cache_num`属性,用于后续控制缓存大小。接着,使用`OrderedDict`初始化`_cache`属性,`OrderedDict`是一种特殊的字典,它可以记住元素被插入的顺序,这对于某些缓存淘汰策略(如最近最少使用LRU)是非常有用的。最后,通过`threading.RLock`创建一个可重入锁`atomic`,赋给对象的`atomic`属性。这个锁用于同步对缓存的访问,确保在多线程环境下对缓存的操作是线程安全的。
|
||||
|
||||
**注意**:
|
||||
- 在多线程环境下操作缓存时,应确保正确使用`self.atomic`锁,以避免数据竞争和不一致的问题。
|
||||
- `cache_num`的默认值为-1,意味着如果不特别指定,缓存大小不会受到限制。在实际应用中,根据需要合理设置此参数,以避免因缓存过大而消耗过多内存资源。
|
||||
- `OrderedDict`虽然可以保持元素的插入顺序,但在处理大量数据时可能会比普通字典有更高的性能开销,因此在设计缓存策略时应考虑到这一点。
|
||||
***
|
||||
### FunctionDef keys(self)
|
||||
**keys**: 此函数的作用是获取缓存中所有键的列表。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `keys` 函数是 `CachePool` 类的一个方法,它的主要作用是从缓存中检索所有的键,并将这些键作为字符串列表返回。在这个函数中,`self._cache.keys()` 调用会获取 `_cache` 字典中所有的键,然后通过 `list()` 函数将这些键转换成列表形式。这是一个非常基础但重要的功能,因为它允许其他部分的代码了解缓存中目前存储了哪些数据的键。
|
||||
|
||||
在项目中,这个函数被 `file_chat` 函数调用,以检查传入的 `knowledge_id` 是否存在于 `memo_faiss_pool` 缓存中。如果 `knowledge_id` 不在缓存的键中,`file_chat` 函数将返回一个错误响应,指出需要的临时知识库未找到。这表明 `keys` 函数在项目中用于验证和检索操作,确保在进行进一步处理之前,所需的数据已经被正确地存储在缓存中。
|
||||
|
||||
**注意**: 使用此函数时,需要确保 `_cache` 已经被正确初始化并且包含了所需的数据。此外,返回的键列表仅代表了函数被调用时刻缓存中的状态,缓存内容的后续更新不会反映在已返回的列表中。
|
||||
|
||||
**输出示例**: 假设缓存中存储了三个键,分别为 `"key1"`, `"key2"`, `"key3"`,那么调用 `keys` 函数将返回以下列表:
|
||||
```python
|
||||
["key1", "key2", "key3"]
|
||||
```
|
||||
***
|
||||
### FunctionDef _check_count(self)
|
||||
**_check_count**: 此函数的功能是检查缓存中的项目数量,并确保其不超过设定的最大值。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `_check_count` 函数是 `CachePool` 类的一个私有方法,用于维护缓存池中的项目数量不超过一个预设的最大值。这个函数首先检查成员变量 `_cache_num` 是否为整数且大于0。如果是,函数进入一个循环,循环的条件是缓存池 `_cache` 的长度大于 `_cache_num`。在循环内部,使用 `_cache.popitem(last=False)` 从缓存中移除最早添加的项目,直到缓存的大小不超过 `_cache_num`。这种机制确保了缓存池不会无限增长,从而有效管理内存使用。
|
||||
|
||||
在项目中,`_check_count` 被 `set` 方法调用。`set` 方法用于向缓存中添加一个新的项目,并在添加后立即调用 `_check_count` 来确保缓存池的大小不会超过预设的限制。这表明 `_check_count` 在缓存管理策略中起到了关键的作用,它通过限制缓存大小来防止内存溢出,确保了缓存系统的健壮性和稳定性。
|
||||
|
||||
**注意**: `_check_count` 是一个私有方法,意味着它仅在 `CachePool` 类内部使用,不应该被类外部直接调用。这种设计封装了缓存管理的细节,使得 `CachePool` 类的使用更加安全和方便。在使用 `CachePool` 类时,开发者无需直接管理缓存大小,而是通过设置 `_cache_num` 并使用 `set` 方法来间接控制。
|
||||
***
|
||||
### FunctionDef get(self, key)
|
||||
**get**: 此函数的功能是从缓存池中获取与给定键关联的线程安全对象。
|
||||
|
||||
**参数**:
|
||||
- `key`: 字符串类型,用于从缓存中检索对象的键。
|
||||
|
||||
**代码描述**:
|
||||
`get` 函数首先尝试从缓存池 `_cache` 中使用给定的键 `key` 来获取一个对象。如果找到了对应的对象,该函数会调用该对象的 `wait_for_loading` 方法。这个方法的作用是阻塞当前线程,直到对象的加载状态被设置为完成。这确保了在返回对象之前,对象已经处于可用状态。如果缓存中没有找到对应的键,函数将不会返回任何值。
|
||||
|
||||
在项目中,`get` 函数被多个地方调用,包括但不限于加载嵌入向量、保存和卸载向量存储、以及在工作线程中操作向量存储。这些调用场景表明,`get` 函数是处理缓存对象的关键组件,特别是在需要确保对象加载完成后再进行操作的情况下。
|
||||
|
||||
**注意**:
|
||||
- 使用 `get` 函数时,应确保提供的键 `key` 在缓存中确实存在,否则函数将返回 `None`。
|
||||
- 在多线程环境下,`get` 函数通过 `wait_for_loading` 方法确保了线程安全,避免了在对象加载完成前的竞态条件。
|
||||
|
||||
**输出示例**:
|
||||
假设缓存中存在一个键为 `"example_key"` 的 `ThreadSafeObject` 实例,且该实例已完成加载。调用 `get("example_key")` 将返回该 `ThreadSafeObject` 实例。如果 `"example_key"` 不存在于缓存中,函数将返回 `None`。
|
||||
***
|
||||
### FunctionDef set(self, key, obj)
|
||||
**set**: 此函数的功能是将一个线程安全的对象添加到缓存池中,并返回该对象。
|
||||
|
||||
**参数**:
|
||||
- `key`: 字符串类型,用于标识缓存中的对象。
|
||||
- `obj`: `ThreadSafeObject` 类型,表示要添加到缓存中的线程安全对象。
|
||||
|
||||
**代码描述**: `set` 函数首先将传入的线程安全对象 `obj` 与其对应的键 `key` 存储在缓存池的内部字典 `_cache` 中。这一操作确保了对象可以通过键值快速检索。随后,函数调用 `_check_count` 方法来检查缓存池中的对象数量是否超过了预设的最大值,如果超过了,将自动移除最早添加的对象以保持缓存池的大小在限制之内。最后,函数返回刚刚添加的线程安全对象 `obj`。
|
||||
|
||||
在项目中,`set` 函数被用于多个场景,包括但不限于加载嵌入向量(`load_embeddings`)、加载向量存储(`load_vector_store`)等。这些场景中,`set` 函数负责将新创建或加载的资源(如嵌入向量、向量存储)以线程安全的方式添加到缓存池中,确保后续可以高效、安全地访问这些资源。
|
||||
|
||||
**注意**:
|
||||
- 使用 `set` 函数时,需要确保传入的键 `key` 在缓存池中唯一,以避免覆盖已有的缓存项。
|
||||
- 由于 `set` 函数会检查缓存池的大小并在必要时移除最早的缓存项,开发者应当合理设置缓存池的最大容量 `_cache_num`,以平衡内存使用和性能需求。
|
||||
- 在多线程环境下,`set` 函数保证了添加缓存项的线程安全性,但在使用缓存项时,仍需注意线程安全的访问和操作。
|
||||
|
||||
**输出示例**: 假设调用 `set` 函数添加了一个键为 `"example_key"`,对象为某个 `ThreadSafeObject` 实例的缓存项,函数将返回这个 `ThreadSafeObject` 实例。
|
||||
***
|
||||
### FunctionDef pop(self, key)
|
||||
**pop**: 该函数用于从缓存池中移除并返回指定键的对象或最早添加的对象。
|
||||
|
||||
**参数**:
|
||||
- `key`: 字符串类型,指定要移除对象的键。默认为 None,表示移除并返回最早添加的对象。
|
||||
|
||||
**代码描述**:
|
||||
`pop` 函数是 `CachePool` 类的一个方法,用于根据给定的键从缓存中移除并返回相应的对象。如果调用时没有提供键(即 `key=None`),则函数会移除并返回缓存中最早被添加的对象。这是通过调用 `_cache` 字典的 `popitem` 方法实现的,其中 `last=False` 参数确保返回最早添加的项。如果提供了键,则通过 `_cache` 字典的 `pop` 方法尝试移除并返回与该键关联的对象。如果键不存在,则返回 `None`。
|
||||
|
||||
在项目中,`pop` 方法被多个场景调用,例如在 `upload_temp_docs` 函数中,用于移除之前的临时文档;在 `unload_vector_store` 方法中,用于释放向量库;在 `do_clear_vs` 方法中,用于清除特定的向量存储;以及在 `drop_kb_summary` 方法中,用于删除知识库摘要。这些调用场景表明 `pop` 方法在管理缓存资源、维护缓存状态和释放不再需要的资源方面起着关键作用。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `pop` 方法时,应确保键的正确性和存在性,特别是在期望移除特定对象时。如果键不存在,方法将返回 `None`,而不是抛出异常。
|
||||
- 当不需要指定键移除对象时,应注意 `pop` 方法将移除并返回最早添加的对象,这可能会影响缓存的使用逻辑。
|
||||
|
||||
**输出示例**:
|
||||
假设缓存中存在键为 "example_key" 的 `ThreadSafeObject` 对象,调用 `pop("example_key")` 将返回该对象,并从缓存中移除。如果缓存为空或键不存在,调用 `pop("nonexistent_key")` 将返回 `None`。
|
||||
***
|
||||
### FunctionDef acquire(self, key, owner, msg)
|
||||
**acquire**: 此函数的功能是从缓存池中安全地获取与给定键关联的对象。
|
||||
|
||||
**参数**:
|
||||
- `key`: 字符串或元组类型,用于从缓存中检索对象的键。
|
||||
- `owner`: 字符串类型,默认为空字符串,表示请求对象的所有者。
|
||||
- `msg`: 字符串类型,默认为空字符串,用于附加消息或说明。
|
||||
|
||||
**代码描述**:
|
||||
`acquire` 函数首先通过调用 `get` 方法尝试从缓存池中获取与给定键 `key` 关联的对象。如果缓存中不存在该键对应的对象,函数将抛出 `RuntimeError` 异常,提示请求的资源不存在。如果成功获取到对象,并且该对象是 `ThreadSafeObject` 类型的实例,则会调用该对象的 `acquire` 方法来安全地获取对象的引用,并将其返回。这一过程涉及到线程安全的处理,确保在多线程环境下对对象的访问是安全的。如果获取到的对象不是 `ThreadSafeObject` 类型的实例,则直接返回该对象。
|
||||
|
||||
在项目中,`acquire` 函数被用于安全地获取缓存中的对象,以进行后续操作。例如,在 `knowledge_base_chat_iterator` 函数中,通过调用 `acquire` 方法来获取知识库中的向量存储对象,以执行相似度搜索等操作。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `acquire` 函数时,应确保提供的键 `key` 在缓存中确实存在,否则会抛出异常。
|
||||
- 当获取到的对象是 `ThreadSafeObject` 类型的实例时,应通过 `with` 语句或其他方式确保在操作完成后释放锁,以避免潜在的死锁问题。
|
||||
- `acquire` 方法的使用场景主要集中在需要线程安全访问和操作缓存对象的情况。
|
||||
|
||||
**输出示例**:
|
||||
由于 `acquire` 函数的返回值取决于缓存中对象的类型,因此可能有不同的返回形式。如果缓存中的对象是 `ThreadSafeObject` 类型的实例,则返回值将是该对象的引用;如果是其他类型的对象,则直接返回该对象。例如,如果缓存中存在键为 `"example_key"` 的 `ThreadSafeObject` 实例,调用 `acquire("example_key")` 将返回该实例的引用。如果 `"example_key"` 对应的是非 `ThreadSafeObject` 类型的对象,则直接返回该对象。
|
||||
***
|
||||
### FunctionDef load_kb_embeddings(self, kb_name, embed_device, default_embed_model)
|
||||
**load_kb_embeddings**: 此函数的功能是加载指定知识库名称的嵌入向量。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 字符串类型,指定要加载嵌入向量的知识库名称。
|
||||
- `embed_device`: 字符串类型,默认值由`embedding_device`函数确定,用于指定计算设备。
|
||||
- `default_embed_model`: 字符串类型,默认值为`EMBEDDING_MODEL`,用于指定默认的嵌入模型。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先从`knowledge_base_repository`中调用`get_kb_detail`函数,根据`kb_name`获取知识库的详细信息,包括嵌入模型名称。如果知识库详情中包含嵌入模型名称,则使用该名称;否则,使用传入的`default_embed_model`作为嵌入模型名称。接着,函数检查该嵌入模型是否在在线模型列表中,该列表由`list_online_embed_models`函数提供。如果嵌入模型存在于在线模型列表中,则通过`EmbeddingsFunAdapter`类创建一个嵌入向量适配器实例并返回。如果嵌入模型不在在线模型列表中,则调用`embeddings_pool`的`load_embeddings`方法,根据模型名称和设备类型加载嵌入向量,并返回加载的嵌入向量实例。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,需要确保传入的`kb_name`是存在的知识库名称,且知识库中有对应的嵌入模型信息。
|
||||
- `embed_device`参数应根据实际计算环境选择合适的设备类型,如`"cuda"`、`"mps"`或`"cpu"`。
|
||||
- 此函数依赖于`EmbeddingsFunAdapter`类和`embeddings_pool`的`load_embeddings`方法,因此在使用前应确保相关依赖正确配置。
|
||||
|
||||
**输出示例**:
|
||||
假设知识库名称为"技术文档库",且该知识库使用的嵌入模型在在线模型列表中,则可能返回一个`EmbeddingsFunAdapter`实例。如果嵌入模型不在在线模型列表中,则可能返回由`load_embeddings`方法加载的嵌入向量实例,具体类型取决于加载的嵌入模型。
|
||||
***
|
||||
## ClassDef EmbeddingsPool
|
||||
**EmbeddingsPool**: EmbeddingsPool 类的功能是管理和加载不同模型的嵌入向量。
|
||||
|
||||
**属性**:
|
||||
- 无特定公开属性,继承自 CachePool 类的属性。
|
||||
|
||||
**代码描述**:
|
||||
EmbeddingsPool 类继承自 CachePool 类,专门用于加载和管理嵌入向量。它提供了一个 `load_embeddings` 方法,该方法负责根据指定的模型和设备加载嵌入向量。方法首先尝试从缓存中获取嵌入向量,如果缓存中不存在,则根据模型类型创建相应的嵌入向量对象,并将其添加到缓存中。
|
||||
|
||||
在加载嵌入向量时,根据模型的不同,EmbeddingsPool 类会调用不同的嵌入向量类。例如,对于 OpenAI 的 "text-embedding-ada-002" 模型,它会使用 `OpenAIEmbeddings` 类;对于包含 "bge-" 的模型,它会根据模型语言选择 `HuggingFaceBgeEmbeddings` 类,并设置相应的查询指令;对于其他模型,它默认使用 `HuggingFaceEmbeddings` 类。
|
||||
|
||||
此外,`load_embeddings` 方法在加载嵌入向量之前会通过 `atomic` 锁确保线程安全,避免在并发环境下的数据竞争问题。加载完成后,嵌入向量对象会被存储在缓存中,以便后续快速获取。
|
||||
|
||||
**注意**:
|
||||
- 使用 `load_embeddings` 方法时,需要确保传入的模型和设备参数正确,否则可能无法加载正确的嵌入向量。
|
||||
- 在多线程环境下使用此类时,其内部的线程安全机制可以保护嵌入向量的加载过程,但调用者仍需注意线程安全的其他方面。
|
||||
- 由于嵌入向量可能占用大量内存,应合理管理缓存大小,避免内存溢出。
|
||||
|
||||
**输出示例**:
|
||||
调用 `load_embeddings` 方法可能返回的嵌入向量对象示例:
|
||||
```python
|
||||
embeddings = embeddings_pool.load_embeddings(model="text-embedding-ada-002", device="cuda")
|
||||
```
|
||||
此代码行将返回一个针对 "text-embedding-ada-002" 模型的 `OpenAIEmbeddings` 对象,该对象已配置好与 OpenAI API 交互所需的所有参数,并准备好在指定的设备上进行嵌入向量的计算。
|
||||
### FunctionDef load_embeddings(self, model, device)
|
||||
**load_embeddings**: 此函数的功能是加载并返回指定模型和设备上的嵌入向量对象。
|
||||
|
||||
**参数**:
|
||||
- `model`: 字符串类型,指定要加载的嵌入模型名称。如果未提供,则使用默认的嵌入模型。
|
||||
- `device`: 字符串类型,指定计算设备。如果未提供,则通过`embedding_device`函数自动检测并选择合适的设备。
|
||||
|
||||
**代码描述**:
|
||||
函数首先尝试获取一个线程安全的锁,以确保在多线程环境下的操作安全。然后,根据提供的模型名称和设备类型构造一个键值对`key`,用于检索或存储嵌入向量对象。如果缓存中不存在对应的嵌入向量对象,函数将创建一个新的`ThreadSafeObject`实例,并根据模型名称加载相应的嵌入向量。
|
||||
|
||||
如果模型名称为`"text-embedding-ada-002"`,则加载OpenAI提供的嵌入模型。如果模型名称包含`"bge-"`,则根据模型名称中的语言标识(如`"zh"`或`"en"`)加载对应语言的HuggingFace Bge嵌入模型,并设置相应的查询指令。对于其他模型名称,将加载HuggingFace提供的嵌入模型。
|
||||
|
||||
加载完成后,将嵌入向量对象赋值给`ThreadSafeObject`实例的`obj`属性,并标记加载完成。如果缓存中已存在对应的嵌入向量对象,则直接返回该对象。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,应确保提供的模型名称和计算设备类型正确,以便正确加载嵌入向量。
|
||||
- 函数内部使用了多线程安全机制,包括锁和`ThreadSafeObject`,以确保在并发环境下的操作安全。
|
||||
- 加载嵌入向量可能需要一定的时间,特别是首次加载时,因此在设计应用逻辑时应考虑到可能的延迟。
|
||||
|
||||
**输出示例**:
|
||||
调用`load_embeddings(model="text-embedding-ada-002", device="cuda")`可能会返回一个`OpenAIEmbeddings`的实例,该实例已经加载了指定的OpenAI嵌入模型,并准备好在CUDA设备上进行嵌入向量的计算。
|
||||
|
||||
在项目中,`load_embeddings`函数被`load_kb_embeddings`和`load_local_embeddings`等函数调用,用于加载知识库嵌入向量或本地嵌入向量,以支持不同的应用场景,如文本相似度计算、文本检索等。
|
||||
***
|
||||
302
markdown_docs/server/knowledge_base/kb_cache/faiss_cache.md
Normal file
@ -0,0 +1,302 @@
|
||||
## FunctionDef _new_ds_search(self, search)
|
||||
**_new_ds_search**: 此函数的功能是根据提供的搜索字符串查找并返回相应的文档或未找到的信息。
|
||||
|
||||
**参数**:
|
||||
- `search`: 需要搜索的字符串,用于在内部字典中查找对应的文档。
|
||||
|
||||
**代码描述**:
|
||||
此函数接收一个名为`search`的参数,该参数是一个字符串,用于在内部维护的字典`_dict`中查找对应的条目。函数首先检查`search`是否存在于`_dict`中。如果不存在,函数将返回一个格式化的字符串,指出给定的ID未找到。如果找到了对应的条目,函数将进一步检查这个条目是否是一个`Document`类型的实例。如果是,函数将在该文档的元数据中添加一个`id`字段,其值为`search`参数的值。最后,无论条目是否为`Document`实例,函数都将返回这个条目。
|
||||
|
||||
**注意**:
|
||||
- 函数返回值的类型依赖于查找结果。如果未找到对应的条目,将返回一个字符串;如果找到了条目,返回值将是该条目本身,可能是`Document`类型或其他类型。
|
||||
- 在使用此函数时,需要确保`_dict`已经被正确初始化并填充了相应的数据。
|
||||
- 当返回的是`Document`类型的实例时,其`metadata`将包含一个额外的`id`字段,其值对应于搜索字符串。
|
||||
|
||||
**输出示例**:
|
||||
- 如果搜索的ID未在`_dict`中找到,可能的返回值为:"ID 12345 not found."
|
||||
- 如果搜索的ID在`_dict`中找到,并且对应的条目是一个`Document`实例,返回的将是这个被更新了`metadata`的`Document`实例。
|
||||
## ClassDef ThreadSafeFaiss
|
||||
**ThreadSafeFaiss**: ThreadSafeFaiss 类的功能是提供一个线程安全的封装,用于操作和管理 FAISS 向量库。
|
||||
|
||||
**属性**:
|
||||
- `key`: 对象的键,用于标识特定的向量库。
|
||||
- `_obj`: 存储实际 FAISS 向量库的对象。
|
||||
- `docs_count`: 表示向量库中文档的数量。
|
||||
|
||||
**代码描述**:
|
||||
ThreadSafeFaiss 类继承自 ThreadSafeObject,增加了与 FAISS 向量库相关的特定功能。这个类主要用于在多线线程环境中安全地操作 FAISS 向量库,包括文档计数、保存到磁盘和清空向量库等操作。
|
||||
|
||||
- `__repr__` 方法提供了类的字符串表示,包括类名、键、对象以及文档数量。
|
||||
- `docs_count` 方法返回向量库中文档的数量,这是通过查询 `_obj.docstore._dict` 的长度来实现的。
|
||||
- `save` 方法用于将向量库保存到指定的磁盘路径。如果路径不存在且 `create_path` 参数为真,则会创建该路径。保存操作完成后,会记录一条日志信息。
|
||||
- `clear` 方法用于清空向量库中的所有文档。清空操作完成后,会记录一条日志信息。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `save` 和 `clear` 方法时,会通过 `acquire` 方法获取锁,以确保线程安全。这意味着在这些操作执行期间,其他线程将无法访问该向量库对象。
|
||||
- 修改 `_obj` 属性时,应通过 `obj` 属性的 setter 方法,以确保线程安全。
|
||||
- 在多线程环境下操作向量库时,使用 ThreadSafeFaiss 可以有效避免数据竞争和其他并发问题。
|
||||
|
||||
**输出示例**:
|
||||
假设有一个 ThreadSafeFaiss 实例,其 `key` 为 "example_key",`_obj` 为某个 FAISS 向量库对象,且向量库中有 100 个文档。调用 `__repr__` 方法可能会返回如下字符串:
|
||||
`"<ThreadSafeFaiss: key: example_key, obj: <FAISS向量库对象的表示>, docs_count: 100>"`
|
||||
|
||||
通过这个类,开发者可以在多线程环境中安全高效地管理和操作 FAISS 向量库,无需担心线程安全问题。
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是生成并返回对象的字符串表示形式。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `__repr__` 方法是 `ThreadSafeFaiss` 类的一个特殊方法,用于提供对象的官方字符串表示。这种表示形式通常用于调试和日志记录,使得开发者可以更容易地理解对象的状态。在这个方法中,首先通过 `type(self).__name__` 获取对象的类名,然后通过访问对象的 `key` 属性和 `_obj` 属性,以及调用 `docs_count` 方法来获取文档数量,构造出一个格式化的字符串。这个字符串包含了对象的类名、键值、对应的对象以及文档数量,这些信息对于理解和调试 `ThreadSafeFaiss` 对象的状态非常有用。
|
||||
|
||||
`key` 属性提供了对象在缓存或其他数据结构中的唯一标识符,是通过访问对象的 `_key` 属性来获取的。`docs_count` 方法返回文档存储中文档的数量,是通过计算 `_obj.docstore._dict` 的长度来实现的。这里的 `_obj` 属性指向一个文档存储对象,`_dict` 是该存储对象中用于保存文档的字典。
|
||||
|
||||
通过这种方式,`__repr__` 方法为 `ThreadSafeFaiss` 对象提供了一个详细且易于理解的字符串表示,包括了关键的状态信息,如对象的键值和存储中的文档数量。
|
||||
|
||||
**注意**: 在使用 `__repr__` 方法时,需要确保 `_obj` 属性和 `_key` 属性已经被正确初始化,并且 `_obj.docstore._dict` 中包含了需要计数的文档。如果这些属性或字典未被正确初始化,可能会影响到字符串表示的准确性。
|
||||
|
||||
**输出示例**: 假设一个 `ThreadSafeFaiss` 对象的类名为 `ThreadSafeFaiss`,其键值为 `"example_key"`,对应的 `_obj` 属性指向一个包含3个文档的文档存储对象,那么调用 `__repr__` 方法可能返回如下字符串:
|
||||
```
|
||||
"<ThreadSafeFaiss: key: example_key, obj: <文档存储对象>, docs_count: 3>"
|
||||
```
|
||||
***
|
||||
### FunctionDef docs_count(self)
|
||||
**docs_count**: 此函数的功能是返回文档存储中文档的数量。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `docs_count` 函数是 `ThreadSafeFaiss` 类的一个方法,用于获取当前对象中文档存储 `_dict` 的长度,即文档的数量。这里,`self._obj.docstore` 指向一个文档存储对象,而 `_dict` 是该存储对象中用于保存文档的字典。通过调用 `len` 函数计算 `_dict` 的长度,可以得到存储中文档的总数。此方法在 `ThreadSafeFaiss` 类的实例化对象中被调用,特别是在其 `__repr__` 方法中,用于生成对象的字符串表示,其中包括了文档数量的信息。这样,当需要展示或记录 `ThreadSafeFaiss` 对象的状态时,可以直接通过其字符串表示来获取关键信息,包括文档数量。
|
||||
|
||||
**注意**: 使用此函数时,需要确保 `self._obj.docstore._dict` 已经正确初始化并包含了需要计数的文档。如果 `_dict` 是空的或者未被正确初始化,此函数将返回 `0`。
|
||||
|
||||
**输出示例**: 假设 `_dict` 中存储了3个文档,那么 `docs_count()` 的返回值将是 `3`。
|
||||
***
|
||||
### FunctionDef save(self, path, create_path)
|
||||
**save**: 此函数的功能是将向量库保存到指定路径。
|
||||
|
||||
**参数**:
|
||||
- `path`: 字符串类型,表示向量库保存的目标路径。
|
||||
- `create_path`: 布尔类型,默认为True,指示如果目标路径不存在,是否创建该路径。
|
||||
|
||||
**代码描述**:
|
||||
`save` 函数首先通过调用 `acquire` 方法来安全地获取资源,确保在多线程环境下的操作不会引起数据竞争或不一致的问题。在成功获取资源后,函数检查`path`参数指定的路径是否存在,如果不存在且`create_path`参数为True,则会创建该路径。随后,函数调用 `_obj.save_local` 方法将向量库保存到指定的路径。在保存过程中,会通过日志记录功能输出保存操作的信息,包括向量库的键值(通过调用 `key` 方法获取)和保存的目标路径。完成保存操作后,释放之前获取的资源,并返回 `_obj.save_local` 方法的返回值。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保提供的`path`参数是有效的文件系统路径,且当前运行环境有足够的权限在该路径下创建文件夹或写入文件。
|
||||
- 如果`create_path`参数设置为False,而指定的路径不存在,则不会创建新路径,可能会导致保存操作失败。
|
||||
- 此函数在多线程环境下安全使用,但调用者应确保正确处理任何可能的异常,以避免资源泄露或其他意外情况。
|
||||
|
||||
**输出示例**: 由于此函数的主要作用是保存文件到磁盘,其返回值取决于 `_obj.save_local` 方法的实现,通常不直接输出信息。但在日志中,可以看到类似以下的信息:
|
||||
```
|
||||
已将向量库 example_key 保存到磁盘
|
||||
```
|
||||
这表明键值为`example_key`的向量库已成功保存到磁盘。
|
||||
***
|
||||
### FunctionDef clear(self)
|
||||
**clear**: 此函数的功能是清空向量库。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `clear` 函数负责清空当前对象所代表的向量库。它首先创建一个空列表 `ret`,用于存储删除操作的返回结果。通过使用 `with self.acquire()` 上下文管理器,函数确保在多线程环境下安全地访问和操作向量库。在这个上下文管理器内部,首先获取向量库中所有文档的ID列表,然后检查这个列表是否非空。如果非空,调用 `_obj.delete(ids)` 方法删除这些文档,并将返回结果存储到 `ret` 中。此外,函数通过断言 `assert len(self._obj.docstore._dict) == 0` 确保所有文档都已被删除,向量库被成功清空。最后,记录一条日志信息,表明已经清空了特定的向量库,其中 `self.key` 用于获取向量库的唯一标识符。
|
||||
|
||||
从功能角度来看,`clear` 函数与其调用的对象 `acquire` 和 `key` 密切相关。`acquire` 函数提供了一个线程安全的环境,确保在执行删除操作时不会发生数据竞争。`key` 函数则用于获取向量库的唯一标识符,这在日志记录时非常有用,帮助开发者和维护者追踪是哪个向量库被清空了。
|
||||
|
||||
**注意**: 在使用 `clear` 函数时,需要确保向量库的 `_obj` 属性已经被正确初始化,并且 `_obj.docstore._dict` 能够正确反映向量库中文档的存储状态。此外,考虑到函数中使用了断言来验证向量库是否被成功清空,因此在生产环境中使用时应当确保这一点,以避免因断言失败而导致的异常。
|
||||
|
||||
**输出示例**: 假设向量库中原本存储了若干文档,调用 `clear` 函数后,如果删除成功,函数将返回一个包含删除操作结果的列表。例如,如果删除成功,可能返回如下列表:
|
||||
```
|
||||
[True, True, ...]
|
||||
```
|
||||
如果向量库原本为空,或者在删除过程中没有实际删除任何文档,则返回一个空列表:
|
||||
```
|
||||
[]
|
||||
```
|
||||
***
|
||||
## ClassDef _FaissPool
|
||||
**_FaissPool**: _FaissPool 类的功能是管理和操作基于FAISS库的向量存储。
|
||||
|
||||
**属性**:
|
||||
- 该类继承自 `CachePool`,因此拥有 `CachePool` 的所有属性和方法。
|
||||
|
||||
**代码描述**:
|
||||
_FaissPool 类提供了三个主要方法来管理向量存储:`new_vector_store`、`save_vector_store` 和 `unload_vector_store`。
|
||||
|
||||
1. `new_vector_store` 方法用于创建一个新的向量存储。它接受嵌入模型名称和嵌入设备作为参数,使用 `EmbeddingsFunAdapter` 来适配不同的嵌入模型,并创建一个文档对象 `doc` 作为初始化数据。然后,它使用 `FAISS.from_documents` 方法根据这个文档对象和嵌入模型创建一个新的FAISS向量存储,同时设置L2归一化和距离策略。创建后,它会删除这个初始化文档对象,以便返回一个空的向量存储。
|
||||
|
||||
2. `save_vector_store` 方法用于保存指定名称的向量存储到磁盘。如果在缓存中找到了对应名称的向量存储,它会调用向量存储的 `save` 方法将其保存到指定路径。
|
||||
|
||||
3. `unload_vector_store` 方法用于从缓存中卸载并释放指定名称的向量存储。如果在缓存中找到了对应名称的向量存储,它会先从缓存中移除该向量存储,然后记录一条日志信息表示向量库已成功释放。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `new_vector_store` 方法创建向量存储时,需要确保传入的嵌入模型名称和嵌入设备是有效的,因为这将影响向量存储的创建和后续的向量检索性能。
|
||||
- 使用 `save_vector_store` 方法保存向量存储时,如果没有提供保存路径,则需要确保向量存储对象已经配置了默认的保存路径。
|
||||
- 在调用 `unload_vector_store` 方法卸载向量存储之前,应确保没有其他操作正在使用该向量存储,以避免数据丢失或访问冲突。
|
||||
|
||||
**输出示例**:
|
||||
由于这些方法主要进行向量存储的管理操作,它们的输出通常不直接返回数据给用户。例如,`new_vector_store` 方法返回一个初始化后的空的FAISS向量存储对象,而 `save_vector_store` 和 `unload_vector_store` 方法则没有返回值,它们的执行结果主要通过日志信息和向量存储的状态变化来体现。
|
||||
### FunctionDef new_vector_store(self, embed_model, embed_device)
|
||||
**new_vector_store**: 此函数的功能是创建一个新的向量存储空间。
|
||||
|
||||
**参数**:
|
||||
- `embed_model`: 字符串类型,默认值为 `EMBEDDING_MODEL`。用于指定嵌入模型的名称。
|
||||
- `embed_device`: 字符串类型,默认值为 `embedding_device()` 函数的返回值。用于指定嵌入计算的设备类型。
|
||||
|
||||
**代码描述**:
|
||||
`new_vector_store` 函数首先通过 `EmbeddingsFunAdapter` 类实例化一个嵌入模型适配器,该适配器根据传入的 `embed_model` 参数来处理文本嵌入转换。接着,函数创建一个包含初始化内容和元数据的 `Document` 对象。此后,利用 `FAISS.from_documents` 方法,以该文档对象、嵌入模型适配器、L2归一化以及内积距离策略作为参数,创建一个新的FAISS向量存储实例。创建过程中,会先向该向量存储中添加一个文档,然后立即删除,目的是初始化一个空的向量存储空间。最后,函数返回这个初始化后的向量存储实例。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数之前,需要确保 `embed_model` 指定的嵌入模型已经存在且可用。
|
||||
- `embed_device` 参数应根据实际运行环境的硬件配置来设置,以确保嵌入计算能在最适合的设备上执行(如GPU、MPS或CPU)。
|
||||
- 此函数创建的向量存储实例是空的,即没有包含任何文档的向量数据。通常用于初始化向量存储空间,后续需要通过其他方法向其中添加具体的文档向量。
|
||||
|
||||
**输出示例**:
|
||||
由于此函数返回一个FAISS向量存储实例,而具体的实例内容依赖于运行时的环境和参数,因此不易提供一个具体的输出示例。但可以预期,返回的向量存储实例是一个初始化状态的FAISS对象,准备好接收和管理文档向量数据。
|
||||
***
|
||||
### FunctionDef save_vector_store(self, kb_name, path)
|
||||
**save_vector_store**: 此函数的功能是保存向量存储。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 字符串类型,指定要保存的知识库名称。
|
||||
- `path`: 字符串类型,可选参数,指定保存向量存储的路径。如果未提供,则使用默认路径。
|
||||
|
||||
**代码描述**:
|
||||
`save_vector_store` 函数首先尝试通过调用 `get` 函数从缓存池中获取与给定知识库名称 (`kb_name`) 关联的线程安全对象。如果成功获取到对象,该函数将调用该对象的 `save` 方法,并将可选的路径参数 `path` 传递给它。这一过程实现了向量存储的保存操作。
|
||||
|
||||
从功能上看,`get` 函数是从缓存池中检索与给定键关联的线程安全对象的关键步骤。它确保了在进行保存操作之前,所需的对象已经被成功加载并处于可用状态。这一点对于确保数据的一致性和防止在保存过程中发生错误至关重要。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `save_vector_store` 函数时,应确保提供的知识库名称 (`kb_name`) 在缓存中存在。如果不存在,函数将不执行任何操作并返回 `None`。
|
||||
- 提供的保存路径 (`path`) 应确保是有效的,如果路径无效或未提供,可能会导致保存操作失败或使用默认路径。
|
||||
|
||||
**输出示例**:
|
||||
假设存在一个名为 `"example_kb"` 的知识库对象,并且该对象已经被加载到缓存中。调用 `save_vector_store("example_kb", "/path/to/store")` 将会将该知识库对象的向量存储保存到指定的路径。如果 `"example_kb"` 不存在于缓存中,函数将不执行任何操作并返回 `None`。
|
||||
***
|
||||
### FunctionDef unload_vector_store(self, kb_name)
|
||||
**unload_vector_store**: 此函数的功能是从缓存池中卸载并释放指定的向量库。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 字符串类型,指定要卸载并释放的向量库的名称。
|
||||
|
||||
**代码描述**:
|
||||
`unload_vector_store` 函数是 `_FaissPool` 类的一个方法,用于卸载并释放指定名称的向量库。该函数首先调用 `get` 方法尝试从缓存池中获取与给定名称 `kb_name` 关联的向量库对象。如果成功获取到对象,`get` 方法会确保该对象的加载状态已完成,这是通过对象的 `wait_for_loading` 方法实现的,从而确保在进行后续操作前,对象已经处于可用状态。
|
||||
|
||||
获取到对象后,函数接着调用 `pop` 方法,根据提供的向量库名称 `kb_name` 从缓存池中移除该对象。移除操作成功后,会通过日志记录一条信息,表明指定的向量库已成功释放。
|
||||
|
||||
在整个过程中,`get` 方法确保了只有在向量库对象确实存在且加载完成的情况下,才会进行卸载操作。而 `pop` 方法则负责实际的移除操作,并处理缓存池中对象的移除逻辑。
|
||||
|
||||
**注意**:
|
||||
- 使用此函数时,应确保提供的向量库名称 `kb_name` 在缓存池中确实存在。如果不存在,函数将不执行任何操作。
|
||||
- 此函数通过日志记录操作结果,有助于监控和调试向量库的卸载过程。
|
||||
- 在多线程环境下,`get` 方法的线程安全机制确保了在进行卸载操作前,对象的加载状态已经完成,避免了潜在的竞态条件。
|
||||
***
|
||||
## ClassDef KBFaissPool
|
||||
**KBFaissPool**: KBFaissPool 类的功能是管理和加载基于FAISS库的向量存储池。
|
||||
|
||||
**属性**:
|
||||
- 继承自 `_FaissPool` 类,因此拥有 `_FaissPool` 的所有属性和方法。
|
||||
|
||||
**代码描述**:
|
||||
KBFaissPool 类主要提供了 `load_vector_store` 方法,用于加载或创建向量存储。该方法接受知识库名称(`kb_name`)、向量名称(`vector_name`)、是否创建新的向量存储(`create`)、嵌入模型名称(`embed_model`)和嵌入设备(`embed_device`)作为参数。
|
||||
|
||||
1. 方法首先尝试从内部缓存中获取指定的向量存储。如果未找到,它将初始化一个新的 `ThreadSafeFaiss` 对象,并尝试从磁盘加载向量存储或根据参数创建一个新的向量存储。
|
||||
|
||||
2. 如果指定路径下存在 `index.faiss` 文件,则从磁盘加载向量存储,并使用指定的嵌入模型和设备加载知识库嵌入。加载过程中,会对向量进行L2归一化,并设置距离策略为内积。
|
||||
|
||||
3. 如果指定路径下不存在 `index.faiss` 文件且 `create` 参数为真,则会创建一个新的空向量存储,并保存到磁盘。
|
||||
|
||||
4. 如果既不存在 `index.faiss` 文件,`create` 参数也为假,则抛出异常,表示指定的知识库不存在。
|
||||
|
||||
在加载或创建向量存储后,方法会将 `ThreadSafeFaiss` 对象存入内部缓存,并返回该对象。
|
||||
|
||||
**注意**:
|
||||
- 在调用 `load_vector_store` 方法时,需要确保传入的知识库名称和向量名称是有效的,以便正确地加载或创建向量存储。
|
||||
- 如果指定的向量存储已存在于内部缓存中,则方法会直接返回该缓存对象,而不会重复加载或创建。
|
||||
- 在创建新的向量存储时,需要确保嵌入模型和设备参数正确配置,以保证向量存储的性能和兼容性。
|
||||
|
||||
**输出示例**:
|
||||
调用 `load_vector_store` 方法可能返回的示例输出为一个 `ThreadSafeFaiss` 对象,该对象封装了FAISS向量存储的操作和管理,允许线程安全地访问和修改向量存储。
|
||||
### FunctionDef load_vector_store(self, kb_name, vector_name, create, embed_model, embed_device)
|
||||
**load_vector_store**: 此函数用于加载或创建指定知识库的向量存储。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 字符串类型,指定要加载或创建向量存储的知识库名称。
|
||||
- `vector_name`: 字符串类型,可选参数,默认为None。指定向量存储的名称。如果未提供,则使用嵌入模型名称作为向量名称。
|
||||
- `create`: 布尔类型,可选参数,默认为True。指示如果指定的向量存储不存在时,是否创建一个新的向量存储。
|
||||
- `embed_model`: 字符串类型,可选参数,默认为`EMBEDDING_MODEL`。用于指定嵌入模型的名称。
|
||||
- `embed_device`: 字符串类型,可选参数,默认由`embedding_device()`函数确定。用于指定嵌入计算的设备类型。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先尝试获取一个互斥锁,以确保线程安全。然后,根据提供的知识库名称和向量名称(如果未提供向量名称,则使用嵌入模型名称)尝试从缓存中获取对应的向量存储。如果缓存中不存在该向量存储,则会根据`create`参数的值决定是创建一个新的向量存储还是抛出异常。创建向量存储的过程包括初始化一个`ThreadSafeFaiss`实例,并将其添加到缓存中。接着,根据向量存储是否已存在于磁盘上,选择是从磁盘加载向量存储还是创建一个新的空向量存储。加载或创建完成后,会将向量存储实例赋值给`ThreadSafeFaiss`实例的`obj`属性,并标记加载完成。如果向量存储已存在于缓存中,则直接释放互斥锁。最后,函数返回缓存中的向量存储实例。
|
||||
|
||||
**注意**:
|
||||
- 在多线程环境下使用此函数时,内部的互斥锁确保了线程安全。
|
||||
- 如果`create`参数为False且指定的向量存储不存在,则会抛出运行时错误。
|
||||
- 在调用此函数之前,应确保`kb_name`和`vector_name`(如果提供)正确无误,因为它们直接影响向量存储的加载和创建。
|
||||
- 此函数依赖于`embedding_device()`函数来确定嵌入计算的设备类型,因此需要确保相关硬件和软件配置正确。
|
||||
|
||||
**输出示例**:
|
||||
由于此函数返回一个`ThreadSafeFaiss`实例,而具体的实例内容依赖于运行时的环境和参数,因此不易提供一个具体的输出示例。但可以预期,返回的向量存储实例是一个初始化状态的`ThreadSafeFaiss`对象,准备好接收和管理文档向量数据。
|
||||
***
|
||||
## ClassDef MemoFaissPool
|
||||
**MemoFaissPool**: MemoFaissPool 类的功能是在内存中加载和管理基于FAISS库的向量存储池。
|
||||
|
||||
**属性**:
|
||||
- 继承自 `_FaissPool` 类,因此拥有 `_FaissPool` 的所有属性和方法。
|
||||
|
||||
**代码描述**:
|
||||
`MemoFaissPool` 类通过继承 `_FaissPool` 类,提供了一种高效管理FAISS向量存储的方式。它主要通过 `load_vector_store` 方法来加载或初始化向量存储。
|
||||
|
||||
1. `load_vector_store` 方法接受三个参数:`kb_name`(知识库名称),`embed_model`(嵌入模型,默认为 `EMBEDDING_MODEL`),和 `embed_device`(嵌入设备,默认由 `embedding_device()` 函数确定)。该方法首先尝试从缓存中获取指定名称的向量存储。如果未找到,它将创建一个新的 `ThreadSafeFaiss` 对象,并将其添加到缓存中。在这个过程中,它使用了线程安全的锁机制来确保操作的原子性。
|
||||
|
||||
2. 在初始化 `ThreadSafeFaiss` 对象时,会调用 `_FaissPool` 类的 `new_vector_store` 方法来创建一个空的向量存储。这个过程涉及到使用指定的嵌入模型和设备来创建向量存储,确保了向量存储的创建与配置的灵活性和可定制性。
|
||||
|
||||
3. 完成向量存储的加载后,`load_vector_store` 方法会通过调用 `finish_loading` 方法来标记向量存储的加载状态,确保向量存储已经准备好被使用。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `load_vector_store` 方法时,需要确保传入的知识库名称、嵌入模型和嵌入设备参数正确无误,因为这些参数直接影响向量存储的创建和性能。
|
||||
- 该类使用了线程安全的锁机制来保护向量存储的加载过程,避免了并发访问和修改时可能出现的数据不一致问题。
|
||||
- 由于 `MemoFaissPool` 类继承自 `_FaissPool`,在使用该类之前,需要对 `_FaissPool` 类及其方法有一定的了解。
|
||||
|
||||
**输出示例**:
|
||||
由于 `load_vector_store` 方法的主要作用是加载或初始化向量存储,其直接的返回值是一个 `ThreadSafeFaiss` 对象。这个对象代表了一个已加载或新创建的向量存储,可以被进一步用于向量的检索或管理操作。例如,如果成功加载了名为 "knowledge_base" 的向量存储,那么返回的 `ThreadSafeFaiss` 对象将包含这个向量存储的所有相关信息和操作接口。
|
||||
### FunctionDef load_vector_store(self, kb_name, embed_model, embed_device)
|
||||
**load_vector_store**: 此函数的功能是加载或初始化一个向量存储库,并确保其线程安全。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 字符串类型,用于指定知识库的名称。
|
||||
- `embed_model`: 字符串类型,默认值为 `EMBEDDING_MODEL`。用于指定嵌入模型的名称。
|
||||
- `embed_device`: 字符串类型,默认值为 `embedding_device()` 函数的返回值。用于指定嵌入计算的设备类型。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先尝试获取一个原子锁,以确保线程安全。接着,尝试从缓存中获取与`kb_name`对应的向量存储对象。如果未找到,即`cache`为`None`,则会创建一个新的`ThreadSafeFaiss`实例,并将其与`kb_name`关联后设置到缓存中。在这个过程中,会初始化一个新的向量存储空间,这是通过调用`new_vector_store`函数实现的,该函数根据指定的嵌入模型和计算设备创建向量存储。完成向量存储的初始化后,会调用`finish_loading`方法标记加载过程完成。如果在缓存中找到了对应的向量存储对象,则直接释放原子锁。最后,函数返回从缓存中获取的向量存储对象。
|
||||
|
||||
**注意**:
|
||||
- 在多线程环境下使用此函数时,通过原子锁确保了操作的原子性和线程安全。
|
||||
- 在初始化向量存储时,需要确保指定的嵌入模型和计算设备已经准备就绪,以避免在后续操作中出现错误。
|
||||
- 此函数在向量存储对象不存在时会进行创建并加载,这可能是一个耗时操作,因此在设计应用逻辑时应考虑到这一点。
|
||||
|
||||
**输出示例**:
|
||||
由于此函数返回的是一个`ThreadSafeFaiss`实例,具体的实例内容依赖于运行时的环境和参数,因此不易提供一个具体的输出示例。但可以预期,返回的向量存储实例是一个经过初始化,准备好接收和管理文档向量数据的`ThreadSafeFaiss`对象。
|
||||
|
||||
在项目中,`load_vector_store`函数被`upload_temp_docs`函数调用,用于在上传文件并进行向量化处理时,加载或初始化临时向量库。这确保了上传的文档能够被正确地添加到向量库中,以支持后续的搜索和检索操作。
|
||||
***
|
||||
## FunctionDef worker(vs_name, name)
|
||||
**worker**: 此函数用于处理向量存储中文档的添加、搜索和删除操作。
|
||||
|
||||
**参数**:
|
||||
- `vs_name`: 字符串类型,指定向量存储的名称。
|
||||
- `name`: 字符串类型,表示执行当前操作的工作线程或用户的名称。
|
||||
|
||||
**代码描述**:
|
||||
`worker`函数首先将`vs_name`参数的值设置为"samples",这意味着所有操作都将在名为"samples"的向量存储中进行。接着,函数通过调用`load_local_embeddings`函数加载本地嵌入向量。这一步骤是必要的,因为无论是添加文档还是搜索文档,都需要使用到嵌入向量。
|
||||
|
||||
函数随机选择一个整数`r`,根据`r`的值决定执行添加文档、搜索文档还是删除文档的操作。具体来说,如果`r`等于1,则执行添加文档操作;如果`r`等于2,则执行搜索文档操作;如果`r`等于3,则执行删除文档操作。
|
||||
|
||||
在执行添加或搜索操作时,函数通过`kb_faiss_pool.load_vector_store(vs_name).acquire(name)`获取向量存储的上下文管理器,并确保操作的线程安全。在此上下文管理器内,根据`r`的值执行相应的操作。添加文档时,使用`add_texts`方法将文本和对应的嵌入向量添加到向量存储中,并打印添加的文档ID。搜索文档时,使用`similarity_search_with_score`方法根据提供的文本和嵌入向量搜索最相似的文档,并打印搜索结果。
|
||||
|
||||
如果`r`等于3,即执行删除文档操作,则在上下文管理器外部调用`kb_faiss_pool.get(vs_name).clear()`方法,清除指定向量存储中的所有文档。此操作通过日志记录执行删除操作的信息。
|
||||
|
||||
**注意**:
|
||||
- 在使用`worker`函数时,需要确保`vs_name`和`name`参数正确无误,因为它们直接影响向量存储的操作。
|
||||
- `load_local_embeddings`函数的调用依赖于正确的嵌入模型配置和计算设备设置,因此在执行`worker`函数之前,应确保相关配置正确。
|
||||
- `worker`函数通过随机选择操作类型(添加、搜索或删除文档),模拟了一个简单的向量存储操作场景。在实际应用中,可以根据具体需求调整操作逻辑。
|
||||
- 在多线程环境下使用`worker`函数时,通过`acquire`方法获取的上下文管理器确保了操作的线程安全。
|
||||
417
markdown_docs/server/knowledge_base/kb_doc_api.md
Normal file
@ -0,0 +1,417 @@
|
||||
## FunctionDef search_docs(query, knowledge_base_name, top_k, score_threshold, file_name, metadata)
|
||||
**search_docs**: 此函数的功能是根据用户输入的查询条件,在指定的知识库中搜索相关文档。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,默认为空字符串,表示用户的查询输入。
|
||||
- `knowledge_base_name`: 字符串类型,必填,表示要搜索的知识库名称。
|
||||
- `top_k`: 整型,表示返回的匹配向量数目。
|
||||
- `score_threshold`: 浮点型,取值范围在0-1之间,表示知识库匹配相关度阈值。SCORE越小,相关度越高,取到1相当于不筛选。
|
||||
- `file_name`: 字符串类型,默认为空字符串,表示文件名称,支持sql通配符。
|
||||
- `metadata`: 字典类型,默认为空字典,表示根据metadata进行过滤,仅支持一级键。
|
||||
|
||||
**代码描述**:
|
||||
函数首先通过`KBServiceFactory.get_service_by_name`方法获取指定知识库的服务实例。如果知识库服务实例存在,函数将根据是否提供了`query`参数来决定搜索逻辑。如果提供了`query`参数,函数将调用知识库服务实例的`search_docs`方法进行搜索,并将搜索结果转换为`DocumentWithVSId`对象列表返回。如果没有提供`query`但提供了`file_name`或`metadata`参数,函数将调用知识库服务实例的`list_docs`方法列出文档。最终,函数返回一个包含`DocumentWithVSId`对象的列表。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,确保传入的知识库名称在系统中已存在,否则将无法获取知识库服务实例,导致搜索失败。
|
||||
- `score_threshold`参数用于过滤搜索结果,较低的值意味着更高的相关性要求,可根据实际需求调整。
|
||||
- 当`query`参数为空时,可以通过`file_name`或`metadata`参数来列出知识库中的文档,这在需要根据特定条件获取文档列表时非常有用。
|
||||
|
||||
**输出示例**:
|
||||
假设在知识库中搜索"技术文档",并且设置`top_k=2`,`score_threshold=0.5`,可能得到如下输出:
|
||||
```python
|
||||
[
|
||||
DocumentWithVSId(id="doc1", score=0.45, metadata={"title": "技术文档介绍", "author": "张三"}),
|
||||
DocumentWithVSId(id="doc2", score=0.48, metadata={"title": "技术文档使用手册", "author": "李四"})
|
||||
]
|
||||
```
|
||||
此输出示例展示了根据查询条件返回的前两个最相关的文档对象列表,每个对象包含文档的唯一标识符、匹配得分以及元数据信息。
|
||||
## FunctionDef update_docs_by_id(knowledge_base_name, docs)
|
||||
**update_docs_by_id**: 按照文档 ID 更新文档内容。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库名称,类型为字符串。此参数用于指定要更新文档的知识库。
|
||||
- `docs`: 要更新的文档内容,类型为字典,形如 `{id: Document, ...}`。字典的键为文档的 ID,值为 `Document` 对象。
|
||||
|
||||
**代码描述**:
|
||||
`update_docs_by_id` 函数首先通过 `KBServiceFactory.get_service_by_name` 方法,根据传入的知识库名称 `knowledge_base_name` 获取对应的知识库服务实例。如果指定的知识库不存在,函数将返回一个 `BaseResponse` 对象,其 `code` 属性设置为500,`msg` 属性表示指定的知识库不存在的错误信息。如果知识库存在,函数将调用知识库服务实例的 `update_doc_by_ids` 方法,尝试更新传入的文档。如果更新成功,函数返回一个 `BaseResponse` 对象,其 `msg` 属性表示文档更新成功的信息;如果更新失败,返回的 `BaseResponse` 对象的 `msg` 属性将表示文档更新失败的信息。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的 `knowledge_base_name` 在系统中存在,否则将无法找到对应的知识库进行操作。
|
||||
- `docs` 参数中的 `Document` 对象应包含要更新的文档内容。确保文档 ID 与知识库中现有文档的 ID 匹配,以便正确更新。
|
||||
- 此函数的执行结果(成功或失败)将通过返回的 `BaseResponse` 对象的 `msg` 属性反馈。因此,调用此函数后应检查返回值,以确认操作结果。
|
||||
|
||||
**输出示例**:
|
||||
如果指定的知识库名称不存在,函数可能返回如下的 `BaseResponse` 对象:
|
||||
```python
|
||||
BaseResponse(code=500, msg="指定的知识库 不存在")
|
||||
```
|
||||
如果文档更新成功,函数将返回:
|
||||
```python
|
||||
BaseResponse(msg="文档更新成功")
|
||||
```
|
||||
如果文档更新失败,函数将返回:
|
||||
```python
|
||||
BaseResponse(msg="文档更新失败")
|
||||
```
|
||||
|
||||
此函数是项目中知识库管理功能的一部分,允许通过 API 直接根据文档 ID 更新知识库中的文档内容。它在 `server/api.py` 文件中通过 `mount_knowledge_routes` 函数注册为 API 路由,使得前端或其他服务可以通过发送 HTTP 请求来调用此功能,实现知识库文档的更新操作。
|
||||
## FunctionDef list_files(knowledge_base_name)
|
||||
**list_files**: 此函数用于列出指定知识库中的所有文件名。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 字符串类型,表示要查询文件列表的知识库名称。
|
||||
|
||||
**代码描述**: `list_files` 函数首先验证传入的知识库名称的合法性,如果名称不合法(例如包含潜在的安全风险字符),则返回一个403状态码和错误信息。之后,函数对知识库名称进行URL解码处理,以确保能够正确处理经过URL编码的知识库名称。接着,通过 `KBServiceFactory.get_service_by_name` 方法获取对应知识库的服务实例。如果该知识库不存在,则返回一个404状态码和错误信息。如果知识库存在,函数将调用知识库服务实例的 `list_files` 方法获取所有文件名,并将这些文件名作为数据返回给客户端。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,需要确保传入的知识库名称是经过URL编码的,以避免潜在的URL解析错误。
|
||||
- 此函数依赖于 `KBServiceFactory.get_service_by_name` 方法来获取知识库服务实例,因此需要确保知识库名称在系统中是存在的。
|
||||
- 返回的文件名列表是通过 `ListResponse` 类封装的,这意味着除了文件名列表数据外,还会包含响应的状态码和状态消息。
|
||||
|
||||
**输出示例**:
|
||||
假设存在一个名为 "技术文档库" 的知识库,其中包含三个文件 "doc1.docx", "doc2.pdf", "doc3.txt",调用 `list_files("技术文档库")` 将返回如下响应体:
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": ["doc1.docx", "doc2.pdf", "doc3.txt"]
|
||||
}
|
||||
```
|
||||
如果传入的知识库名称不合法或知识库不存在,将返回相应的错误状态码和消息,例如:
|
||||
```
|
||||
{
|
||||
"code": 403,
|
||||
"msg": "Don't attack me",
|
||||
"data": []
|
||||
}
|
||||
```
|
||||
或
|
||||
```
|
||||
{
|
||||
"code": 404,
|
||||
"msg": "未找到知识库 技术文档库",
|
||||
"data": []
|
||||
}
|
||||
```
|
||||
## FunctionDef _save_files_in_thread(files, knowledge_base_name, override)
|
||||
**_save_files_in_thread**: 该函数的功能是通过多线程将上传的文件保存到对应知识库目录内。
|
||||
|
||||
**参数**:
|
||||
- `files`: 一个`UploadFile`对象列表,表示需要保存的文件。
|
||||
- `knowledge_base_name`: 字符串,指定要保存文件的知识库名称。
|
||||
- `override`: 布尔值,指示如果文件已存在是否覆盖原文件。
|
||||
|
||||
**代码描述**:
|
||||
`_save_files_in_thread`函数主要通过内部定义的`save_file`函数来处理单个文件的保存逻辑。对于每个上传的文件,它会首先检查目标路径是否存在同名文件,如果存在且不允许覆盖,或者文件大小相同,则记录一条警告日志并返回一个包含错误代码404的字典。如果文件不存在或允许覆盖,函数会创建必要的目录结构,并将文件内容写入目标路径。在写入文件的过程中,如果遇到异常,则记录一条错误日志并返回一个包含错误代码500的字典。
|
||||
|
||||
此函数使用`run_in_thread_pool`来并发执行`save_file`函数,以提高文件保存的效率。`run_in_thread_pool`接受一个函数和一个参数列表,其中每个参数都是一个字典,包含了`save_file`所需的参数。这样,`_save_files_in_thread`可以同时处理多个文件的保存操作,每个文件的保存操作在一个独立的线程中执行。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,需要确保`knowledge_base_name`是有效的,且对应的知识库目录具有写入权限。
|
||||
- 由于使用了多线程,需要注意线程安全问题,尤其是在写文件和创建目录时。
|
||||
- 函数返回一个生成器,每次迭代返回一个文件的保存结果,因此调用此函数时需要适当处理这些结果。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "成功上传文件 example.txt",
|
||||
"data": {
|
||||
"knowledge_base_name": "sample_kb",
|
||||
"file_name": "example.txt"
|
||||
}
|
||||
}
|
||||
```
|
||||
此示例展示了一个成功保存文件的返回值,其中包含了状态码、消息以及文件的相关信息。
|
||||
### FunctionDef save_file(file, knowledge_base_name, override)
|
||||
**save_file**: 此函数的功能是保存上传的单个文件到指定的知识库中。
|
||||
|
||||
**参数**:
|
||||
- file: UploadFile类型,表示需要上传的文件。
|
||||
- knowledge_base_name: 字符串类型,表示目标知识库的名称。
|
||||
- override: 布尔类型,指示如果文件已存在是否覆盖原文件。
|
||||
|
||||
**代码描述**:
|
||||
`save_file` 函数首先从上传的文件中提取文件名,并使用 `get_file_path` 函数构造目标文件的存储路径。此路径是基于知识库名称和文件名动态生成的,确保文件能够被正确地保存在对应的知识库目录下。
|
||||
|
||||
函数接着读取上传文件的内容。在尝试保存文件之前,会检查目标路径上的文件是否已存在,以及是否设置了不覆盖已存在文件的选项(`override` 参数)。如果文件已存在且不允许覆盖,函数将记录一条警告日志,并返回一个包含错误代码和消息的字典。
|
||||
|
||||
如果目标文件夹不存在,函数会创建必要的目录结构。然后,以二进制写入模式打开目标文件路径,将上传的文件内容写入其中。
|
||||
|
||||
在文件成功保存后,函数返回一个包含成功代码和消息的字典。如果在文件保存过程中发生异常,函数会捕获异常,记录一条错误日志,并返回一个包含错误代码和消息的字典。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数之前,确保传入的 `file` 参数是一个有效的 `UploadFile` 对象,且 `knowledge_base_name` 参数正确指向一个存在的知识库。
|
||||
- 如果设置 `override` 参数为 `False`,而目标文件已存在且文件大小与上传文件相同,则不会进行文件覆盖,而是返回文件已存在的消息。
|
||||
- 异常处理是此函数的重要组成部分,确保了文件操作过程中的稳定性和可靠性。
|
||||
|
||||
**输出示例**:
|
||||
成功上传文件时,可能的返回值为:
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "成功上传文件 example.docx",
|
||||
"data": {
|
||||
"knowledge_base_name": "my_knowledge_base",
|
||||
"file_name": "example.docx"
|
||||
}
|
||||
}
|
||||
```
|
||||
如果文件已存在且不覆盖,返回值可能为:
|
||||
```
|
||||
{
|
||||
"code": 404,
|
||||
"msg": "文件 example.docx 已存在。",
|
||||
"data": {
|
||||
"knowledge_base_name": "my_knowledge_base",
|
||||
"file_name": "example.docx"
|
||||
}
|
||||
}
|
||||
```
|
||||
在文件上传失败时,返回值可能为:
|
||||
```
|
||||
{
|
||||
"code": 500,
|
||||
"msg": "example.docx 文件上传失败,报错信息为: [具体错误信息]",
|
||||
"data": {
|
||||
"knowledge_base_name": "my_knowledge_base",
|
||||
"file_name": "example.docx"
|
||||
}
|
||||
}
|
||||
```
|
||||
***
|
||||
## FunctionDef upload_docs(files, knowledge_base_name, override, to_vector_store, chunk_size, chunk_overlap, zh_title_enhance, docs, not_refresh_vs_cache)
|
||||
**upload_docs**: 此函数用于上传文件到知识库,并可选择进行文件的向量化处理。
|
||||
|
||||
**参数**:
|
||||
- `files`: 上传的文件列表,支持多文件上传。
|
||||
- `knowledge_base_name`: 知识库名称,指定要上传文件的目标知识库。
|
||||
- `override`: 布尔值,指示是否覆盖已有文件。
|
||||
- `to_vector_store`: 布尔值,指示上传文件后是否进行向量化处理。
|
||||
- `chunk_size`: 知识库中单段文本的最大长度。
|
||||
- `chunk_overlap`: 知识库中相邻文本的重合长度。
|
||||
- `zh_title_enhance`: 布尔值,指示是否开启中文标题加强功能。
|
||||
- `docs`: 自定义的docs,需转为json字符串格式。
|
||||
- `not_refresh_vs_cache`: 布尔值,指示是否暂不保存向量库(用于FAISS)。
|
||||
|
||||
**代码描述**:
|
||||
函数首先验证知识库名称的合法性,如果不合法,则返回403状态码并提示错误信息。接着,根据知识库名称获取对应的知识库服务实例。如果实例获取失败,则返回404状态码并提示未找到知识库。
|
||||
|
||||
函数继续执行,将上传的文件保存到磁盘,并记录保存失败的文件。对于需要进行向量化处理的文件,函数将调用`update_docs`函数进行处理,并更新失败文件列表。如果`not_refresh_vs_cache`为`False`,则会保存向量库。
|
||||
|
||||
最后,函数返回包含操作结果的响应,其中包括失败文件列表。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的知识库名称在系统中已存在。
|
||||
- 上传的文件将被保存到指定的知识库目录中,如果`override`参数为`False`,则不会覆盖已存在的同名文件。
|
||||
- 如果选择进行向量化处理,需要考虑服务器的性能和资源限制。
|
||||
- 自定义的docs需要正确格式化为json字符串,以确保能够被正确解析和处理。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "文件上传与向量化完成",
|
||||
"data": {
|
||||
"failed_files": {
|
||||
"error_file.txt": "文件保存失败的错误信息"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
此示例展示了函数执行成功的情况,其中`failed_files`字段列出了处理失败的文件及其错误信息。
|
||||
## FunctionDef delete_docs(knowledge_base_name, file_names, delete_content, not_refresh_vs_cache)
|
||||
**delete_docs**: 此函数用于从知识库中删除指定的文件。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库的名称,类型为字符串,示例值为["samples"]。
|
||||
- `file_names`: 需要删除的文件名称列表,类型为字符串列表,示例值为[["file_name.md", "test.txt"]]。
|
||||
- `delete_content`: 布尔值,指定是否从磁盘中删除文件内容,默认为`False`。
|
||||
- `not_refresh_vs_cache`: 布尔值,指定是否暂不保存向量库(用于FAISS),默认为`False`,描述为"暂不保存向量库(用于FAISS)"。
|
||||
|
||||
**代码描述**:
|
||||
函数首先验证知识库名称的合法性,如果不合法,则返回403状态码和错误消息"Don't attack me"。之后,对知识库名称进行URL解码,并尝试获取对应的知识库服务实例。如果知识库服务实例不存在,则返回404状态码和错误消息,指出未找到知识库。
|
||||
|
||||
对于每个指定的文件名,函数检查文件是否存在于知识库中。如果文件不存在,将其添加到失败文件列表中。对于存在的文件,尝试删除文件,包括从知识库中删除记录和可选的从磁盘中删除文件内容。如果删除过程中发生异常,将异常信息记录到失败文件列表中,并记录错误日志。
|
||||
|
||||
如果`not_refresh_vs_cache`为`False`,则调用`save_vector_store`方法保存向量库。最后,函数返回200状态码和包含失败文件列表的响应。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的知识库名称和文件名列表正确,且知识库存在。
|
||||
- `delete_content`参数应谨慎使用,因为一旦从磁盘删除文件内容,该操作是不可逆的。
|
||||
- `not_refresh_vs_cache`参数用于控制是否立即保存向量库的状态,这在批量删除文件时可以用来优化性能。
|
||||
|
||||
**输出示例**:
|
||||
如果所有指定的文件都成功删除,且没有需要刷新的向量库,函数可能返回如下响应:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "文件删除完成",
|
||||
"data": {
|
||||
"failed_files": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
如果存在未找到或删除失败的文件,响应中的`failed_files`将包含这些文件的名称和相关错误信息。
|
||||
## FunctionDef update_info(knowledge_base_name, kb_info)
|
||||
**update_info**: 此函数用于更新知识库的介绍信息。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库的名称,类型为字符串。此参数是必需的,用于指定要更新介绍信息的知识库。
|
||||
- `kb_info`: 知识库的介绍信息,类型为字符串。此参数是必需的,用于提供新的知识库介绍。
|
||||
|
||||
**代码描述**:
|
||||
首先,`update_info` 函数通过调用 `validate_kb_name` 函数验证传入的知识库名称是否合法。如果知识库名称不合法(例如包含潜在的安全风险字符),函数将返回一个状态码为403的 `BaseResponse` 对象,消息为"Don't attack me",表示请求被拒绝。
|
||||
|
||||
如果知识库名称验证通过,函数接着尝试通过 `KBServiceFactory.get_service_by_name` 方法获取对应知识库的服务实例。如果指定的知识库不存在(即服务实例为None),函数将返回一个状态码为404的 `BaseResponse` 对象,消息为"未找到知识库 {knowledge_base_name}",表示未找到指定的知识库。
|
||||
|
||||
当知识库服务实例成功获取后,函数调用该实例的 `update_info` 方法,传入新的知识库介绍信息 `kb_info` 进行更新。
|
||||
|
||||
最后,函数返回一个状态码为200的 `BaseResponse` 对象,消息为"知识库介绍修改完成",并在数据字段中返回更新后的知识库介绍信息,表示知识库介绍信息更新成功。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的知识库名称在系统中已存在且合法,否则可能会导致更新失败。
|
||||
- 更新知识库介绍信息的操作可能会受到知识库服务实例类型的限制,确保知识库服务支持信息更新操作。
|
||||
|
||||
**输出示例**:
|
||||
如果更新操作成功,函数可能返回如下的 `BaseResponse` 对象示例:
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "知识库介绍修改完成",
|
||||
"data": {
|
||||
"kb_info": "这是一个更新后的知识库介绍"
|
||||
}
|
||||
}
|
||||
```
|
||||
如果知识库名称不合法,返回的 `BaseResponse` 对象示例可能如下:
|
||||
```
|
||||
{
|
||||
"code": 403,
|
||||
"msg": "Don't attack me",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
如果未找到指定的知识库,返回的 `BaseResponse` 对象示例可能如下:
|
||||
```
|
||||
{
|
||||
"code": 404,
|
||||
"msg": "未找到知识库 {knowledge_base_name}",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
## FunctionDef update_docs(knowledge_base_name, file_names, chunk_size, chunk_overlap, zh_title_enhance, override_custom_docs, docs, not_refresh_vs_cache)
|
||||
**update_docs**: 此函数用于更新知识库中的文档。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库名称,字符串类型,必填参数。
|
||||
- `file_names`: 文件名称列表,支持多文件,列表中每个元素为字符串类型。
|
||||
- `chunk_size`: 知识库中单段文本最大长度,整数类型。
|
||||
- `chunk_overlap`: 知识库中相邻文本重合长度,整数类型。
|
||||
- `zh_title_enhance`: 是否开启中文标题加强,布尔类型。
|
||||
- `override_custom_docs`: 是否覆盖之前自定义的docs,布尔类型,默认为False。
|
||||
- `docs`: 自定义的docs,需要转为json字符串,字典类型。
|
||||
- `not_refresh_vs_cache`: 暂不保存向量库(用于FAISS),布尔类型,默认为False。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先验证传入的知识库名称是否合法,如果不合法,则返回403状态码和错误信息。接着,通过知识库名称获取对应的知识库服务实例。如果实例获取失败,则返回404状态码和错误信息。
|
||||
|
||||
函数继续执行,生成需要加载docs的文件列表。对于每个文件,首先检查该文件是否使用了自定义docs,如果是且不覆盖自定义docs,则跳过该文件。否则,尝试将文件添加到待处理列表中。如果在此过程中出现异常,则记录错误信息。
|
||||
|
||||
接下来,函数将文件列表中的文件转换为docs,并进行向量化处理。这一步骤利用多线程在后台执行,以提高处理效率。处理完成后,如果指定了不刷新向量库缓存,则不立即保存向量库;否则,调用知识库服务的`save_vector_store`方法保存向量库。
|
||||
|
||||
最后,函数返回200状态码和处理结果,包括处理失败的文件列表。
|
||||
|
||||
**注意**:
|
||||
- 在使用此函数时,确保传入的知识库名称在系统中已存在。
|
||||
- 如果需要对文件进行自定义docs处理,确保`docs`参数格式正确,并且文件名与`file_names`中的文件名匹配。
|
||||
- 此函数支持批量处理文件,但需要注意服务器资源和性能限制。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "更新文档完成",
|
||||
"data": {
|
||||
"failed_files": {
|
||||
"error_file.txt": "加载文档时出错"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
此示例展示了函数执行成功的情况,其中`failed_files`字段列出了处理失败的文件及其错误信息。
|
||||
## FunctionDef download_doc(knowledge_base_name, file_name, preview)
|
||||
**download_doc**: 此函数用于下载知识库中的文档。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库名称,用于指定从哪个知识库下载文档。
|
||||
- `file_name`: 文件名称,指定要下载的文件名。
|
||||
- `preview`: 是否预览,布尔值,指示用户是希望在浏览器中预览文件还是直接下载文件。
|
||||
|
||||
**代码描述**:
|
||||
`download_doc` 函数首先通过调用 `validate_kb_name` 函数验证传入的知识库名称是否合法。如果知识库名称不合法,函数将返回一个带有403状态码的 `BaseResponse` 对象,提示用户不要进行攻击。接着,函数尝试通过 `KBServiceFactory.get_service_by_name` 方法获取对应知识库的服务实例。如果找不到对应的知识库服务实例,将返回一个带有404状态码的 `BaseResponse` 对象,提示未找到指定的知识库。
|
||||
|
||||
根据 `preview` 参数的值,函数设置 `content_disposition_type`。如果 `preview` 为 `True`,则设置为 `"inline"`,允许在浏览器中预览文件;否则,`content_disposition_type` 为 `None`,表示文件将被下载。
|
||||
|
||||
然后,函数创建一个 `KnowledgeFile` 实例,用于表示和处理知识库中的文件。如果文件存在于磁盘上,函数将返回一个 `FileResponse` 对象,允许用户下载或预览文件。如果在尝试读取文件时发生异常,函数将记录错误信息并返回一个带有500状态码的 `BaseResponse` 对象,提示读取文件失败。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的知识库名称和文件名称是正确的。
|
||||
- 如果知识库名称不合法或文件不存在,函数将返回错误响应。
|
||||
- 此函数支持文件预览和下载功能,通过 `preview` 参数控制。
|
||||
|
||||
**输出示例**:
|
||||
假设存在一个名为 "samples" 的知识库,其中包含一个名为 "test.txt" 的文件。如果调用 `download_doc(knowledge_base_name="samples", file_name="test.txt", preview=False)`,函数将返回一个 `FileResponse` 对象,允许用户下载 "test.txt" 文件。如果指定的文件不存在,将返回一个带有404状态码的 `BaseResponse` 对象,提示未找到文件。
|
||||
## FunctionDef recreate_vector_store(knowledge_base_name, allow_empty_kb, vs_type, embed_model, chunk_size, chunk_overlap, zh_title_enhance, not_refresh_vs_cache)
|
||||
**recreate_vector_store**: 该函数用于根据内容文件夹中的文档重建向量库。
|
||||
|
||||
**参数**:
|
||||
- `knowledge_base_name`: 知识库名称,类型为字符串,默认示例为“samples”。
|
||||
- `allow_empty_kb`: 是否允许空的知识库,布尔类型,默认为True。
|
||||
- `vs_type`: 向量库类型,字符串类型,默认值为`DEFAULT_VS_TYPE`。
|
||||
- `embed_model`: 嵌入模型名称,字符串类型,默认值为`EMBEDDING_MODEL`。
|
||||
- `chunk_size`: 知识库中单段文本的最大长度,整数类型,默认值为`CHUNK_SIZE`。
|
||||
- `chunk_overlap`: 知识库中相邻文本的重合长度,整数类型,默认值为`OVERLAP_SIZE`。
|
||||
- `zh_title_enhance`: 是否开启中文标题加强功能,布尔类型,默认值为`ZH_TITLE_ENHANCE`。
|
||||
- `not_refresh_vs_cache`: 是否暂不保存向量库(用于FAISS),布尔类型,默认为False。
|
||||
|
||||
**代码描述**:
|
||||
`recreate_vector_store`函数主要用于在用户直接将文件复制到内容文件夹而不是通过网络上传输的情况下,从这些内容文件中重建向量库。默认情况下,只有在`info.db`中存在且包含文档文件的知识库才会被返回。通过将`allow_empty_kb`设置为True,可以使该函数也适用于那些在`info.db`中不存在或没有文档的空知识库。函数内部首先尝试获取指定的知识库服务,如果知识库不存在且不允许空的知识库,则返回404错误。如果知识库存在,则清除现有的向量库并重新创建。随后,函数遍历内容文件夹中的所有文件,并将它们转换为文档,同时考虑文本的分块大小、重合长度以及是否开启中文标题加强功能。每处理完一个文件,就会生成一个包含处理状态的JSON对象,并通过生成器返回。如果在添加文件到知识库时出现错误,则记录错误并跳过该文件。最后,如果不是设置为不刷新向量库缓存,则保存向量库。
|
||||
|
||||
在项目中,`recreate_vector_store`函数通过`server/api.py/mount_knowledge_routes`被注册为FastAPI的一个POST路由。这意味着该函数可以通过HTTP POST请求被调用,用于在用户通过其他方式将文件直接放入内容文件夹后,重新构建知识库的向量库。这在管理知识库时特别有用,尤其是在需要批量更新文档内容而不想逐个上传时。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用此函数之前,内容文件夹中的文件格式和内容符合知识库的要求。
|
||||
- 函数的执行时间可能会根据内容文件夹中的文件数量和大小而有很大差异。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "(1 / 10): example.docx",
|
||||
"total": 10,
|
||||
"finished": 1,
|
||||
"doc": "example.docx"
|
||||
}
|
||||
```
|
||||
此JSON对象表示第一个文件处理成功,总共有10个文件需要处理,当前已完成1个。
|
||||
### FunctionDef output
|
||||
**output**: 此函数的功能是重建知识库的向量存储,并输出处理过程中的状态信息。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**:
|
||||
`output` 函数首先通过 `KBServiceFactory.get_service` 方法获取对应知识库的服务实例,该实例根据知识库名称、向量存储类型和嵌入模型来确定。如果指定的知识库不存在且不允许创建空的知识库,则函数会生成并返回一个包含错误代码404和相应错误信息的JSON对象。如果知识库存在,函数会先清除知识库中的向量存储,然后重新创建知识库。
|
||||
|
||||
接下来,函数通过 `list_files_from_folder` 方法列出知识库文件夹中的所有文件,并为每个文件创建一个 `KnowledgeFile` 实例。这些文件实例随后被批量处理,通过 `files2docs_in_thread` 方法将文件内容转换为文档,并添加到知识库中。在文件转换过程中,函数会逐个生成并返回包含处理状态的JSON对象,这些对象包含了处理进度、文件名等信息。
|
||||
|
||||
如果在文件转换过程中遇到错误,函数会记录错误信息并生成包含错误代码500和相应错误信息的JSON对象。所有文件处理完成后,如果不需要刷新向量存储缓存,则会调用 `save_vector_store` 方法保存向量库。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,需要确保 `KBServiceFactory.get_service` 能够根据提供的参数正确返回知识库服务实例。
|
||||
- `list_files_from_folder` 方法用于列出知识库文件夹中的所有文件,确保知识库文件夹路径正确。
|
||||
- `files2docs_in_thread` 方法负责将文件内容转换为文档并添加到知识库中,该过程是多线程执行的,需要注意线程安全问题。
|
||||
- `save_vector_store` 方法用于保存向量库,确保在调用此方法之前,所有需要保存的数据已经正确处理完毕。
|
||||
- 此函数通过生成器返回处理状态信息,调用方需要适当处理这些生成的JSON对象,以实现状态监控或错误处理。
|
||||
***
|
||||
940
markdown_docs/server/knowledge_base/kb_service/base.md
Normal file
@ -0,0 +1,940 @@
|
||||
## FunctionDef normalize(embeddings)
|
||||
**normalize**: 此函数的功能是对输入的嵌入向量进行L2范数归一化处理。
|
||||
|
||||
**参数**:
|
||||
- **embeddings**: 一个列表的列表,其中每个内部列表包含浮点数,代表一个嵌入向量。
|
||||
|
||||
**代码描述**:
|
||||
`normalize`函数接受一个嵌入向量列表作为输入,这些嵌入向量可以是文档或查询的表示。它首先计算每个嵌入向量的L2范数,然后将每个向量的元素分别除以其L2范数,以实现归一化。这个过程确保了所有的嵌入向量都被规范化到单位球上,这在很多向量空间模型中是一个常见的预处理步骤,有助于提高后续处理的效果和稳定性。
|
||||
|
||||
在项目中,`normalize`函数被`EmbeddingsFunAdapter`类中的`embed_documents`、`embed_query`、`aembed_documents`和`aembed_query`方法调用。这些方法分别负责同步和异步地嵌入文档和查询,然后使用`normalize`函数对嵌入结果进行归一化处理。这表明归一化步骤是嵌入过程的一个重要组成部分,无论是处理文档还是查询,都需要进行归一化以确保嵌入向量的质量。
|
||||
|
||||
**注意**:
|
||||
- 输入的嵌入向量列表需要确保每个向量的维度相同,因为归一化过程涉及到按元素的运算。
|
||||
- 该函数依赖于`numpy`库进行矩阵运算,因此在使用前需要确保已经安装了`numpy`。
|
||||
|
||||
**输出示例**:
|
||||
假设输入的嵌入向量列表为`[[1.0, 2.0], [2.0, 3.0]]`,则函数的返回值可能如下所示:
|
||||
```
|
||||
[[0.4472136 0.89442719]
|
||||
[0.5547002 0.83205029]]
|
||||
```
|
||||
这个输出展示了两个经过L2范数归一化的二维向量。
|
||||
## ClassDef SupportedVSType
|
||||
**SupportedVSType**: SupportedVSType的功能是定义支持的向量存储类型。
|
||||
|
||||
**属性**:
|
||||
- FAISS: 代表使用FAISS作为向量存储服务。
|
||||
- MILVUS: 代表使用MILVUS作为向量存储服务。
|
||||
- DEFAULT: 代表使用默认的向量存储服务。
|
||||
- ZILLIZ: 代表使用ZILLIZ作为向量存储服务。
|
||||
- PG: 代表使用PostgreSQL (PG) 作为向量存储服务。
|
||||
- ES: 代表使用Elasticsearch (ES) 作为向量存储服务。
|
||||
- CHROMADB: 代表使用ChromaDB作为向量存储服务。
|
||||
|
||||
**代码描述**:
|
||||
SupportedVSType类是一个枚举类,它定义了在知识库服务中支持的各种向量存储类型。这些类型包括FAISS、MILVUS、ZILLIZ、PostgreSQL、Elasticsearch和ChromaDB等,以及一个默认选项。这个类在项目中的主要作用是在知识库服务工厂(KBServiceFactory)中,根据传入的向量存储类型字符串,动态选择并实例化对应的知识库服务实现。例如,如果指定了FAISS作为向量存储类型,那么KBServiceFactory将实例化并返回一个FaissKBService对象。
|
||||
|
||||
在项目中,SupportedVSType类通过KBServiceFactory的get_service方法被调用,以确定并实例化相应的知识库服务。此外,各个具体的知识库服务类(如FaissKBService、MilvusKBService等)也通过实现vs_type方法,返回其对应的SupportedVSType值,以标识它们支持的向量存储类型。
|
||||
|
||||
**注意**:
|
||||
- 在使用SupportedVSType时,应确保传入的向量存储类型字符串与SupportedVSType中定义的属性名称一致,以避免在动态解析时发生错误。
|
||||
- DEFAULT类型通常用于指定一个默认的向量存储服务,具体实现可能会根据项目配置或环境而变化。
|
||||
- 在扩展项目以支持新的向量存储服务时,应在SupportedVSType中添加相应的属性,并在KBServiceFactory中实现相应的逻辑以支持新的服务类型。
|
||||
## ClassDef KBService
|
||||
**KBService**: KBService 类是用于管理和操作知识库的抽象基类,提供了一系列对知识库进行操作的方法。
|
||||
|
||||
**属性**:
|
||||
- `kb_name`: 知识库名称。
|
||||
- `kb_info`: 知识库信息,如果在`KB_INFO`中找不到对应的知识库名称,则显示为"关于xxx的知识库"。
|
||||
- `embed_model`: 嵌入模型名称,默认为`EMBEDDING_MODEL`。
|
||||
- `kb_path`: 知识库路径。
|
||||
- `doc_path`: 文档路径。
|
||||
|
||||
**代码描述**:
|
||||
KBService 类定义了一系列方法用于管理知识库,包括创建知识库、删除知识库、向知识库添加文档、从知识库删除文档、更新知识库信息、文档搜索等。它是一个抽象基类(ABC),意味着它不能直接实例化,而是需要通过继承它的子类来实现具体的功能。这样的设计允许不同类型的知识库服务(如Faiss、Milvus、Elasticsearch等)实现相同的接口,从而提供一致的操作方式。
|
||||
|
||||
KBService 类在项目中被多个子类继承,每个子类代表一种特定类型的知识库服务,例如`FaissKBService`、`MilvusKBService`等。这些子类实现了KBService类中定义的抽象方法,以适应不同知识库的具体操作需求。
|
||||
|
||||
此外,KBService 类还与`KBServiceFactory`类相关联,`KBServiceFactory`类提供了`get_service`和`get_service_by_name`方法,用于根据知识库名称和向量存储类型动态创建相应的知识库服务实例。这种工厂模式的设计使得在不同知识库服务之间切换变得更加灵活和方便。
|
||||
|
||||
**注意**:
|
||||
- 由于KBService是一个抽象基类,直接实例化KBService会引发错误。应该通过继承KBService并实现其抽象方法的方式来创建子类。
|
||||
- 在使用KBService的子类时,需要确保已经正确配置了知识库的相关信息,如知识库名称、嵌入模型名称等。
|
||||
- 在进行知识库操作(如添加文档、搜索文档等)时,需要注意操作的具体实现可能会依赖于所使用的知识库服务类型。
|
||||
|
||||
**输出示例**:
|
||||
由于KBService是一个抽象基类,它本身不直接产生输出。具体的输出将取决于继承KBService的子类以及实现的方法。例如,一个可能的搜索文档的输出示例为:
|
||||
```python
|
||||
[
|
||||
{"id": "doc1", "text": "文档1的内容", "score": 0.95},
|
||||
{"id": "doc2", "text": "文档2的内容", "score": 0.90}
|
||||
]
|
||||
```
|
||||
这表示在执行搜索操作时,返回了两个文档及其相关性得分。
|
||||
### FunctionDef __init__(self, knowledge_base_name, embed_model)
|
||||
**__init__**: 此函数的功能是初始化KBService类的实例。
|
||||
|
||||
**参数**:
|
||||
- knowledge_base_name: 字符串类型,指定知识库的名称。
|
||||
- embed_model: 字符串类型,默认值为EMBEDDING_MODEL,指定嵌入模型的名称。
|
||||
|
||||
**代码描述**:
|
||||
`__init__` 方法是 `KBService` 类的构造函数,负责初始化该类的实例。在这个方法中,首先将传入的知识库名称(`knowledge_base_name`)赋值给实例变量 `self.kb_name`。然后,使用 `KB_INFO.get` 方法尝试从一个预定义的字典 `KB_INFO` 中获取与 `knowledge_base_name` 对应的知识库信息,如果未找到,则使用默认信息(`"关于{knowledge_base_name}的知识库"`)。接下来,将传入的嵌入模型名称(`embed_model`)赋值给实例变量 `self.embed_model`。
|
||||
|
||||
此外,`__init__` 方法调用了 `get_kb_path` 和 `get_doc_path` 函数,分别用于获取知识库的存储路径和文档存储路径,并将这些路径分别赋值给实例变量 `self.kb_path` 和 `self.doc_path`。这两个函数分别位于 `server/knowledge_base/utils.py` 文件中,`get_kb_path` 函数负责构造并返回知识库的文件路径,而 `get_doc_path` 函数则负责获取知识库文档的存储路径。
|
||||
|
||||
最后,`__init__` 方法调用了 `do_init` 方法,这是一个在 `KBService` 类中定义的方法,用于执行进一步的初始化操作。当前,`do_init` 方法的实现可能为空(使用 `pass` 关键字),但它的存在表明在初始化 `KBService` 实例时可能需要执行的额外步骤或特定的初始化逻辑。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `KBService` 类之前,确保 `KB_INFO` 字典已经被正确定义,且包含了所有可能的知识库名称及其对应的信息。
|
||||
- `EMBEDDING_MODEL` 应为一个有效的嵌入模型名称,默认值应在类或模块的其他部分被定义。
|
||||
- `do_init` 方法的具体实现应根据实际需求进行添加,以完成知识库服务的特定初始化需求。
|
||||
***
|
||||
### FunctionDef __repr__(self)
|
||||
**__repr__**: 此函数的功能是生成对象的官方字符串表示。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `__repr__` 方法是一个特殊方法,用于定义对象的“官方”字符串表示。在 Python 中,当我们尝试使用 `repr()` 函数或者在解释器中直接查询对象时,会调用此方法。在本例中,`__repr__` 方法返回一个格式化的字符串,该字符串包含了两个对象属性:`kb_name` 和 `embed_model`。这意味着当此方法被调用时,它会返回一个包含知识库名称 (`kb_name`) 和嵌入模型 (`embed_model`) 的字符串,两者通过 "@" 符号连接。这种表示方式有助于快速识别对象的关键信息,特别是在调试和日志记录中非常有用。
|
||||
|
||||
**注意**: 使用 `__repr__` 方法时,应确保返回的字符串尽可能明确地反映对象的关键信息。此外,返回的字符串应该尽量遵循 Python 对象表示的惯例,即可能的话,应该能够通过执行这个字符串来重新创建该对象的一个相似实例。
|
||||
|
||||
**输出示例**: 假设一个 `KBService` 对象的 `kb_name` 属性值为 `"KnowledgeBase1"`,`embed_model` 属性值为 `"ModelX"`,那么调用此对象的 `__repr__` 方法将返回字符串 `"KnowledgeBase1 @ ModelX"`。这提供了一个直观的方式来理解对象的主要属性。
|
||||
***
|
||||
### FunctionDef save_vector_store(self)
|
||||
**save_vector_store**: 此函数的功能是保存向量库。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `save_vector_store` 函数是`KBService`类的一个方法,它的主要作用是将向量库的数据持久化保存。在具体实现中,此函数根据不同的向量库类型(如FAISS、Milvus等)采取不同的保存策略。例如,对于FAISS类型的向量库,数据可能会被保存到磁盘上的文件中;而对于Milvus类型的向量库,数据则会被保存到数据库中。需要注意的是,当前代码示例中此函数的实现为空,这意味着具体的保存逻辑需要根据实际的向量库类型和需求来完成。
|
||||
|
||||
在项目中,`save_vector_store`函数被多个地方调用,以确保在进行文档的上传、删除、更新或向量库重建等操作后,向量库的状态能够被正确地保存。这些调用场景包括:
|
||||
|
||||
- 文档上传(`upload_docs`):在上传文档并进行向量化处理后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。
|
||||
- 文档删除(`delete_docs`):在删除指定的文档后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。
|
||||
- 文档更新(`update_docs`):在更新文档内容并进行向量化处理后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。
|
||||
- 向量库重建(`recreate_vector_store`的`output`方法):在重建向量库的过程中,完成所有文档的向量化处理后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。
|
||||
- 数据库文档清理(`prune_db_docs`):在从数据库中删除不存在于本地文件夹中的文档后,保存向量库以确保向量库与数据库的一致性。
|
||||
|
||||
**注意**: 在使用`save_vector_store`函数时,需要根据实际使用的向量库类型(如FAISS、Milvus等)来实现具体的保存逻辑。此外,考虑到向量库可能包含大量数据,保存操作可能会涉及到较大的I/O开销,因此在设计调用此函数的策略时应当考虑到性能影响,合理安排保存向量库的时机。
|
||||
***
|
||||
### FunctionDef create_kb(self)
|
||||
**create_kb**: 此函数的功能是创建知识库。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `create_kb` 方法是 `KBService` 类的一个核心方法,负责知识库的创建流程。该方法首先检查指定的文档路径是否存在,如果不存在,则创建该路径。接着,调用 `do_create_kb` 方法,这是一个预留给开发者的扩展点,允许在知识库创建的基础流程中插入自定义逻辑。之后,该方法会调用 `add_kb_to_db` 函数,将知识库的名称、简介、向量库类型和嵌入模型等信息添加到数据库中。`add_kb_to_db` 函数的执行结果(状态)会被返回,表示知识库创建操作的成功与否。
|
||||
|
||||
在整个创建流程中,`do_create_kb` 方法提供了一个扩展点,允许开发者根据具体需求实现特定的知识库创建逻辑,而 `add_kb_to_db` 函数则负责将知识库信息持久化到数据库中。这种设计模式不仅提高了代码的可扩展性,也确保了知识库创建过程的灵活性和可维护性。
|
||||
|
||||
**注意**:
|
||||
- 在调用 `create_kb` 方法之前,确保已经正确设置了 `KBService` 类的 `doc_path`、`kb_name`、`kb_info`、`vs_type()` 和 `embed_model` 属性,因为这些属性会在知识库创建过程中被使用。
|
||||
- `do_create_kb` 方法默认不执行任何操作,需要在继承 `KBService` 类的子类中根据具体需求重写此方法。
|
||||
- `add_kb_to_db` 函数的调用需要确保传入的知识库名称是唯一的,以避免不必要的信息覆盖。
|
||||
|
||||
**输出示例**: 该方法返回一个布尔值,表示知识库创建操作的成功与否。例如,如果知识库成功创建并添加到数据库中,方法将返回 `True`。
|
||||
***
|
||||
### FunctionDef clear_vs(self)
|
||||
**clear_vs**: 此函数的功能是删除向量库中所有内容。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `clear_vs` 方法是 `KBService` 类的一个成员方法,主要负责清除知识库中的向量数据。该方法首先调用 `do_clear_vs` 方法,执行删除向量数据之前的预处理操作,尽管在当前的实现中,`do_clear_vs` 方法的具体实现为空,但它为未来可能的逻辑扩展提供了接口。接下来,`clear_vs` 方法通过调用 `delete_files_from_db` 函数,传入知识库名称(`self.kb_name`),从数据库中删除与该知识库相关的所有文件记录。`delete_files_from_db` 函数的执行结果(布尔值)将作为 `clear_vs` 方法的返回值,指示操作是否成功完成。
|
||||
|
||||
**注意**:
|
||||
- 在调用 `clear_vs` 方法之前,确保知识库名称已正确设置在 `KBService` 实例的 `kb_name` 属性中。
|
||||
- 该方法会永久删除知识库中的所有文件记录,此操作不可逆,请谨慎使用。
|
||||
- 虽然当前 `do_clear_vs` 方法的实现为空,但开发者在未来的开发中可以在此方法中添加删除向量数据之前需要执行的特定逻辑(如日志记录、数据备份、权限检查等)。
|
||||
|
||||
**输出示例**:
|
||||
如果操作成功完成,`clear_vs` 方法将返回 `True`。例如,在成功删除知识库中所有内容后,方法返回值为:
|
||||
```
|
||||
True
|
||||
```
|
||||
|
||||
此方法在项目中的调用场景包括但不限于知识库的删除操作(`delete_kb` 函数)、知识库向量存储的重建操作(`recreate_vector_store` 函数的 `output` 方法)、以及知识库迁移操作中的向量库重建(`folder2db` 函数)。这些场景均涉及到需要先清除知识库中现有的向量数据,再进行后续的操作,确保知识库的数据状态是最新的。
|
||||
***
|
||||
### FunctionDef drop_kb(self)
|
||||
**drop_kb**: 此函数的功能是删除知识库。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `drop_kb` 方法是 `KBService` 类的一个成员方法,负责实现知识库的删除操作。该方法首先调用 `do_drop_kb` 方法来执行删除知识库的具体逻辑。`do_drop_kb` 方法是一个可由子类实现的方法,用于在删除知识库之前执行特定的逻辑,比如清理相关资源等。接着,`drop_kb` 方法调用 `delete_kb_from_db` 函数,该函数从数据库中删除指定名称的知识库。`delete_kb_from_db` 函数接受一个知识库名称作为参数,并返回一个布尔值,表示操作是否成功。最后,`drop_kb` 方法返回 `delete_kb_from_db` 函数的返回值,作为删除操作的最终状态。
|
||||
|
||||
**注意**:
|
||||
- 在调用 `drop_kb` 方法之前,应确保知识库名称已正确设置在 `KBService` 实例的 `kb_name` 属性中。
|
||||
- `do_drop_kb` 方法在 `KBService` 类中默认不执行任何操作,具体的删除逻辑需要在子类中根据实际需求实现。
|
||||
- 删除知识库的操作不会自动提交数据库事务。调用 `drop_kb` 方法的代码需要根据实际情况决定是否提交事务。
|
||||
|
||||
**输出示例**: 由于 `drop_kb` 方法返回的是 `delete_kb_from_db` 函数的返回值,而该函数始终返回 `True`,因此在成功执行删除操作后,`drop_kb` 方法的返回值将为 `True`。
|
||||
|
||||
在项目中,`drop_kb` 方法的调用场景包括但不限于通过 API 删除知识库、在自动化测试中验证知识库删除功能等。例如,在 `delete_kb` API 方法中,会根据提供的知识库名称创建 `KBService` 实例,并调用其 `drop_kb` 方法来删除知识库。此外,自动化测试 `test_delete_db` 和 `test_drop_kb` 也通过调用 `drop_kb` 方法来测试知识库的删除功能是否正常工作。这些调用示例说明了 `drop_kb` 方法在知识库管理功能中的重要作用,以及如何在不同场景下使用该方法来实现知识库的删除。
|
||||
***
|
||||
### FunctionDef _docs_to_embeddings(self, docs)
|
||||
**_docs_to_embeddings**: 该函数的功能是将文档对象列表转化为向量存储系统可以接受的参数格式。
|
||||
|
||||
**参数**:
|
||||
- `docs`: 需要转化为向量的文档对象列表,类型为`List[Document]`。
|
||||
|
||||
**代码描述**:
|
||||
`_docs_to_embeddings`函数是`KBService`类的一个私有方法,用于将文档对象列表转化为向量形式,以便后续存储或查询操作。该函数内部调用了`embed_documents`函数,传入文档对象列表`docs`、嵌入模型`embed_model`以及一个标志位`to_query`。`embed_model`是`KBService`类的一个属性,指定了用于文档向量化的模型。`to_query`参数在此处被设置为`False`,意味着向量化的结果不是用于查询操作。`embed_documents`函数负责实际的文档向量化过程,包括文本提取、向量化以及元数据处理,最终返回一个包含向量化结果的字典。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`docs`参数是有效的文档对象列表,且每个文档对象都应包含必要的内容和元数据。
|
||||
- `_docs_to_embeddings`函数依赖于`embed_model`属性指定的嵌入模型,因此在使用前应确保嵌入模型已正确设置。
|
||||
- 该函数设计为KBService类的内部方法,不建议直接从类外部调用。
|
||||
|
||||
**输出示例**:
|
||||
调用`_docs_to_embeddings(docs=[Document1, Document2])`可能会返回如下字典:
|
||||
```python
|
||||
{
|
||||
"texts": ["文档1的内容", "文档2的内容"],
|
||||
"embeddings": [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]],
|
||||
"metadatas": [{"title": "文档1标题"}, {"title": "文档2标题"}]
|
||||
}
|
||||
```
|
||||
这个字典包含了文档的原始内容(`texts`)、向量化结果(`embeddings`)以及文档的元数据信息(`metadatas`),为后续的文档存储或查询操作提供了必要的数据结构。
|
||||
***
|
||||
### FunctionDef add_doc(self, kb_file, docs)
|
||||
**add_doc**: 此函数用于向知识库添加文件。
|
||||
|
||||
**参数**:
|
||||
- `kb_file`: `KnowledgeFile`类型的对象,表示要添加到知识库的文件。
|
||||
- `docs`: `Document`类型的列表,默认为空列表。这些是要添加到知识库的文档。
|
||||
- `**kwargs`: 接收额外的关键字参数,这些参数将传递给内部方法。
|
||||
|
||||
**代码描述**:
|
||||
`add_doc`函数首先检查`docs`参数是否已提供。如果提供了`docs`,则将`custom_docs`标志设置为`True`,并为每个文档的元数据中添加`source`字段,其值为`kb_file`的文件名。如果没有提供`docs`,则调用`kb_file`的`file2text`方法将文件内容转换为文档列表,并将`custom_docs`标志设置为`False`。
|
||||
|
||||
接下来,如果`docs`列表不为空,函数会尝试将每个文档的`source`字段中的绝对路径转换为相对于`self.doc_path`的相对路径。然后,调用`delete_doc`方法删除知识库中与`kb_file`相对应的旧文档。
|
||||
|
||||
随后,调用`do_add_doc`方法将文档添加到知识库中,该方法需要在子类中具体实现。`do_add_doc`方法的执行结果(`doc_infos`)将用于调用`add_file_to_db`函数,将文件信息添加到数据库中。此过程中,会根据`custom_docs`标志和文档数量更新数据库中的文件条目。
|
||||
|
||||
最后,函数根据操作结果返回一个状态值,如果文档列表为空,则直接返回`False`。
|
||||
|
||||
**注意**:
|
||||
- 在使用`add_doc`函数时,需要确保传入的`kb_file`对象正确实例化,并且其代表的文件确实存在。
|
||||
- 如果提供了`docs`参数,则这些文档将直接添加到知识库中,不会对文件内容进行向量化处理。
|
||||
- `**kwargs`参数提供了额外的灵活性,允许在不修改`add_doc`函数签名的情况下,传递额外的参数给内部方法。
|
||||
|
||||
**输出示例**:
|
||||
由于`add_doc`函数的主要作用是执行添加操作,其返回值主要用于指示操作是否成功。例如,如果文件成功添加到知识库并更新数据库,函数可能返回`True`。如果在添加过程中遇到任何问题,可能返回`False`。
|
||||
***
|
||||
### FunctionDef delete_doc(self, kb_file, delete_content)
|
||||
**delete_doc**: 此函数的功能是从知识库中删除指定的文件。
|
||||
|
||||
**参数**:
|
||||
- `kb_file`: `KnowledgeFile`类型的对象,表示需要从知识库中删除的文件。
|
||||
- `delete_content`: 布尔值,指定是否从磁盘中删除文件内容。默认为`False`,即不删除文件内容。
|
||||
- `**kwargs`: 接收额外的关键字参数,这些参数将传递给`do_delete_doc`方法。
|
||||
|
||||
**代码描述**:
|
||||
`delete_doc`函数首先调用`do_delete_doc`方法,该方法需要在子类中根据具体逻辑进行实现,用于执行删除文件的自定义操作。随后,函数调用`delete_file_from_db`函数,从数据库中删除指定的知识文件,并更新相关知识库的文件计数。如果`delete_content`参数为`True`,且文件在磁盘上存在,则使用`os.remove`方法从磁盘中删除该文件。最后,函数返回删除操作的状态,该状态由`delete_file_from_db`函数的返回值决定。
|
||||
|
||||
**注意**:
|
||||
- 在调用`delete_doc`函数之前,需要确保传入的`kb_file`对象正确实例化,且其代表的文件确实存在于知识库中。
|
||||
- `delete_content`参数应谨慎使用,因为一旦从磁盘删除文件内容,该操作是不可逆的。
|
||||
- `**kwargs`参数提供了额外的灵活性,允许在不修改`delete_doc`函数签名的情况下,传递额外的参数给`do_delete_doc`方法。
|
||||
|
||||
**输出示例**:
|
||||
由于`delete_doc`函数的主要作用是执行删除操作,其返回值主要用于指示操作是否成功。例如,如果文件成功从数据库和(可选的)磁盘中删除,函数可能返回`True`。如果在删除过程中遇到任何问题,根据`delete_file_from_db`函数的实现,可能返回`False`或抛出异常。
|
||||
***
|
||||
### FunctionDef update_info(self, kb_info)
|
||||
**update_info**: 此函数的功能是更新知识库的介绍信息。
|
||||
|
||||
**参数**:
|
||||
- `kb_info`: 字符串类型,表示要更新的知识库介绍信息。
|
||||
|
||||
**代码描述**:
|
||||
`update_info`函数主要用于更新知识库的介绍信息。它接收一个字符串参数`kb_info`,该参数包含了知识库的新介绍信息。函数首先将这个新的介绍信息赋值给`self.kb_info`,以更新当前知识库服务实例的介绍信息。随后,函数调用`add_kb_to_db`方法,将更新后的知识库信息(包括知识库名称`self.kb_name`、介绍信息`self.kb_info`、向量库类型`self.vs_type()`和嵌入模型`self.embed_model`)添加到数据库中。这里的`self.vs_type()`是通过调用`vs_type`方法获取的,该方法需要在`KBService`类的子类中具体实现,以返回正确的向量库类型。
|
||||
|
||||
`add_kb_to_db`函数负责将知识库信息添加或更新到数据库中。如果数据库中不存在具有相同名称的知识库,则会创建一个新的知识库记录;如果已存在,则更新该知识库的介绍信息、向量库类型和嵌入模型信息。`add_kb_to_db`函数最终返回一个布尔值,表示操作是否成功。
|
||||
|
||||
**注意**:
|
||||
- 在调用`update_info`函数之前,确保知识库名称`self.kb_name`已经正确设置,因为它是更新数据库记录的关键标识。
|
||||
- `vs_type`方法需要在`KBService`类的子类中实现,以确保能够提供正确的向量库类型信息。
|
||||
- 调用`update_info`函数后,需要根据`add_kb_to_db`函数的返回值来判断更新操作是否成功。
|
||||
|
||||
**输出示例**:
|
||||
由于`update_info`函数的返回值是由`add_kb_to_db`函数决定的,因此在成功更新知识库信息后,`update_info`函数将返回`True`。例如,如果更新操作成功完成,函数调用将返回`True`。
|
||||
***
|
||||
### FunctionDef update_doc(self, kb_file, docs)
|
||||
**update_doc**: 此函数用于使用指定的文件更新知识库中的文档。
|
||||
|
||||
**参数**:
|
||||
- `kb_file`: `KnowledgeFile`类型的对象,表示要更新的知识库文件。
|
||||
- `docs`: `Document`类型的列表,表示自定义的文档列表。默认为空列表。
|
||||
- `**kwargs`: 接收额外的关键字参数,这些参数将传递给内部的`delete_doc`和`add_doc`方法。
|
||||
|
||||
**代码描述**:
|
||||
`update_doc`函数首先检查`kb_file`指定的文件路径是否存在。如果文件存在,则调用`delete_doc`方法删除知识库中与该文件对应的旧文档。随后,调用`add_doc`方法将新的文档添加到知识库中。如果在调用过程中指定了`docs`参数,则这些自定义文档将被添加到知识库中,并且数据库中对应的条目会被标记为`custom_docs=True`,表示这些文档是自定义的。如果没有指定`docs`,则`add_doc`方法会根据`kb_file`中的文件内容生成文档并添加到知识库中。
|
||||
|
||||
**注意**:
|
||||
- 在使用`update_doc`函数时,需要确保传入的`kb_file`对象已正确初始化,并且其代表的文件确实存在于磁盘上。
|
||||
- 如果提供了`docs`参数,则这些文档将直接添加到知识库中,而不会对`kb_file`中的文件内容进行再次处理或向量化。
|
||||
- `**kwargs`参数提供了额外的灵活性,允许在不修改`update_doc`函数签名的情况下,传递额外的参数给`delete_doc`和`add_doc`方法。
|
||||
|
||||
**输出示例**:
|
||||
由于`update_doc`函数的主要作用是更新知识库中的文档,其没有直接的返回值。但是,通过调用`delete_doc`和`add_doc`方法,可以间接获得关于删除和添加操作的状态。例如,如果文档成功删除并添加到知识库,则这两个方法可能会返回操作成功的状态值。如果在更新过程中遇到任何问题,根据这两个方法的实现,可能会返回错误信息或抛出异常。
|
||||
|
||||
在项目中,`update_doc`函数被`update_docs`方法调用,用于处理来自API请求的知识库文档更新操作。这包括从文件生成文档、处理自定义文档以及更新知识库中的文档向量等任务。通过这种方式,`update_doc`函数在知识库管理系统中扮演了重要的角色,确保知识库内容的准确性和最新性。
|
||||
***
|
||||
### FunctionDef exist_doc(self, file_name)
|
||||
**exist_doc**: 此函数用于检查指定的文件是否已存在于知识库中。
|
||||
|
||||
**参数**:
|
||||
- `file_name`: 字符串类型,表示要检查是否存在的文件名。
|
||||
|
||||
**代码描述**:
|
||||
`exist_doc` 函数通过接收一个文件名 (`file_name`) 作为参数,来检查该文件是否已经存在于知识库中。函数内部首先创建了一个 `KnowledgeFile` 对象,该对象包含了知识库的名称 (`kb_name`) 和文件名 (`file_name`)。然后,调用 `file_exists_in_db` 函数,将这个 `KnowledgeFile` 对象传递给它,以检查数据库中是否存在与之对应的文件记录。如果 `file_exists_in_db` 函数返回 `True`,表示文件已存在于数据库中;如果返回 `False`,则表示文件不存在。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `file_name` 是正确的文件名,并且该文件名不应包含路径信息,只有文件名本身。
|
||||
- `exist_doc` 函数依赖于 `KnowledgeFile` 类和 `file_exists_in_db` 函数,因此在使用前需要确保这些依赖项正确实现且可用。
|
||||
- 此函数不会对数据库进行任何修改操作,仅用于检查文件的存在性。
|
||||
|
||||
**输出示例**:
|
||||
假设知识库中已存在名为 "example.pdf" 的文件,当调用 `exist_doc("example.pdf")` 时,函数将返回 `True`。如果文件 "new_document.txt" 不存在于知识库中,调用 `exist_doc("new_document.txt")` 将返回 `False`。
|
||||
***
|
||||
### FunctionDef list_files(self)
|
||||
**list_files**: 此函数的功能是列出属于特定知识库的所有文件名。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数,但依赖于类实例中的`kb_name`属性。
|
||||
|
||||
**代码描述**: `list_files`函数是`KBService`类的一个方法,它的主要作用是调用`list_files_from_db`函数,以获取属于特定知识库的所有文件名。在调用`list_files_from_db`时,它传递了`self.kb_name`作为参数,这意味着它将列出与当前实例的`kb_name`属性相匹配的所有文件名。`list_files_from_db`函数进一步通过数据库会话查询`KnowledgeFileModel`模型,筛选出`kb_name`字段与给定知识库名称相匹配的记录,并返回这些记录的文件名列表。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用`list_files`方法之前,`KBService`类的实例已正确初始化,并且`kb_name`属性已经被赋予了一个有效的知识库名称。
|
||||
- 此方法的执行结果直接依赖于数据库中的数据,因此确保数据库已正确填充了相关知识库的文件信息。
|
||||
- 由于`list_files_from_db`函数使用了`ilike`方法进行查询,查询对大小写不敏感,但这可能会在某些情况下影响性能。
|
||||
|
||||
**输出示例**: 假设当前实例的`kb_name`属性值为"GeneralKB",并且数据库中存在属于"GeneralKB"的文件名为"document1.pdf"和"report2.docx"的文件,那么调用`list_files`方法将返回以下列表:
|
||||
```
|
||||
["document1.pdf", "report2.docx"]
|
||||
```
|
||||
|
||||
此方法在项目中的使用场景包括但不限于获取知识库文件列表以供进一步处理,如在`get_kb_file_details`方法中获取文件列表以合并文件夹和数据库中的文件信息,在`folder2db`方法中用于确定需要更新或增量添加到数据库的文件列表,以及在测试用例中验证迁移、增量更新或数据库清理操作的正确性。
|
||||
***
|
||||
### FunctionDef count_files(self)
|
||||
**count_files**: 此函数的功能是统计指定知识库中的文件数量。
|
||||
|
||||
**参数**: 此函数不直接接受任何参数,但它依赖于`KBService`类的实例属性。
|
||||
|
||||
**代码描述**: `count_files`方法是`KBService`类的一个成员方法,它的主要作用是调用`count_files_from_db`函数来统计特定知识库中的文件数量。在调用`count_files_from_db`时,它传递了`self.kb_name`作为参数,其中`self.kb_name`是`KBService`类实例化时指定的知识库名称。这意味着`count_files`方法将返回该知识库中的文件总数。`count_files_from_db`函数通过数据库查询来实现此功能,具体地,它使用ORM模型`KnowledgeFileModel`来过滤特定知识库的文件,并计算满足条件的文件数量。
|
||||
|
||||
**注意**: 在使用`count_files`方法时,需要确保`KBService`类的实例已正确初始化,且`kb_name`属性已经被赋予了正确的知识库名称。此外,由于`count_files_from_db`函数使用了不区分大小写的匹配来查找知识库名称,因此在指定知识库名称时应注意其准确性,以避免统计结果的偏差。
|
||||
|
||||
**输出示例**: 假设存在一个名为"DefaultKB"的知识库,且其中包含10个文件。如果`KBService`类的实例的`kb_name`属性被设置为"DefaultKB",那么调用其`count_files`方法将返回整数`10`,表示"DefaultKB"知识库中的文件数量为10。
|
||||
|
||||
通过`count_files`方法,可以方便地获取特定知识库中的文件总数,这对于知识库管理和数据分析等功能是非常有用的。此方法的设计充分考虑了模块化和代码重用,通过与`count_files_from_db`函数的交互,实现了功能的高效执行。
|
||||
***
|
||||
### FunctionDef search_docs(self, query, top_k, score_threshold)
|
||||
**search_docs**: 此函数的功能是在知识库中搜索与查询字符串最相关的文档。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,用户的搜索查询。
|
||||
- `top_k`: 整型,默认值为`VECTOR_SEARCH_TOP_K`,表示返回的最相关文档的最大数量。
|
||||
- `score_threshold`: 浮点型,默认值为`SCORE_THRESHOLD`,表示只有得分高于此阈值的文档才会被返回。
|
||||
|
||||
**代码描述**:
|
||||
`search_docs`方法是`KBService`类中的一个方法,旨在提供一个高层次的接口,用于执行知识库的搜索操作。该方法首先调用`do_search`方法,根据用户提供的查询字符串`query`,返回的最大文档数量`top_k`,以及得分阈值`score_threshold`,执行搜索操作。`do_search`方法负责具体的搜索逻辑,包括查询处理、文档检索和得分计算等。`search_docs`方法通过调用`do_search`,获取搜索结果后,直接将这些结果返回给调用者。这样的设计使得`search_docs`方法可以专注于处理搜索操作的高层次逻辑,如参数的默认值设置,而具体的搜索逻辑则由`do_search`方法负责。
|
||||
|
||||
**注意**:
|
||||
- 在使用`search_docs`方法时,需要注意`query`参数不能为空,且`top_k`和`score_threshold`参数应根据实际需求合理设置,以确保搜索结果的相关性和精确度。
|
||||
- 该方法返回的是一个文档列表,每个文档都是搜索结果中与查询字符串相关性较高的文档。调用方需要根据自己的需求处理这些文档,例如展示给用户。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
Document(id="1", title="文档标题1", content="文档内容1"),
|
||||
Document(id="2", title="文档标题2", content="文档内容2"),
|
||||
...
|
||||
]
|
||||
```
|
||||
在项目中,`search_docs`方法被多个测试用例调用,包括`test_faiss_kb.py`、`test_milvus_db.py`和`test_pg_db.py`中的`test_search_db`函数。这些测试用例通过调用`search_docs`方法,验证不同知识库实现下的搜索功能是否正常工作,确保搜索结果的数量大于0。这表明`search_docs`方法是项目中用于执行知识库搜索操作的关键接口之一,其正确性和性能对于整个知识库服务的质量至关重要。
|
||||
***
|
||||
### FunctionDef get_doc_by_ids(self, ids)
|
||||
**get_doc_by_ids**: 此函数的功能是根据提供的文档ID列表检索对应的文档对象列表。
|
||||
|
||||
**参数**:
|
||||
- ids: 一个字符串列表,包含需要检索的文档的ID。
|
||||
|
||||
**代码描述**:
|
||||
`get_doc_by_ids` 函数是 `KBService` 类的一个方法,旨在根据给定的文档ID列表检索相应的文档对象。当前实现中,此函数返回一个空列表,这意味着它需要进一步的实现来完成其功能。在项目中,此函数被其他对象调用,以实现特定的业务逻辑。
|
||||
|
||||
例如,在 `list_docs` 方法中,通过文件名或元数据检索文档信息后,会使用 `get_doc_by_ids` 方法根据检索到的文档ID获取具体的文档对象。这一过程表明,`get_doc_by_ids` 方法是连接数据库检索与文档对象处理流程的关键一环。
|
||||
|
||||
另一个调用示例是在 `summary_doc_ids_to_vector_store` 函数中,该函数根据文档ID列表,使用 `get_doc_by_ids` 方法获取文档对象,进而进行文档摘要和向量存储的相关处理。这显示了 `get_doc_by_ids` 在文档处理和分析流程中的重要作用。
|
||||
|
||||
**注意**:
|
||||
- 当前函数实现返回一个空列表,这表明需要根据实际的数据库或存储结构来完成此函数的具体实现。
|
||||
- 在使用此函数时,需要确保传入的ID列表中的每个ID都是有效的,并且能够在数据库或存储系统中找到对应的文档。
|
||||
|
||||
**输出示例**:
|
||||
假设函数已经实现,并且数据库中存在对应的文档,那么对于输入 `["doc1", "doc2"]`,一个可能的返回值示例为:
|
||||
```python
|
||||
[
|
||||
Document(id="doc1", title="文档1标题", content="文档1内容"),
|
||||
Document(id="doc2", title="文档2标题", content="文档2内容")
|
||||
]
|
||||
```
|
||||
这个示例展示了函数在成功检索到文档后可能返回的文档对象列表的结构。
|
||||
***
|
||||
### FunctionDef del_doc_by_ids(self, ids)
|
||||
**del_doc_by_ids**: 该函数的功能是根据提供的文档ID列表删除对应的文档。
|
||||
|
||||
**参数**:
|
||||
- ids: 一个字符串列表,包含需要删除的文档的ID。
|
||||
|
||||
**代码描述**:
|
||||
`del_doc_by_ids` 函数接受一个字符串列表作为参数,这个列表包含了需要被删除的文档的ID。函数的主体抛出了一个`NotImplementedError`异常,这表明该函数是一个抽象方法,需要在子类中被具体实现。在当前的上下文中,这个设计模式通常用于定义一个接口,强制继承该类的子类实现这个方法。
|
||||
|
||||
在项目中,`del_doc_by_ids` 函数被`update_doc_by_ids` 方法调用。`update_doc_by_ids` 方法的功能是更新给定ID的文档。如果传入的文档ID对应的文档不存在或者文档的`page_content`为空,则会调用`del_doc_by_ids`方法来删除这些文档。这种设计体现了一种先清理再更新的策略,确保在添加或更新文档之前,移除所有无效或不再需要的文档。
|
||||
|
||||
**注意**:
|
||||
- `del_doc_by_ids` 方法是一个抽象方法,调用时需要注意在具体的子类中实现其功能。
|
||||
- 在使用`del_doc_by_ids`方法之前,确保已经正确处理和筛选了需要删除的文档ID列表,避免误删除重要文档。
|
||||
- 考虑到该方法可能会影响数据库或存储中的数据持久性,实现时应当谨慎处理异常和错误,确保数据的一致性和完整性。
|
||||
***
|
||||
### FunctionDef update_doc_by_ids(self, docs)
|
||||
**update_doc_by_ids**: 此函数的功能是根据文档ID更新或删除文档。
|
||||
|
||||
**参数**:
|
||||
- `docs`: 一个字典,键为文档ID,值为`Document`对象。
|
||||
|
||||
**代码描述**:
|
||||
`update_doc_by_ids` 方法接收一个包含文档ID和对应`Document`对象的字典作为参数。此方法首先调用`del_doc_by_ids`方法,尝试删除所有传入的文档ID对应的文档。随后,方法初始化一个空列表用于存储有效的文档对象和对应的ID。接着,遍历传入的字典,检查每个`Document`对象的有效性:如果`Document`对象为`None`或其`page_content`属性为空(或仅包含空白字符),则该文档被视为无效,不会被添加到有效文档列表中。对于有效的文档,其ID和对象分别被添加到之前初始化的列表中。最后,调用`do_add_doc`方法,将有效的文档重新添加到知识库中。此过程实现了对指定ID的文档进行更新或删除的功能。
|
||||
|
||||
**注意**:
|
||||
- 在调用此方法之前,确保传入的`docs`参数格式正确,即键为文档ID,值为对应的`Document`对象。
|
||||
- 此方法假设`del_doc_by_ids`和`do_add_doc`方法已在子类中具体实现。因此,在使用`update_doc_by_ids`方法之前,需要确保这两个方法能够正常工作。
|
||||
- 由于此方法内部调用了删除和添加文档的操作,可能会对知识库的数据产生重大影响。因此,在生产环境中使用时,应确保充分测试,并考虑实施适当的错误处理和日志记录机制,以便追踪操作结果。
|
||||
|
||||
**输出示例**:
|
||||
调用`update_doc_by_ids`方法总是返回`True`,表示更新操作已被执行。然而,实际上是否成功更新或删除文档,需要依赖于`del_doc_by_ids`和`do_add_doc`方法的具体实现及其返回值。
|
||||
***
|
||||
### FunctionDef list_docs(self, file_name, metadata)
|
||||
**list_docs**: 此函数的功能是通过文件名或元数据检索文档。
|
||||
|
||||
**参数**:
|
||||
- `file_name`: 字符串类型,可选参数,默认为None,指定要查询的文件名称。
|
||||
- `metadata`: 字典类型,可选参数,默认为空字典,用于根据文档的元数据进行过滤查询。
|
||||
|
||||
**代码描述**: `list_docs` 函数首先调用 `list_docs_from_db` 函数,根据提供的知识库名称、文件名和元数据参数从数据库中检索文档信息。检索到的文档信息是一个包含文档ID和元数据的字典列表。随后,函数遍历这个列表,对每个文档ID调用 `get_doc_by_ids` 方法获取具体的文档对象。如果文档对象非空,则创建一个 `DocumentWithVSId` 实例,并将其添加到结果列表中。这个过程允许函数根据文件名或元数据过滤条件,返回一组经过向量化处理的文档对象。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,应确保提供的知识库名称是有效的,以便正确检索文档。
|
||||
- 默认情况下,`metadata` 参数为空字典,如果需要根据特定元数据过滤文档,应显式传入相应的键值对。
|
||||
- 函数处理空文档对象的情况,即如果 `get_doc_by_ids` 方法返回空,则当前迭代会跳过,不会向结果列表中添加任何对象。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在两条记录,其字段值分别为:
|
||||
- id: "docA", metadata: {"author": "张三", "year": "2021"}
|
||||
- id: "docB", metadata: {"author": "李四", "year": "2022"}
|
||||
|
||||
调用 `list_docs(file_name="文件A.pdf")` 可能返回以下列表:
|
||||
```python
|
||||
[
|
||||
DocumentWithVSId(id="docA", metadata={"author": "张三", "year": "2021"}, score=3.0),
|
||||
DocumentWithVSId(id="docB", metadata={"author": "李四", "year": "2022"}, score=3.0)
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数如何根据指定的文件名返回该文件下所有文档的向量化处理对象列表。
|
||||
***
|
||||
### FunctionDef do_create_kb(self)
|
||||
**do_create_kb**: 此函数的功能是创建知识库的子类实现逻辑。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_create_kb` 函数是 `KBService` 类中的一个方法,设计用于被子类重写,以实现特定的知识库创建逻辑。在 `KBService` 类的上下文中,`do_create_kb` 方法提供了一个扩展点,允许开发者在不修改 `create_kb` 方法逻辑的情况下,添加或修改知识库创建时的行为。具体来说,当 `create_kb` 方法被调用时,它首先检查指定的文档路径是否存在,如果不存在则创建该路径。之后,`create_kb` 方法会调用 `do_create_kb`,这一步骤是预留给开发者的扩展点,允许在创建知识库的基础流程中插入自定义逻辑。完成这些步骤后,`create_kb` 方法会继续执行,将知识库信息添加到数据库中,并返回操作的状态。
|
||||
|
||||
在实际使用中,开发者应该通过继承 `KBService` 类并重写 `do_create_kb` 方法来实现特定的知识库创建逻辑。这种设计模式提高了代码的可扩展性和可维护性,允许不同的知识库实现具有不同的创建逻辑,而不必修改公共的 `create_kb` 方法。
|
||||
|
||||
**注意**: `do_create_kb` 方法默认不执行任何操作,因为它是设计给子类用于重写的。如果在不重写此方法的情况下直接使用,它将不会对知识库的创建过程产生任何影响。因此,开发者在使用 `KBService` 类时,需要根据具体需求重写 `do_create_kb` 方法,以实现所需的知识库创建逻辑。
|
||||
***
|
||||
### FunctionDef list_kbs_type
|
||||
**list_kbs_type**: 此函数的功能是列出所有知识库类型。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `list_kbs_type` 函数的主要作用是从一个名为 `kbs_config` 的字典中获取所有的键,并将这些键作为一个列表返回。这里的 `kbs_config` 字典预期包含了不同知识库类型的配置信息,其中字典的键代表了各个知识库的类型。通过调用 `keys()` 方法,我们可以获取到一个包含所有键的视图,然后通过 `list()` 函数将这个视图转换成列表。这样,最终返回的就是一个包含所有知识库类型名称的列表。
|
||||
|
||||
**注意**: 使用此函数时,需要确保 `kbs_config` 字典已经被正确初始化并且包含了至少一个知识库类型的配置信息。如果 `kbs_config` 是空的,那么此函数将返回一个空列表。
|
||||
|
||||
**输出示例**:
|
||||
假设 `kbs_config` 字典如下所示:
|
||||
```python
|
||||
kbs_config = {
|
||||
"type1": {...},
|
||||
"type2": {...},
|
||||
"type3": {...}
|
||||
}
|
||||
```
|
||||
调用 `list_kbs_type()` 函数将返回:
|
||||
```python
|
||||
["type1", "type2", "type3"]
|
||||
```
|
||||
这表示当前配置中存在三种类型的知识库。
|
||||
***
|
||||
### FunctionDef list_kbs(cls)
|
||||
**list_kbs**: 此函数的功能是从数据库中列出满足特定条件的知识库名称列表。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `list_kbs` 函数是 `KBService` 类的一个方法,它通过调用 `list_kbs_from_db` 函数来实现其功能。`list_kbs_from_db` 函数负责从数据库中检索并返回满足特定条件(如文件数量大于某个最小值)的知识库名称列表。`list_kbs` 函数作为一个接口,简化了从数据库获取知识库名称列表的过程,使得其他函数或服务可以轻松地获取这些信息而无需直接与数据库交互。
|
||||
|
||||
**注意**:
|
||||
- `list_kbs` 函数的实现依赖于 `list_kbs_from_db` 函数,因此在使用 `list_kbs` 函数之前,需要确保 `list_kbs_from_db` 函数已正确实现并能够成功从数据库中检索信息。
|
||||
- 此函数不接受任何参数,因此调用时不需要提供额外信息。它将返回数据库中所有符合条件的知识库名称列表,具体的筛选条件(如文件数量的最小值)是在 `list_kbs_from_db` 函数内部定义的。
|
||||
|
||||
**输出示例**: 假设数据库中存在多个知识库,且根据 `list_kbs_from_db` 函数的筛选条件,有两个知识库满足条件。那么 `list_kbs` 函数的返回值可能如下:
|
||||
```
|
||||
['知识库A', '知识库B']
|
||||
```
|
||||
这表示在满足特定条件下,数据库中的知识库A和知识库B被成功检索并返回。
|
||||
|
||||
通过 `list_kbs` 函数,`KBService` 类为其他服务或函数提供了一个简洁的接口来获取数据库中的知识库名称列表,进一步促进了项目中不同组件之间的解耦和协作。
|
||||
***
|
||||
### FunctionDef exists(self, kb_name)
|
||||
**exists**: 此函数的功能是检查指定名称的知识库是否存在。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 可选参数,字符串类型,表示要检查的知识库名称。如果未提供,则使用对象自身的`kb_name`属性。
|
||||
|
||||
**代码描述**:
|
||||
`exists`函数用于判断给定名称的知识库是否存在于数据库中。函数首先检查是否提供了`kb_name`参数,如果没有提供,则使用对象自身的`kb_name`属性作为要检查的知识库名称。然后,函数调用`kb_exists`函数,传入知识库名称作为参数,`kb_exists`函数会查询数据库,检查是否存在具有该名称的知识库。如果存在,则`kb_exists`函数返回`True`,否则返回`False`。最终,`exists`函数返回`kb_exists`的返回值,即表示知识库是否存在的布尔值。
|
||||
|
||||
**注意**:
|
||||
- 在调用`exists`函数时,如果已知知识库名称,可以通过`kb_name`参数直接提供。如果不提供`kb_name`参数,则默认使用对象自身的`kb_name`属性。
|
||||
- 确保在调用此函数之前,对象的`kb_name`属性已正确设置,以避免查询错误的知识库名称。
|
||||
- 此函数的返回值是布尔类型,可以直接用于条件判断,例如在决定是否创建新知识库或执行其他依赖于知识库存在性的操作时。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在名为"技术文档库"的知识库,调用`exists(kb_name="技术文档库")`将返回`True`。如果查询一个不存在的知识库名称,如`exists(kb_name="不存在的库")`,则会返回`False`。
|
||||
|
||||
在项目中,`exists`函数被多个场景调用,包括在重建向量存储、生成知识库摘要向量存储、向知识库添加文档前的存在性检查等。这些调用场景表明,`exists`函数是知识库管理流程中的一个重要环节,用于确保操作的目标知识库确实存在,从而保证数据的一致性和操作的有效性。
|
||||
***
|
||||
### FunctionDef vs_type(self)
|
||||
**vs_type**: 此函数的功能是获取知识库的类型。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `vs_type` 函数设计用于返回一个字符串,该字符串代表知识库的类型。在当前的代码实现中,函数体是空的,这意味着需要由继承`KBService`类的子类来具体实现`vs_type`方法,以返回正确的知识库类型。在项目中,`vs_type`函数被`create_kb`和`update_info`两个方法调用。这两个方法分别用于创建和更新知识库,它们通过调用`vs_type`来获取知识库的类型,并将这个类型信息作为参数之一传递给`add_kb_to_db`函数,以便将知识库的相关信息添加到数据库中。这表明`vs_type`函数在知识库创建和更新流程中扮演着关键的角色,确保了知识库类型的信息能够正确地存储和管理。
|
||||
|
||||
**注意**: 虽然当前`vs_type`函数的实现为空,但在实际使用时,开发者需要在继承`KBService`类的子类中重写此方法,以返回具体的知识库类型。这是因为不同类型的知识库可能需要不同的处理逻辑和存储方式,因此正确地识别和返回知识库的类型对于知识库的管理至关重要。
|
||||
***
|
||||
### FunctionDef do_init(self)
|
||||
**do_init**: 此函数的功能是初始化知识库服务。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_init` 函数是 `KBService` 类的一个方法,目前其内部实现为空(即使用 `pass` 关键字),这意味着它是一个待实现的功能或者是一个占位符。在 `KBService` 类的构造函数 `__init__` 中,`do_init` 被调用,这表明在创建 `KBService` 对象的过程中,`do_init` 函数被设计为完成知识库服务的初始化工作。具体来说,`__init__` 函数首先设置了知识库的名称、知识库信息、嵌入模型、知识库路径和文档路径等属性,然后调用 `do_init` 来进行进一步的初始化操作。虽然当前 `do_init` 函数的实现为空,但它的存在暗示了在知识库服务初始化过程中可能需要执行的额外步骤或者特定的初始化逻辑,这些逻辑在未来可以在 `do_init` 函数中实现。
|
||||
|
||||
**注意**: 虽然当前 `do_init` 函数内部为空,但开发者在未来可能会在此函数中添加具体的初始化逻辑。因此,在修改或扩展 `KBService` 类的功能时,应当考虑到 `do_init` 函数的潜在作用和可能的实现内容。此外,调用 `do_init` 的方式表明它是类初始化过程的一部分,因此任何对 `do_init` 的修改都应当谨慎进行,以避免影响 `KBService` 类对象的正常创建和初始化。
|
||||
***
|
||||
### FunctionDef do_drop_kb(self)
|
||||
**do_drop_kb**: 此函数的功能是执行删除知识库的具体逻辑。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `do_drop_kb` 函数是 `KBService` 类中定义的一个方法,用于实现删除知识库的具体逻辑。在该方法的当前实现中,它仅包含一个 `pass` 语句,这意味着它是一个空方法,需要由继承 `KBService` 类的子类来具体实现删除知识库的逻辑。此方法的设计初衷是允许不同的知识库子类根据自己的需求实现具体的删除逻辑,从而提供了一种灵活的方式来扩展知识库服务的功能。
|
||||
|
||||
在项目中,`do_drop_kb` 方法被 `drop_kb` 方法调用。`drop_kb` 方法的主要职责是删除知识库,它首先调用 `do_drop_kb` 方法来执行特定的删除逻辑,然后调用 `delete_kb_from_db` 函数来从数据库中删除知识库,最后返回操作的状态。这种设计模式允许在删除知识库的过程中插入额外的逻辑,而不仅仅是从数据库中删除记录,从而提供了更大的灵活性和可扩展性。
|
||||
|
||||
**注意**: 由于 `do_drop_kb` 方法在 `KBService` 类中默认不执行任何操作,因此在使用 `KBService` 类或其子类进行知识库删除操作时,需要确保根据具体需求重写 `do_drop_kb` 方法,以实现所需的删除逻辑。此外,开发者在扩展或继承 `KBService` 类时,应当注意保持 `do_drop_kb` 方法与知识库删除流程的一致性和完整性。
|
||||
***
|
||||
### FunctionDef do_search(self, query, top_k, score_threshold)
|
||||
**do_search**: 此函数的功能是执行知识库的搜索操作。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,表示搜索查询的内容。
|
||||
- `top_k`: 整型,指定返回的最相关文档的最大数量。
|
||||
- `score_threshold`: 浮点型,设定的分数阈值,只有得分高于此阈值的文档才会被返回。
|
||||
|
||||
**代码描述**:
|
||||
`do_search`函数是`KBService`类的一个方法,旨在根据给定的查询参数,在知识库中搜索并返回最相关的文档。该方法接受三个参数:`query`为用户的查询字符串,`top_k`限定了返回结果的数量,而`score_threshold`则是过滤结果的得分阈值,只有当文档的相关性得分超过这个阈值时,该文档才会被考虑为搜索结果的一部分。函数返回一个列表,列表中的每个元素是一个元组,包含一个文档和该文档的得分。
|
||||
|
||||
在项目中,`do_search`方法被`search_docs`方法调用。`search_docs`方法同样位于`KBService`类中,它提供了一个更高层次的接口,用于执行搜索操作。`search_docs`方法通过调用`do_search`,利用其提供的底层搜索逻辑,然后返回搜索结果。这种设计允许`do_search`方法专注于执行搜索逻辑,而`search_docs`方法则处理与搜索相关的其他逻辑,如参数的默认值设置等。
|
||||
|
||||
**注意**:
|
||||
- `do_search`方法是一个抽象方法,意味着它需要在子类中被具体实现。在不同的知识库实现中,根据具体的搜索需求和知识库的结构,`do_search`方法的实现可能会有所不同。
|
||||
- 调用此方法时,需要确保传入的参数类型和值是正确的,特别是`top_k`和`score_threshold`,这两个参数直接影响搜索结果的质量和数量。
|
||||
- 由于`do_search`方法返回的是包含文档和得分的元组列表,因此调用方需要根据自己的需求处理这些结果,例如展示给用户等。
|
||||
***
|
||||
### FunctionDef do_add_doc(self, docs)
|
||||
**do_add_doc**: 此函数的功能是向知识库添加文档。
|
||||
|
||||
**参数**:
|
||||
- `docs`: 需要添加到知识库中的文档列表,类型为`List[Document]`。
|
||||
- `**kwargs`: 接受可变数量的关键字参数,用于扩展或自定义功能。
|
||||
|
||||
**代码描述**:
|
||||
`do_add_doc`函数是`KBService`类的一个方法,设计用于将文档添加到知识库中。该方法接受一个文档列表`docs`作为参数,每个文档都是`Document`类型的实例,此外还可以接受多个关键字参数`**kwargs`,以提供更多的灵活性和扩展性。函数体内的具体实现逻辑需要由子类根据具体需求来完成,因为在基类中,此方法仅以`pass`占位,暗示这是一个待子类实现的抽象方法。
|
||||
|
||||
在项目中,`do_add_doc`方法被`add_doc`和`update_doc_by_ids`两个方法调用。`add_doc`方法用于向知识库添加文件,如果指定了`docs`参数,则直接调用`do_add_doc`方法添加这些文档,而不再进行文本向量化处理;`update_doc_by_ids`方法则是用于根据文档ID更新知识库中的文档,如果文档内容有效,则会调用`do_add_doc`方法重新添加这些文档。这两种调用方式都体现了`do_add_doc`方法在知识库文档管理中的核心作用,即作为一个接口,允许不同的上层逻辑向知识库中添加或更新文档。
|
||||
|
||||
**注意**:
|
||||
- 由于`do_add_doc`方法在基类中没有具体实现,因此在使用时需要确保其子类已经根据具体的业务逻辑重写了这个方法。
|
||||
- 调用此方法时,需要确保传入的`docs`参数是一个`Document`类型的实例列表,且每个实例都应该包含了要添加到知识库的文档信息。
|
||||
- 通过`**kwargs`参数,可以灵活地为方法传入额外的参数,但使用时应注意检查子类实现中对这些参数的处理逻辑,以避免出现意外的行为。
|
||||
***
|
||||
### FunctionDef do_delete_doc(self, kb_file)
|
||||
**do_delete_doc**: 此函数的功能是从知识库中删除指定的文档。
|
||||
|
||||
**参数**:
|
||||
- `kb_file`: 表示要删除的知识库文件的KnowledgeFile对象。
|
||||
|
||||
**代码描述**: `do_delete_doc`函数是KBService类中用于删除知识库中文档的方法。它接收一个KnowledgeFile类型的参数`kb_file`,该参数封装了需要删除的文件的相关信息。此函数的实现需要子类根据具体逻辑进行重写。在当前的实现中,函数体内部仅包含一个`pass`语句,意味着默认情况下此函数不执行任何操作。实际的删除逻辑应由继承KBService类的子类根据具体需求实现。
|
||||
|
||||
**注意**:
|
||||
- 在使用`do_delete_doc`函数时,需要确保传入的`kb_file`参数正确实例化,且其代表的文件确实存在于知识库中。否则,可能无法正确执行删除操作。
|
||||
- 由于`do_delete_doc`函数默认不执行任何操作,开发者需要在子类中重写此方法,添加具体的删除逻辑。
|
||||
- 此函数通常与`delete_doc`方法配合使用。`delete_doc`方法调用`do_delete_doc`进行文件的删除操作,并根据参数决定是否从磁盘和数据库中删除文件内容。这意味着`do_delete_doc`负责执行删除操作的自定义部分,而`delete_doc`则处理更广泛的删除流程,包括可选的从磁盘删除文件和更新数据库状态。
|
||||
***
|
||||
### FunctionDef do_clear_vs(self)
|
||||
**do_clear_vs**: 此函数的功能是从知识库删除全部向量子类实自己逻辑。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `do_clear_vs` 函数是 `KBService` 类中的一个方法,其主要作用是在知识库服务中执行删除所有向量数据的前置逻辑。具体来说,该函数被设计为在删除向量库中所有内容之前,执行必要的清理或准备工作。然而,根据提供的代码片段,`do_clear_vs` 方法的实现目前为空(使用了 `pass` 语句),这意味着它没有执行任何操作。这可能表明该方法是为了未来可能的扩展而保留的,或者是等待进一步的实现。
|
||||
|
||||
在项目中,`do_clear_vs` 方法被 `clear_vs` 方法调用。`clear_vs` 方法的文档说明了其功能是“删除向量库中所有内容”。在执行具体的删除操作之前,`clear_vs` 首先调用 `do_clear_vs` 方法。这表明 `do_clear_vs` 方法的设计初衷是作为执行实际删除操作前的一个预处理步骤。在 `do_clear_vs` 方法调用之后,`clear_vs` 方法继续调用 `delete_files_from_db` 函数,传入知识库名称作为参数,来完成向量库中所有内容的删除操作,并返回操作的状态。
|
||||
|
||||
**注意**: 虽然当前 `do_clear_vs` 方法的实现为空,但在未来的开发中,如果需要在删除向量数据之前执行特定的逻辑(如日志记录、数据备份、权限检查等),可以在此方法中添加相应的代码。因此,开发者在使用或修改此方法时,应考虑到其在整个删除流程中的定位和作用,避免破坏已有的调用关系和逻辑顺序。
|
||||
***
|
||||
## ClassDef KBServiceFactory
|
||||
**KBServiceFactory**: KBServiceFactory 类的功能是提供一个静态方法工厂,用于根据不同的参数创建并返回不同类型的知识库服务实例。
|
||||
|
||||
**属性**:该类没有定义属性,所有功能都通过静态方法实现。
|
||||
|
||||
**代码描述**:
|
||||
KBServiceFactory 类提供了三个静态方法,分别用于根据不同的条件获取知识库服务实例。
|
||||
|
||||
1. `get_service` 方法接受知识库名称(kb_name)、向量存储类型(vector_store_type)、嵌入模型名称(embed_model)作为参数。该方法首先会检查向量存储类型是否为字符串,如果是,则将其转换为 `SupportedVSType` 枚举类型。根据向量存储类型的不同,方法会动态导入并返回对应的知识库服务实例,如 FaissKBService、PGKBService、MilvusKBService 等。这些服务实例都继承自 KBService 基类,但具体实现根据向量存储的不同而有所差异。
|
||||
|
||||
2. `get_service_by_name` 方法接受知识库名称(kb_name)作为参数,通过调用数据库加载函数 `load_kb_from_db` 来获取知识库的向量存储类型和嵌入模型名称,然后调用 `get_service` 方法来获取对应的知识库服务实例。如果数据库中不存在该知识库,则返回 None。
|
||||
|
||||
3. `get_default` 方法不接受任何参数,直接返回一个默认向量存储类型为 `SupportedVSType.DEFAULT` 的知识库服务实例。
|
||||
|
||||
在项目中,KBServiceFactory 被多个模块调用,用于创建、删除、更新、搜索知识库中的文档,以及上传和下载文档等操作。例如,在 `knowledge_base_chat.py` 中,通过 KBServiceFactory 获取知识库服务实例来搜索知识库中的文档;在 `kb_api.py` 中,通过 KBServiceFactory 创建新的知识库或删除现有知识库。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `get_service` 方法时,需要确保传入的向量存储类型是支持的类型之一,否则可能会抛出异常。
|
||||
- `get_service_by_name` 方法依赖于数据库中的知识库配置信息,如果数据库中不存在指定的知识库名称,将返回 None。
|
||||
- 默认情况下,`get_default` 方法返回的知识库服务实例使用的向量存储类型为 `SupportedVSType.DEFAULT`,具体实现可能会根据项目需求进行调整。
|
||||
|
||||
**输出示例**:
|
||||
由于 KBServiceFactory 类主要提供静态方法来获取知识库服务实例,而不直接产生输出,因此没有具体的输出示例。返回的知识库服务实例根据不同的向量存储类型,将具有不同的方法和属性,用于执行知识库的相关操作。
|
||||
### FunctionDef get_service(kb_name, vector_store_type, embed_model)
|
||||
**get_service**: `get_service` 函数用于根据知识库名称、向量存储类型和嵌入模型名称动态获取对应的知识库服务实例。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 知识库名称,类型为 `str`。
|
||||
- `vector_store_type`: 向量存储类型,可以是 `str` 类型的向量存储类型名称或 `SupportedVSType` 枚举类型。
|
||||
- `embed_model`: 嵌入模型名称,默认值为 `EMBEDDING_MODEL`,类型为 `str`。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先判断 `vector_store_type` 参数的类型,如果是字符串,则将其转换为 `SupportedVSType` 枚举类型。接着,根据向量存储类型的不同,动态导入并返回对应的知识库服务类的实例。支持的向量存储类型包括 FAISS、Milvus、Zilliz、PostgreSQL、Elasticsearch、ChromaDB 等,以及一个默认的向量存储类型。如果指定的向量存储类型为默认类型,则会根据 `model_config.kbs_config` 中的配置返回 MilvusKBService 实例。每种向量存储类型对应的知识库服务类都继承自 `KBService` 基类,并实现了相应的方法以支持知识库的操作。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `get_service` 函数时,需要确保传入的向量存储类型名称与 `SupportedVSType` 中定义的类型名称一致,否则可能会引发错误。
|
||||
- 如果项目中新增了向量存储类型,需要在 `SupportedVSType` 枚举类中添加相应的类型,并在 `get_service` 函数中添加相应的逻辑以支持新的向量存储类型。
|
||||
- 在调用此函数获取知识库服务实例后,可以使用该实例执行创建知识库、添加文档、搜索文档等操作。
|
||||
|
||||
**输出示例**:
|
||||
由于 `get_service` 函数返回的是知识库服务实例,而不是具体的数据,因此没有直接的输出示例。返回的实例类型取决于传入的向量存储类型参数。例如,如果传入的向量存储类型为 `FAISS`,则函数将返回一个 `FaissKBService` 类的实例。
|
||||
***
|
||||
### FunctionDef get_service_by_name(kb_name)
|
||||
**get_service_by_name**: 此函数的功能是根据知识库名称获取对应的知识库服务实例。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 知识库的名称,类型为字符串。
|
||||
|
||||
**代码描述**: `get_service_by_name` 函数首先调用 `load_kb_from_db` 函数,根据传入的知识库名称 `kb_name` 从数据库中加载知识库的信息,包括知识库的名称、向量库类型和嵌入模型名称。如果数据库中不存在指定名称的知识库,`load_kb_from_db` 将返回三个 `None` 值,此时 `get_service_by_name` 函数也将返回 `None`。如果成功从数据库中加载到知识库信息,`get_service_by_name` 函数将使用加载到的知识库名称、向量库类型和嵌入模型名称作为参数,调用 `KBServiceFactory.get_service` 方法,动态获取并返回对应的知识库服务实例。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数之前,确保传入的知识库名称在数据库中存在,否则函数将返回 `None`。
|
||||
- 此函数依赖于 `load_kb_from_db` 函数从数据库中加载知识库信息,因此需要确保数据库连接正常且知识库信息已正确录入数据库。
|
||||
- 返回的知识库服务实例类型取决于知识库的向量库类型,例如,如果向量库类型为 `FAISS`,则返回的实例将是 `FaissKBService` 类的实例。
|
||||
|
||||
**输出示例**:
|
||||
假设数据库中存在一个名为 "技术文档库" 的知识库,其向量库类型为 "FAISS",嵌入模型名称为 "BERT",调用 `get_service_by_name("技术文档库")` 将返回一个 `FaissKBService` 类的实例,该实例用于管理和操作名为 "技术文档库" 的知识库。如果数据库中不存在名为 "不存在的库" 的知识库,调用 `get_service_by_name("不存在的库")` 将返回 `None`。
|
||||
***
|
||||
### FunctionDef get_default
|
||||
**get_default**: `get_default` 函数的功能是获取默认的知识库服务实例。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `get_default` 函数通过调用 `KBServiceFactory.get_service` 方法,传入 `"default"` 作为知识库名称和 `SupportedVSType.DEFAULT` 作为向量存储类型,来获取默认的知识库服务实例。在这个过程中,`SupportedVSType.DEFAULT` 指代默认的向量存储服务类型,其具体实现可能会根据项目配置或环境而变化。根据 `KBServiceFactory.get_service` 的实现逻辑,如果向量存储类型为 `SupportedVSType.DEFAULT`,则会返回一个 `MilvusKBService` 实例,除非项目配置指定了不同的默认服务。这意味着,如果没有特别指定,默认的知识库服务将使用 Milvus 作为向量存储后端。
|
||||
|
||||
**注意**:
|
||||
- 使用 `get_default` 函数时,不需要传递任何参数,这使得它非常适合于需要快速获取默认知识库服务实例的场景。
|
||||
- 返回的知识库服务实例类型可能会根据项目的配置或环境设置而有所不同。默认情况下,它返回的是 `MilvusKBService` 实例,但这一行为是可配置的。
|
||||
- 在实际应用中,应确保项目配置正确,以便 `get_default` 能够返回预期的知识库服务实例。
|
||||
|
||||
**输出示例**: 由于 `get_default` 函数的返回值取决于项目配置,因此没有固定的输出示例。但在大多数情况下,如果项目使用 Milvus 作为默认的向量存储服务,那么该函数可能返回类似于以下的实例表示:
|
||||
|
||||
```python
|
||||
<MilvusKBService object at 0x7f8b2d4c1e50>
|
||||
```
|
||||
|
||||
这表示 `get_default` 成功返回了一个 `MilvusKBService` 的实例,可以用于执行知识库相关的操作,如创建知识库、添加文档、搜索文档等。
|
||||
***
|
||||
## FunctionDef get_kb_details
|
||||
**get_kb_details**: 此函数的功能是获取所有知识库的详细信息列表。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `get_kb_details` 函数首先调用 `list_kbs_from_folder` 函数来获取文件夹中的知识库列表,然后调用 `KBService.list_kbs` 方法获取数据库中的知识库列表。对于文件夹中的每个知识库,函数初始化一个包含基本信息的字典,并将其添加到结果字典中。接下来,对于数据库中的每个知识库,函数通过调用 `get_kb_detail` 函数获取其详细信息,并更新结果字典中相应知识库的信息。如果数据库中的知识库在结果字典中不存在,则将其添加到结果字典中,并标记为不在文件夹中。最后,函数将结果字典中的值转换为列表,并为每个知识库分配一个序号,然后返回这个列表。
|
||||
|
||||
**注意**:
|
||||
- 确保 `list_kbs_from_folder` 和 `KBService.list_kbs` 方法能够正确执行,且数据库连接正常,以便能够获取完整的知识库列表。
|
||||
- `get_kb_detail` 函数需要能够正确返回知识库的详细信息,包括知识库名称、简介、向量库类型、嵌入模型名称、文件数量和创建时间等。
|
||||
|
||||
**输出示例**:
|
||||
假设文件夹和数据库中各有两个知识库,函数可能返回如下列表:
|
||||
```python
|
||||
[
|
||||
{
|
||||
"No": 1,
|
||||
"kb_name": "知识库1",
|
||||
"vs_type": "ElasticSearch",
|
||||
"kb_info": "知识库1的简介",
|
||||
"embed_model": "BERT",
|
||||
"file_count": 100,
|
||||
"create_time": "2023-04-01T12:00:00",
|
||||
"in_folder": True,
|
||||
"in_db": True
|
||||
},
|
||||
{
|
||||
"No": 2,
|
||||
"kb_name": "知识库2",
|
||||
"vs_type": "Faiss",
|
||||
"kb_info": "知识库2的简介",
|
||||
"embed_model": "RoBERTa",
|
||||
"file_count": 50,
|
||||
"create_time": "2023-04-02T12:00:00",
|
||||
"in_folder": False,
|
||||
"in_db": True
|
||||
}
|
||||
]
|
||||
```
|
||||
这个列表包含了两个知识库的详细信息,每个知识库都有一个序号、名称、向量库类型、简介、嵌入模型名称、文件数量、创建时间以及它们是否存在于文件夹和数据库中的标记。
|
||||
## FunctionDef get_kb_file_details(kb_name)
|
||||
**get_kb_file_details**: 此函数用于获取指定知识库中的文件详细信息列表。
|
||||
|
||||
**参数**:
|
||||
- `kb_name`: 字符串类型,指定要查询的知识库名称。
|
||||
|
||||
**代码描述**: `get_kb_file_details` 函数首先通过 `KBServiceFactory.get_service_by_name` 方法根据知识库名称获取对应的知识库服务实例。如果该实例不存在,则直接返回空列表。接着,函数调用 `list_files_from_folder` 函数列出知识库文件夹中的所有文件,并通过知识库服务实例的 `list_files` 方法获取数据库中记录的所有文件名。然后,函数遍历文件夹中的文件,为每个文件构建一个包含文件基本信息的字典,并将其添加到结果字典中。对于数据库中存在的文件,函数通过调用 `get_file_detail` 函数获取其详细信息,并更新到结果字典中。最后,函数将结果字典中的值转换为列表,并为每个元素添加一个序号字段,然后返回这个列表。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `kb_name` 在系统中是存在的,否则函数将返回空列表。
|
||||
- 此函数整合了文件夹和数据库中的文件信息,如果文件同时存在于文件夹和数据库中,数据库中的文件信息将覆盖文件夹中的同名文件信息。
|
||||
- 返回的列表中的每个字典都包含了文件的多个属性,如文件名、扩展名、版本等,这些信息有助于进一步处理和管理知识库中的文件。
|
||||
|
||||
**输出示例**:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"No": 1,
|
||||
"kb_name": "技术文档库",
|
||||
"file_name": "document1.pdf",
|
||||
"file_ext": ".pdf",
|
||||
"file_version": 0,
|
||||
"document_loader": "",
|
||||
"docs_count": 0,
|
||||
"text_splitter": "",
|
||||
"create_time": null,
|
||||
"in_folder": true,
|
||||
"in_db": false
|
||||
},
|
||||
{
|
||||
"No": 2,
|
||||
"kb_name": "技术文档库",
|
||||
"file_name": "report2.docx",
|
||||
"file_ext": ".docx",
|
||||
"file_version": 1,
|
||||
"document_loader": "WordLoader",
|
||||
"docs_count": 10,
|
||||
"text_splitter": "SpacyTextSplitter",
|
||||
"create_time": "2023-04-01 12:00:00",
|
||||
"in_folder": false,
|
||||
"in_db": true
|
||||
}
|
||||
]
|
||||
```
|
||||
此示例展示了当查询到文件时,`get_kb_file_details` 函数返回的信息列表。列表中的每个元素都是一个字典,包含了文件所属的知识库名称、文件名、文件扩展名、文件版本、文档加载器名称、文本分割器名称、文件的创建时间、是否存在于文件夹中、是否存在于数据库中等信息。
|
||||
## ClassDef EmbeddingsFunAdapter
|
||||
**EmbeddingsFunAdapter**: EmbeddingsFunAdapter类的功能是对文本进行嵌入表示的转换,支持同步和异步两种方式。
|
||||
|
||||
**属性**:
|
||||
- `embed_model`: 嵌入模型的名称,用于指定使用哪个预训练模型进行文本嵌入。
|
||||
|
||||
**代码描述**:
|
||||
EmbeddingsFunAdapter类继承自Embeddings类,主要提供了文本嵌入表示的功能。它包含以下几个关键方法:
|
||||
- `__init__`: 构造函数,接收一个嵌入模型名称作为参数,默认使用预定义的EMBEDDING_MODEL。
|
||||
- `embed_documents`: 接收一个文本列表,返回这些文本的嵌入表示。该方法首先使用指定的嵌入模型将文本转换为嵌入向量,然后对这些向量进行归一化处理。
|
||||
- `embed_query`: 接收单个文本字符串,返回该文本的嵌入表示。与`embed_documents`方法类似,但是专门针对单个查询文本进行处理,并将结果转换为一维数组返回。
|
||||
- `aembed_documents`: 异步版本的`embed_documents`方法,功能相同但适用于异步调用场景。
|
||||
- `aembed_query`: 异步版本的`embed_query`方法,功能相同但适用于异步调用场景。
|
||||
|
||||
在项目中,EmbeddingsFunAdapter类被多个模块调用,用于处理不同场景下的文本嵌入需求。例如,在知识库聊天迭代器、知识库缓存加载、以及各种知识库服务中,都可以看到EmbeddingsFunAdapter的身影。这些调用场景表明,EmbeddingsFunAdapter是处理文本嵌入表示的核心组件,支持多种知识库服务的文本相似度查询功能。
|
||||
|
||||
**注意**:
|
||||
- 在使用EmbeddingsFunAdapter进行文本嵌入转换时,需要确保传入的嵌入模型名称是有效且已经预训练好的。
|
||||
- 异步方法`aembed_documents`和`aembed_query`需要在异步环境下调用,以避免阻塞主线程。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
# 使用embed_query方法的输出示例
|
||||
embeddings = embed_func.embed_query("这是一个示例文本")
|
||||
# 输出: [0.01, -0.02, 0.03, ..., 0.05] # 假设的嵌入向量列表
|
||||
|
||||
# 使用aembed_documents方法的输出示例
|
||||
embeddings = await embed_func.aembed_documents(["文本1", "文本2"])
|
||||
# 输出: [[0.01, -0.02, 0.03, ..., 0.05], [0.02, -0.03, 0.04, ..., 0.06]] # 假设的嵌入向量列表
|
||||
```
|
||||
在实际应用中,嵌入向量的维度和具体数值将取决于所使用的嵌入模型。
|
||||
### FunctionDef __init__(self, embed_model)
|
||||
**__init__**: 该函数用于初始化EmbeddingsFunAdapter类的实例。
|
||||
|
||||
**参数**:
|
||||
- **embed_model**: 字符串类型,默认值为EMBEDDING_MODEL。该参数用于指定嵌入模型。
|
||||
|
||||
**代码描述**:
|
||||
`__init__`方法是`EmbeddingsFunAdapter`类的构造函数,负责初始化类的实例。在这个方法中,接收一个名为`embed_model`的参数,该参数用于指定将要使用的嵌入模型。如果调用时没有指定`embed_model`参数,则会使用`EMBEDDING_MODEL`作为默认值。这里的`EMBEDDING_MODEL`是在类外部定义的一个常量,代表默认的嵌入模型名称。
|
||||
|
||||
在方法体内,将传入的`embed_model`参数值赋给实例变量`self.embed_model`。这样,每个`EmbeddingsFunAdapter`类的实例都会拥有一个`embed_model`实例变量,用于存储该实例所使用的嵌入模型名称。
|
||||
|
||||
**注意**:
|
||||
- 在使用`EmbeddingsFunAdapter`类创建实例时,可以根据需要传入不同的`embed_model`参数值,以指定不同的嵌入模型。如果不指定,将使用默认的嵌入模型。
|
||||
- 确保传入的`embed_model`参数值是有效的,且对应的嵌入模型已经正确安装和配置,以避免在后续使用过程中出现错误。
|
||||
***
|
||||
### FunctionDef embed_documents(self, texts)
|
||||
**embed_documents**: 该函数的功能是将文本列表转换为归一化的嵌入向量列表。
|
||||
|
||||
**参数**:
|
||||
- `texts`: 需要转换为嵌入向量的文本字符串列表。
|
||||
|
||||
**代码描述**:
|
||||
`embed_documents`函数首先调用`embed_texts`函数,将文本列表`texts`和嵌入模型`self.embed_model`作为参数传递,以获取文本的嵌入向量。`embed_texts`函数负责将文本向量化,可以处理本地或在线的嵌入模型,并返回一个包含向量化结果的`BaseResponse`对象。接着,`embed_documents`函数使用`normalize`函数对嵌入向量进行L2范数归一化处理,以确保所有向量都规范化到单位球上。这一步骤对于后续的向量空间模型处理非常重要,有助于提高模型的效果和稳定性。最后,函数将归一化的嵌入向量转换为列表格式并返回。
|
||||
|
||||
在整个过程中,`embed_documents`函数依赖于`embed_texts`函数进行文本的向量化处理,并依赖于`normalize`函数进行向量的归一化处理,这两个函数是实现文本嵌入和归一化的关键步骤。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`texts`参数是有效的文本列表,且`self.embed_model`已正确指定,以便函数能够找到并使用正确的嵌入模型进行文本向量化处理。
|
||||
- 归一化步骤是必要的,它确保了嵌入向量的质量,对于后续的处理非常重要。
|
||||
|
||||
**输出示例**:
|
||||
假设调用`embed_documents`函数,传入文本列表`["你好", "世界"]`,可能会返回如下归一化的嵌入向量列表:
|
||||
```
|
||||
[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]
|
||||
```
|
||||
这表示两个文本"你好"和"世界"被成功转换为嵌入向量,并且这些向量已经过归一化处理。
|
||||
***
|
||||
### FunctionDef embed_query(self, text)
|
||||
**embed_query**: 该函数的功能是对输入的文本进行向量化处理,并返回归一化后的向量列表。
|
||||
|
||||
**参数**:
|
||||
- `text`: 需要进行向量化处理的文本,数据类型为字符串。
|
||||
|
||||
**代码描述**:
|
||||
`embed_query`函数首先调用`embed_texts`函数,将输入的文本`text`转换为向量化表示。在这个过程中,`embed_texts`函数接收一个文本列表(本例中为单个文本构成的列表)、嵌入模型名称以及一个标志位`to_query`,后者指示该文本是作为查询使用。得到的向量化结果是一个包含单个向量的列表,该向量代表输入文本的嵌入表示。
|
||||
|
||||
接下来,函数将这个向量转换为二维数组,以满足后续处理的需求。这是通过`np.reshape`实现的,其中`query_embed`是原始的一维向量,`query_embed_2d`是转换后的二维数组。
|
||||
|
||||
然后,使用`normalize`函数对二维数组进行L2范数归一化处理。归一化是向量空间模型中的一个常见预处理步骤,有助于提高模型的效果和稳定性。归一化后的结果是一个二维数组,其中包含了归一化后的嵌入向量。
|
||||
|
||||
最后,函数将归一化后的二维数组转换回一维数组,并将其转换为列表格式返回。这样,返回的结果便是输入文本的归一化嵌入表示,可以直接用于后续的查询或其他处理。
|
||||
|
||||
**注意**:
|
||||
- 输入文本`text`应为有效的字符串,不应为空或非文本类型。
|
||||
- 该函数依赖于`embed_texts`和`normalize`两个函数,因此在使用前需要确保这些依赖函数正确实现且可用。
|
||||
- 归一化处理依赖于`numpy`库,使用前需确保已安装`numpy`。
|
||||
|
||||
**输出示例**:
|
||||
假设输入文本为"你好世界",且嵌入模型将该文本向量化为`[0.1, 0.2, 0.3]`,则归一化后的输出可能如下所示:
|
||||
```
|
||||
[0.26726124, 0.53452248, 0.80178373]
|
||||
```
|
||||
这表示输入文本"你好世界"的归一化嵌入向量为上述列表。
|
||||
***
|
||||
### FunctionDef aembed_documents(self, texts)
|
||||
**aembed_documents**: 此函数的功能是异步地将一系列文本向量化,并返回归一化后的向量列表。
|
||||
|
||||
**参数**:
|
||||
- `texts`: 需要进行向量化处理的文本列表,类型为List[str]。
|
||||
|
||||
**代码描述**:
|
||||
`aembed_documents`函数是`EmbeddingsFunAdapter`类的一个方法,它接受一个文本列表作为输入,使用`aembed_texts`函数异步地将这些文本转换为嵌入向量。这一过程涉及到调用`aembed_texts`函数,该函数根据指定的嵌入模型(`embed_model`)对文本进行向量化处理,并返回一个包含向量化结果的`BaseResponse`对象。在获得向量化结果后,`aembed_documents`方法进一步调用`normalize`函数对嵌入向量进行L2范数归一化处理,以确保向量在同一规范化空间内,这对于后续的向量相似度计算等操作是非常重要的。最后,该方法将归一化后的嵌入向量转换为列表格式并返回。
|
||||
|
||||
从功能角度看,`aembed_documents`方法与其调用的`aembed_texts`函数和`normalize`函数共同构成了文本向量化和归一化处理的完整流程。其中,`aembed_texts`负责文本的异步向量化处理,而`normalize`负责对向量化结果进行归一化,以优化向量的表示和后续使用。
|
||||
|
||||
**注意**:
|
||||
- 在调用此方法时,需要确保传入的`texts`参数是有效的文本列表。
|
||||
- 该方法的执行效率和效果依赖于`embed_model`的选择和配置,以及`aembed_texts`函数和`normalize`函数的实现。
|
||||
- 由于该方法涉及到异步调用,因此在使用时需要配合`await`关键字或在异步环境中调用。
|
||||
|
||||
**输出示例**:
|
||||
假设调用`await aembed_documents(texts=["你好", "世界"])`,可能会返回如下归一化后的向量列表:
|
||||
```
|
||||
[[0.4472136, 0.89442719], [0.5547002, 0.83205029]]
|
||||
```
|
||||
这表示两个文本"你好"和"世界"被成功向量化并归一化,向量化结果分别为`[0.4472136, 0.89442719]`和`[0.5547002, 0.83205029]`。
|
||||
***
|
||||
### FunctionDef aembed_query(self, text)
|
||||
**aembed_query**: 此函数的功能是对给定文本进行异步向量化处理,并返回归一化后的向量列表。
|
||||
|
||||
**参数**:
|
||||
- `text`: 需要进行向量化处理的文本,类型为str。
|
||||
|
||||
**代码描述**:
|
||||
`aembed_query`函数首先调用`aembed_texts`函数,对输入的文本`text`进行异步向量化处理。该过程涉及将文本封装成列表,并指定使用的嵌入模型`embed_model`以及将`to_query`参数设置为True,以优化向量化结果的使用场景。向量化处理后,返回的结果是一个包含向量化结果的`BaseResponse`对象。
|
||||
|
||||
接下来,函数从`BaseResponse`对象中提取出第一个(也是唯一一个,因为输入文本为单个字符串)向量化结果,并将其从一维数组转换为二维数组。这一步骤是为了满足后续归一化处理的需求。
|
||||
|
||||
随后,函数调用`normalize`函数对二维数组进行L2范数归一化处理。归一化是向量空间模型中的一个常见预处理步骤,有助于提高后续处理的效果和稳定性。归一化处理后,函数将归一化后的二维数组转换回一维数组,并将其作为最终结果返回。
|
||||
|
||||
**注意**:
|
||||
- 在调用此函数时,需要确保传入的`text`参数是有效的文本字符串。
|
||||
- 函数的执行结果依赖于`embed_model`指定的嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。
|
||||
- 归一化处理是基于`numpy`库实现的,因此在使用此函数前需要确保已经安装了`numpy`库。
|
||||
|
||||
**输出示例**:
|
||||
假设调用`await aembed_query(text="你好")`,可能会返回如下归一化后的向量列表:
|
||||
```python
|
||||
[0.1, 0.2, 0.3, 0.4]
|
||||
```
|
||||
这表示文本"你好"被成功向量化并归一化,向量化结果为一个一维数组。
|
||||
|
||||
在项目中,`aembed_query`函数被用于处理需要异步进行文本向量化的场景,如在聊天文件中对用户查询进行异步向量化以支持快速的文本查询和相似度计算。此外,它也支持通过在线API进行文本向量化,为项目提供了灵活的向量化解决方案。
|
||||
***
|
||||
## FunctionDef score_threshold_process(score_threshold, k, docs)
|
||||
**score_threshold_process**: 此函数的功能是根据给定的分数阈值和文档相似度,筛选出符合条件的文档,并返回前k个文档。
|
||||
|
||||
**参数**:
|
||||
- score_threshold: 分数阈值,用于筛选相似度高于此阈值的文档。
|
||||
- k: 返回的文档数量上限。
|
||||
- docs: 包含文档及其相似度分数的列表。
|
||||
|
||||
**代码描述**:
|
||||
`score_threshold_process` 函数接收三个参数:`score_threshold`(分数阈值),`k`(返回的文档数量上限),以及`docs`(包含文档及其相似度分数的列表)。如果`score_threshold`不为`None`,则函数会使用`operator.le`(小于等于比较操作符)来筛选出相似度分数小于等于`score_threshold`的文档。之后,函数返回筛选后的文档列表中的前`k`个文档。
|
||||
|
||||
在项目中,`score_threshold_process`函数被多个知识库服务(如`MilvusKBService`、`PGKBService`和`ZillizKBService`)中的`do_search`方法调用。这些服务通过不同的后端(如Milvus、PostgreSQL、Zilliz等)执行相似度搜索,并使用`score_threshold_process`函数来根据分数阈值筛选和限制返回的结果数量。这样,无论底层使用哪种搜索技术,都能通过统一的方式控制搜索结果的质量和数量。
|
||||
|
||||
**注意**:
|
||||
- 如果`score_threshold`为`None`,则不会进行分数阈值筛选,直接返回前`k`个文档。
|
||||
- 函数的返回值依赖于输入的`docs`列表和`k`值,因此在调用此函数前,确保`docs`列表已按相似度分数排序。
|
||||
|
||||
**输出示例**:
|
||||
假设有以下输入:
|
||||
- score_threshold = 0.5
|
||||
- k = 3
|
||||
- docs = [("doc1", 0.6), ("doc2", 0.4), ("doc3", 0.7), ("doc4", 0.5)]
|
||||
|
||||
调用`score_threshold_process(score_threshold, k, docs)`后,返回值可能为:
|
||||
- [("doc1", 0.6), ("doc3", 0.7), ("doc4", 0.5)]
|
||||
|
||||
这表示在给定的文档中,有三个文档的相似度分数满足小于等于分数阈值的条件,并且根据要求返回了前3个文档。
|
||||
@ -0,0 +1,306 @@
|
||||
## FunctionDef _get_result_to_documents(get_result)
|
||||
**_get_result_to_documents**: 该函数的功能是将`GetResult`类型的查询结果转换为`Document`对象列表。
|
||||
|
||||
**参数**:
|
||||
- `get_result`: `GetResult`类型,表示从数据库查询得到的结果。
|
||||
|
||||
**代码描述**:
|
||||
`_get_result_to_documents`函数主要用于处理从数据库查询得到的结果,并将这些结果转换为`Document`对象列表。首先,函数检查`get_result`中的`documents`字段是否为空,如果为空,则直接返回空列表。如果不为空,则继续处理。
|
||||
|
||||
接下来,函数检查`get_result`中的`metadatas`字段。如果`metadatas`字段存在且不为空,则使用该字段的值;如果不存在或为空,则创建一个与`documents`字段长度相同的空字典列表。这一步确保了每个文档都有对应的元数据,即使某些文档没有元数据也会分配一个空字典。
|
||||
|
||||
然后,函数遍历`documents`和`metadatas`列表,将它们的元素打包成`Document`对象,并添加到一个新的列表`document_list`中。这里,`Document`对象是通过关键字参数`page_content`和`metadata`构造的,分别对应每个文档的内容和元数据。
|
||||
|
||||
最后,函数返回构造好的`Document`对象列表。
|
||||
|
||||
在项目中,`_get_result_to_documents`函数被`ChromaKBService`类的`get_doc_by_ids`方法调用。`get_doc_by_ids`方法负责根据给定的ID列表从数据库中查询文档,并使用`_get_result_to_documents`函数将查询结果转换为`Document`对象列表,以便进一步处理或响应客户端请求。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`get_result`参数格式正确,特别是`documents`和`metadatas`字段,以避免运行时错误。
|
||||
- 该函数不直接与数据库交互,而是处理已经查询得到的结果。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
Document(page_content="文档内容1", metadata={"作者": "张三"}),
|
||||
Document(page_content="文档内容2", metadata={"作者": "李四"})
|
||||
]
|
||||
```
|
||||
此示例展示了当`_get_result_to_documents`函数处理包含两个文档内容和对应元数据的查询结果时,返回的`Document`对象列表的可能形态。
|
||||
## FunctionDef _results_to_docs_and_scores(results)
|
||||
**_results_to_docs_and_scores**: 该函数的功能是将搜索结果转换为文档和分数的列表。
|
||||
|
||||
**参数**:
|
||||
- `results`: 任意类型,预期为包含文档内容、元数据和距离的搜索结果。
|
||||
|
||||
**代码描述**:
|
||||
`_results_to_docs_and_scores` 函数接收一个包含搜索结果的参数 `results`,这个参数预期是一个字典,其中包含三个键:`"documents"`、`"metadatas"` 和 `"distances"`。每个键对应的值都是一个列表,列表中的每个元素分别代表搜索到的文档内容、文档的元数据和文档与查询之间的距离(通常用于表示相似度或相关性的分数)。
|
||||
|
||||
函数通过对这三个列表进行并行迭代(使用 `zip` 函数),为每个搜索结果创建一个元组,其中包含一个 `Document` 对象和一个浮点数。`Document` 对象由文档内容和元数据构成,而浮点数则是该文档与查询之间的距离。这个过程生成了一个元组列表,每个元组代表一个搜索结果及其相关性分数。
|
||||
|
||||
在项目中,`_results_to_docs_and_scores` 函数被 `ChromaKBService` 类的 `do_search` 方法调用。`do_search` 方法负责执行搜索查询,并使用 `_results_to_docs_and_scores` 函数处理查询结果,将其转换为更易于处理和展示的格式。这种设计模式允许将搜索逻辑与结果处理逻辑分离,提高了代码的可读性和可维护性。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的 `results` 参数格式正确,即包含 `"documents"`、`"metadatas"` 和 `"distances"` 三个键,且每个键对应的值都是列表格式。
|
||||
- 该函数依赖于 `Document` 类的正确实现。`Document` 类需要能够接受页面内容和元数据作为参数,并将它们封装为一个对象。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
(Document(page_content="文档内容1", metadata={"作者": "张三"}), 0.95),
|
||||
(Document(page_content="文档内容2", metadata={"作者": "李四"}), 0.89)
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数返回值的可能形式,其中包含了两个元组,每个元组都包含一个 `Document` 对象和一个表示与查询相似度的分数。
|
||||
## ClassDef ChromaKBService
|
||||
**ChromaKBService**: ChromaKBService 类是用于操作和管理基于 ChromaDB 的知识库服务。
|
||||
|
||||
**属性**:
|
||||
- `vs_path`: 向量存储路径。
|
||||
- `kb_path`: 知识库路径。
|
||||
- `client`: ChromaDB 客户端实例。
|
||||
- `collection`: 当前知识库的集合。
|
||||
|
||||
**代码描述**:
|
||||
ChromaKBService 类继承自 KBService 类,专门用于处理基于 ChromaDB 的知识库操作。它提供了一系列方法来初始化服务、创建知识库、删除知识库、添加文档、删除文档、清空向量存储、以及执行文档搜索等操作。
|
||||
|
||||
- `vs_type` 方法返回当前知识库服务使用的向量存储类型,即 ChromaDB。
|
||||
- `get_vs_path` 和 `get_kb_path` 方法分别用于获取向量存储和知识库的路径。
|
||||
- `do_init` 方法初始化 ChromaDB 客户端和集合。
|
||||
- `do_create_kb` 方法创建一个新的知识库,实际上是在 ChromaDB 中创建一个新的集合。
|
||||
- `do_drop_kb` 方法删除知识库,即删除 ChromaDB 中的集合。
|
||||
- `do_search` 方法执行文档搜索,返回与查询最相关的文档列表和它们的得分。
|
||||
- `do_add_doc` 方法向知识库添加文档,包括文档的文本、嵌入向量和元数据。
|
||||
- `get_doc_by_ids` 和 `del_doc_by_ids` 方法分别根据文档 ID 获取文档和删除文档。
|
||||
- `do_clear_vs` 方法清空向量存储,通过删除并重新创建集合来实现。
|
||||
- `do_delete_doc` 方法根据提供的知识文件删除文档。
|
||||
|
||||
**注意**:
|
||||
- 在使用 ChromaKBService 之前,需要确保 ChromaDB 环境已经正确设置并可用。
|
||||
- 在调用 `do_add_doc` 方法添加文档时,需要确保文档数据包含有效的文本、嵌入向量和元数据。
|
||||
- 删除操作(`do_drop_kb`、`del_doc_by_ids`、`do_delete_doc`)应谨慎使用,以避免意外丢失数据。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
# 搜索文档的示例输出
|
||||
[
|
||||
(Document(text="文档内容示例", metadata={"author": "作者示例"}), 0.95),
|
||||
(Document(text="另一个文档内容示例", metadata={"author": "另一个作者示例"}), 0.90)
|
||||
]
|
||||
```
|
||||
这个示例展示了执行文档搜索操作后,可能返回的文档列表和它们的相关性得分。每个元组包含一个 Document 实例和一个得分,Document 实例包含文档的文本和元数据。
|
||||
### FunctionDef vs_type(self)
|
||||
**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。
|
||||
|
||||
**参数**: 该函数没有参数。
|
||||
|
||||
**代码描述**: vs_type函数是ChromaKBService类的一个方法,它的作用是指明该知识库服务实例支持的向量存储类型。在这个具体实现中,vs_type方法通过返回SupportedVSType枚举类中的CHROMADB值,明确表示ChromaKBService支持ChromaDB作为其向量存储服务。SupportedVSType枚举类定义了一系列项目中支持的向量存储类型,包括但不限于FAISS、MILVUS、ZILLIZ、PostgreSQL、Elasticsearch等,其中CHROMADB代表使用ChromaDB作为向量存储服务。这种设计允许知识库服务在项目中以一种灵活的方式来指定和使用不同的向量存储解决方案,同时也便于在KBServiceFactory中根据需要动态选择和实例化相应的知识库服务实现。
|
||||
|
||||
**注意**:
|
||||
- 在使用vs_type方法时,开发者不需要传递任何参数,该方法将自动返回ChromaKBService所支持的向量存储类型。
|
||||
- 返回的向量存储类型应与SupportedVSType枚举类中定义的类型一致,以确保知识库服务的正确实例化和使用。
|
||||
- 当扩展项目以支持新的向量存储服务时,应在SupportedVSType枚举类中添加新的类型,并确保知识库服务类正确实现vs_type方法以反映这一变化。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
'chromadb'
|
||||
```
|
||||
在这个示例中,vs_type方法将返回一个字符串'chromadb',表示ChromaKBService类支持使用ChromaDB作为其向量存储服务。
|
||||
***
|
||||
### FunctionDef get_vs_path(self)
|
||||
**get_vs_path**: 此函数的功能是获取向量空间的路径。
|
||||
|
||||
**参数**: 此函数没有显式参数,但依赖于对象的`kb_name`和`embed_model`属性。
|
||||
|
||||
**代码描述**: `get_vs_path`函数是`ChromaKBService`类的一个方法,用于返回知识库的向量空间路径。它通过调用全局函数`get_vs_path`实现,该全局函数接受两个参数:知识库名称(`kb_name`)和嵌入模型(`embed_model`)。这两个参数是`ChromaKBService`对象的属性,分别代表当前知识库的名称和使用的嵌入模型。此方法的返回值是一个字符串,表示向量空间的文件路径。
|
||||
|
||||
在项目中,`get_vs_path`方法被`do_init`方法调用。在`do_init`方法中,首先通过调用`get_kb_path`获取知识库的路径,然后调用`get_vs_path`获取向量空间的路径,并使用此路径初始化`PersistentClient`对象。这表明`get_vs_path`方法在知识库初始化过程中起到了关键作用,它确保了向量空间的路径可以被正确获取并用于后续的数据库客户端和集合的创建。
|
||||
|
||||
**注意**: 使用`get_vs_path`方法时,需要确保`ChromaKBService`对象的`kb_name`和`embed_model`属性已经被正确设置,因为这两个属性直接影响向量空间路径的生成。
|
||||
|
||||
**输出示例**: 假设知识库名称为`example_kb`,嵌入模型为`model_v1`,则`get_vs_path`可能返回的路径示例为`/path/to/vector_space/example_kb_model_v1.vs`。
|
||||
***
|
||||
### FunctionDef get_kb_path(self)
|
||||
**get_kb_path**: 此函数的功能是获取知识库的路径。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `get_kb_path` 函数是 `ChromaKBService` 类的一个方法,它的主要作用是返回知识库的路径。这个方法通过调用 `get_kb_path` 函数,并传递 `self.kb_name` 作为参数,来实现这一功能。在这里,`self.kb_name` 是 `ChromaKBService` 类的一个属性,它存储了当前知识库的名称。通过这种方式,`get_kb_path` 方法能够根据知识库的名称动态地获取其路径。
|
||||
|
||||
在项目中,`get_kb_path` 方法被 `do_init` 方法调用。在 `do_init` 方法中,首先通过调用 `get_kb_path` 方法来获取知识库路径,并将其存储在 `self.kb_path` 属性中。这一步骤是初始化过程的一部分,确保了后续操作能够基于正确的知识库路径进行。此外,`do_init` 方法还涉及到获取视图存储路径和初始化持久化客户端等操作,这些都是基于知识库服务正常运行所必需的步骤。
|
||||
|
||||
**注意**: 在使用 `get_kb_path` 方法时,需要确保 `self.kb_name` 已经被正确赋值,因为这将直接影响到获取路径的结果。
|
||||
|
||||
**输出示例**: 假设当前知识库的名称为 "example_kb",那么 `get_kb_path` 方法的返回值可能看起来像这样:
|
||||
```
|
||||
"/path/to/knowledge_bases/example_kb"
|
||||
```
|
||||
***
|
||||
### FunctionDef do_init(self)
|
||||
**do_init**: 此函数的功能是初始化ChromaKBService对象。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_init`方法是`ChromaKBService`类的一个关键方法,负责初始化知识库服务的核心组件。这个方法首先调用`get_kb_path`方法来获取知识库的路径,并将这个路径存储在`self.kb_path`属性中。接着,它调用`get_vs_path`方法来获取向量空间的路径,并将这个路径用于初始化`PersistentClient`对象,该对象存储在`self.client`属性中。最后,通过`self.client`的`get_or_create_collection`方法,使用`self.kb_name`属性(即知识库的名称)来获取或创建一个集合,并将这个集合对象存储在`self.collection`属性中。
|
||||
|
||||
从功能上看,`do_init`方法通过组合`get_kb_path`和`get_vs_path`方法的功能,确保了知识库服务可以正确地访问知识库路径和向量空间路径。这两个路径对于后续的知识库操作至关重要,因为它们分别确定了知识库数据的存储位置和向量空间数据的存储位置。通过`PersistentClient`对象,`do_init`方法进一步确保了知识库服务能够进行持久化操作,如数据的存储和检索。此外,`self.collection`的初始化为知识库中数据的管理提供了基础,使得数据的增删查改操作可以在此基础上进行。
|
||||
|
||||
**注意**: 在调用`do_init`方法之前,需要确保`ChromaKBService`对象的`kb_name`和`embed_model`属性已经被正确设置,因为这些属性会影响到`get_vs_path`方法的执行结果,进而影响到整个知识库服务的初始化过程。此外,`do_init`方法的成功执行是后续所有知识库操作能够正常进行的前提,因此在知识库服务的启动流程中,这个方法的调用是不可或缺的一步。
|
||||
***
|
||||
### FunctionDef do_create_kb(self)
|
||||
**do_create_kb**: 此函数的功能是在ChromaDB中创建一个知识库(KB)。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `do_create_kb`函数是`ChromaKBService`类的一个方法,用于在ChromaDB中创建一个新的知识库。在ChromaDB中,知识库的概念与集合(collection)相对应。因此,此函数的主要任务是创建或获取一个与知识库名称(`self.kb_name`)相对应的集合。这一过程通过调用`self.client.get_or_create_collection(self.kb_name)`实现,其中`self.client`是指向ChromaDB客户端的引用,而`self.kb_name`则是需要创建或获取的集合的名称。如果指定名称的集合已经存在,则此操作将返回现有集合的引用;如果不存在,则创建一个新的集合并返回其引用。操作完成后,集合的引用被存储在`self.collection`属性中,以便后续操作可以使用。
|
||||
|
||||
**注意**: 使用`do_create_kb`方法时,需要确保`self.client`已经正确初始化并且可以连接到ChromaDB服务器。此外,`self.kb_name`应该是一个有效的集合名称,遵循ChromaDB对集合名称的任何限制或规则。在调用此方法之前,最好确认这些条件已经满足,以避免运行时错误。
|
||||
***
|
||||
### FunctionDef do_drop_kb(self)
|
||||
**do_drop_kb**: 此函数的功能是删除ChromaDB中的一个集合。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_drop_kb`函数负责在ChromaDB数据库中删除一个名为`kb_name`的集合。这个过程首先尝试通过调用`self.client.delete_collection`方法来实现,其中`self.kb_name`作为参数传递,指定了要删除的集合的名称。如果在删除过程中遇到`ValueError`异常,并且异常信息不是因为集合不存在(即错误信息不是"Collection {self.kb_name} does not exist."),那么这个异常将会被重新抛出,以便调用者可以处理这个异常情况。这种设计确保了只有在遇到预期之外的错误时,才会中断程序的执行,而对于集合不存在这种可能预期的情况,则不会影响程序的继续执行。
|
||||
|
||||
在项目中,`do_drop_kb`函数被`do_clear_vs`函数调用,作为清空向量存储的一部分操作。在`do_clear_vs`函数中,调用`do_drop_kb`可以理解为在清空向量存储之前,先删除对应的集合,这可能是因为在某些情况下,直接删除集合比尝试清空其内容来得更为高效或者更符合业务逻辑。
|
||||
|
||||
**注意**: 在使用`do_drop_kb`函数时,需要确保`self.kb_name`已经正确设置为目标集合的名称,并且调用者应当准备好处理可能抛出的`ValueError`异常,特别是在集合可能不存在的情况下。此外,考虑到删除集合是一个不可逆的操作,应当谨慎使用此函数,确保其调用是在适当的上下文中,并且符合业务逻辑的需求。
|
||||
***
|
||||
### FunctionDef do_search(self, query, top_k, score_threshold)
|
||||
**do_search**: 该函数的功能是执行文本查询,并返回与查询最相关的文档及其相关性分数。
|
||||
|
||||
**参数**:
|
||||
- `query`: 需要进行搜索的查询文本,数据类型为字符串。
|
||||
- `top_k`: 返回的最相关文档的数量,数据类型为整数。
|
||||
- `score_threshold`: 相关性分数的阈值,默认为SCORE_THRESHOLD,只有分数高于此阈值的文档才会被返回,数据类型为浮点数。
|
||||
|
||||
**代码描述**:
|
||||
`do_search`函数首先通过`EmbeddingsFunAdapter`类的实例化,使用`self.embed_model`作为嵌入模型来创建一个嵌入函数`embed_func`。然后,使用`embed_func.embed_query(query)`方法将查询文本`query`转换为嵌入向量`embeddings`。这一步骤是通过将文本转换为向量化表示,以便后续进行相似度计算。
|
||||
|
||||
接下来,函数调用`self.collection.query`方法,传入查询嵌入向量`embeddings`和结果数量`n_results`等于`top_k`,执行查询操作。此方法返回一个`QueryResult`对象,包含了查询的结果。
|
||||
|
||||
最后,函数调用`_results_to_docs_and_scores(query_result)`,将查询结果转换为文档和分数的列表。这一步骤通过解析`QueryResult`对象,提取出每个文档及其与查询文本的相似度分数,然后将这些信息封装成元组列表返回。
|
||||
|
||||
在整个过程中,`do_search`函数通过与`EmbeddingsFunAdapter`和`_results_to_docs_and_scores`等函数的交互,实现了从文本查询到获取相关文档及其分数的完整流程。
|
||||
|
||||
**注意**:
|
||||
- 确保`query`参数是有效的查询文本,且`top_k`参数正确设置以返回期望数量的结果。
|
||||
- 函数的性能和准确性依赖于嵌入模型的质量和查询处理机制,因此选择合适的嵌入模型和调整查询参数对于获得有用的搜索结果至关重要。
|
||||
- 默认的`score_threshold`是SCORE_THRESHOLD,可以根据需要调整以过滤掉低相关性的结果。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
(Document(page_content="文档内容1", metadata={"作者": "张三"}), 0.95),
|
||||
(Document(page_content="文档内容2", metadata={"作者": "李四"}), 0.89)
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数返回值的可能形式,其中包含了两个元组,每个元组都包含一个`Document`对象和一个表示与查询相似度的分数。这样的输出格式便于后续处理和展示搜索结果。
|
||||
***
|
||||
### FunctionDef do_add_doc(self, docs)
|
||||
**do_add_doc**: 该函数的功能是将文档列表添加到数据库中,并返回包含文档ID和元数据的信息列表。
|
||||
|
||||
**参数**:
|
||||
- `docs`: 需要添加到数据库的文档对象列表,类型为`List[Document]`。
|
||||
- `**kwargs`: 接受可变数量的关键字参数,用于扩展或自定义功能。
|
||||
|
||||
**代码描述**:
|
||||
`do_add_doc`函数首先调用`_docs_to_embeddings`私有方法,将文档对象列表转化为向量化的数据,包括文本内容、向量化结果和元数据。这一步是为了准备将文档存储到向量数据库中,便于后续的检索和分析操作。
|
||||
|
||||
接下来,函数为每个文档生成一个唯一的ID(使用`uuid.uuid1()`方法),并通过遍历每个文档的向量化数据,调用`collection.add`方法将文档的ID、向量化结果、元数据和文本内容添加到数据库的集合中。每次添加操作后,函数会将文档的ID和元数据收集到`doc_infos`列表中。
|
||||
|
||||
最后,函数返回`doc_infos`列表,其中包含了每个添加到数据库中的文档的ID和元数据信息,为后续的文档管理和检索提供了便利。
|
||||
|
||||
**注意**:
|
||||
- 确保传入的`docs`参数是有效的文档对象列表,且每个文档对象都应包含必要的内容和元数据。
|
||||
- `_docs_to_embeddings`方法依赖于特定的文档向量化模型,因此在使用`do_add_doc`函数之前,应确保相关的向量化模型已经被正确设置和初始化。
|
||||
- 生成的文档ID是基于时间戳的UUID,保证了每个文档的唯一性。
|
||||
|
||||
**输出示例**:
|
||||
调用`do_add_doc(docs=[Document1, Document2])`可能会返回如下列表:
|
||||
```python
|
||||
[
|
||||
{"id": "文档1的UUID", "metadata": {"title": "文档1标题"}},
|
||||
{"id": "文档2的UUID", "metadata": {"title": "文档2标题"}}
|
||||
]
|
||||
```
|
||||
这个列表包含了每个添加到数据库中的文档的唯一ID和元数据信息,便于后续的文档管理和检索操作。
|
||||
***
|
||||
### FunctionDef get_doc_by_ids(self, ids)
|
||||
**get_doc_by_ids**: 该函数的功能是根据一组ID从数据库中查询并返回对应的文档对象列表。
|
||||
|
||||
**参数**:
|
||||
- `ids`: `List[str]`类型,表示需要查询的文档ID列表。
|
||||
|
||||
**代码描述**:
|
||||
`get_doc_by_ids`方法是`ChromaKBService`类的一部分,负责根据给定的ID列表从数据库中检索文档。该方法首先调用集合的`get`方法,传入ID列表作为参数,以从数据库中获取对应的文档数据。获取的结果是`GetResult`类型,随后该方法调用`_get_result_to_documents`函数,将`GetResult`类型的查询结果转换为`Document`对象列表。
|
||||
|
||||
`_get_result_to_documents`函数详细处理了如何从`GetResult`类型的查询结果中提取文档内容和元数据,并将它们封装成`Document`对象。这一过程包括检查查询结果中的`documents`和`metadatas`字段,确保每个文档都能正确地与其元数据对应,并最终生成一个包含所有查询到的文档的`Document`对象列表。
|
||||
|
||||
通过这种方式,`get_doc_by_ids`方法能够提供一个高效且方便的接口,用于根据文档ID查询并获取文档内容及其元数据,进而支持后续的文档处理或响应客户端请求。
|
||||
|
||||
**注意**:
|
||||
- 传入的ID列表应确保有效,以避免查询不到文档或产生异常。
|
||||
- 该方法依赖于`_get_result_to_documents`函数正确处理查询结果,因此需要保证`GetResult`类型的数据结构与预期匹配。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
Document(page_content="文档内容1", metadata={"作者": "张三"}),
|
||||
Document(page_content="文档内容2", metadata={"作者": "李四"})
|
||||
]
|
||||
```
|
||||
此示例展示了当根据给定的ID列表查询数据库并处理结果时,`get_doc_by_ids`方法可能返回的`Document`对象列表的形态。每个`Document`对象包含了文档的内容(`page_content`)和元数据(`metadata`)。
|
||||
***
|
||||
### FunctionDef del_doc_by_ids(self, ids)
|
||||
**del_doc_by_ids**: 此函数的功能是根据提供的ID列表删除数据库中的文档。
|
||||
|
||||
**参数**:
|
||||
- ids: 一个字符串列表,包含要删除的文档的ID。
|
||||
|
||||
**代码描述**:
|
||||
`del_doc_by_ids`函数接受一个参数`ids`,这是一个字符串列表,每个字符串代表一个需要从数据库中删除的文档的ID。函数内部调用`self.collection.delete`方法,将`ids`作为参数传递给该方法,以便删除对应的文档。完成删除操作后,函数返回`True`,表示文档已成功删除。
|
||||
|
||||
**注意**:
|
||||
- 确保传递给`del_doc_by_ids`函数的`ids`列表中的每个ID都是有效且存在于数据库中的,否则可能会导致删除操作失败或不完全。
|
||||
- 此函数总是返回`True`,即使某些ID可能因为不存在而没有被实际删除。因此,调用者可能需要额外的逻辑来验证删除操作的实际效果。
|
||||
|
||||
**输出示例**:
|
||||
由于此函数返回的是一个布尔值,因此调用`del_doc_by_ids(['123', '456'])`后,预期的返回值为:
|
||||
```
|
||||
True
|
||||
```
|
||||
这表示指定的文档已被成功删除。
|
||||
***
|
||||
### FunctionDef do_clear_vs(self)
|
||||
**do_clear_vs**: 此函数的功能是清空向量存储。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_clear_vs`函数是ChromaKBService类中的一个方法,其主要作用是清空向量存储。在实现上,它通过调用`do_drop_kb`方法来达到清空向量存储的目的。根据`do_drop_kb`方法的文档描述,我们知道`do_drop_kb`的功能是删除ChromaDB中的一个集合。因此,`do_clear_vs`通过删除集合的方式来清空向量存储,这可能是因为直接删除集合比尝试清空其内容来得更为高效或者更符合业务逻辑。在调用`do_drop_kb`时,会尝试删除一个名为`kb_name`的集合,如果在删除过程中遇到`ValueError`异常,并且异常信息不是因为集合不存在,则这个异常将会被重新抛出。这种设计确保了只有在遇到预期之外的错误时,才会中断程序的执行。
|
||||
|
||||
**注意**: 在使用`do_clear_vs`函数时,需要确保`self.kb_name`已经正确设置为目标集合的名称。此外,考虑到删除集合是一个不可逆的操作,应当谨慎使用此函数,确保其调用是在适当的上下文中,并且符合业务逻辑的需求。由于`do_clear_vs`函数的实现依赖于`do_drop_kb`,因此在使用`do_clear_vs`时也应当准备好处理可能由`do_drop_kb`抛出的`ValueError`异常,特别是在集合可能不存在的情况下。
|
||||
***
|
||||
### FunctionDef do_delete_doc(self, kb_file)
|
||||
**do_delete_doc**: 此函数用于删除知识库中的指定文件。
|
||||
|
||||
**参数**:
|
||||
- `kb_file`: KnowledgeFile对象,代表要删除的知识库文件。
|
||||
- `**kwargs`: 接收额外的关键字参数,可用于扩展功能或传递额外信息。
|
||||
|
||||
**代码描述**:
|
||||
`do_delete_doc`函数是`ChromaKBService`类的一个方法,负责从知识库中删除指定的文件。该方法接收一个`KnowledgeFile`对象作为参数,该对象包含了要删除文件的详细信息,包括文件的路径等。函数内部通过调用`self.collection.delete`方法来执行删除操作,其中`where`参数用于指定删除条件,本例中以文件的路径(`kb_file.filepath`)作为删除的依据。
|
||||
|
||||
在项目的层次结构中,`KnowledgeFile`对象由`server/knowledge_base/utils.py`中定义,它封装了与知识库文件相关的信息和操作。`do_delete_doc`方法通过使用这个对象,可以精确地定位并操作知识库中的特定文件,实现了文件的删除功能。
|
||||
|
||||
此方法的实现依赖于`collection`对象的`delete`方法,该方法是对数据库操作的抽象,允许通过指定条件来删除记录。在本项目中,`collection`很可能代表了一个封装了数据库操作的类实例,用于管理知识库中的数据记录。
|
||||
|
||||
**注意**:
|
||||
- 在调用`do_delete_doc`方法时,需要确保传入的`kb_file`对象有效,并且其`filepath`属性正确指向了要删除的文件路径。
|
||||
- 该方法的执行结果依赖于`collection.delete`方法的实现,因此在不同的数据库或数据存储方案中,其具体行为可能会有所不同。
|
||||
- 删除操作是不可逆的,因此在执行前应确保文件确实不再需要,以避免数据丢失。
|
||||
|
||||
**输出示例**:
|
||||
由于`do_delete_doc`方法的主要作用是从数据库中删除记录,其返回值取决于`collection.delete`方法的实现。通常,该方法可能会返回一个表示删除操作结果的对象或布尔值。例如,如果删除成功,可能会返回`True`或者一个包含删除成功信息的对象;如果删除失败,可能会返回`False`或者一个包含错误信息的对象。
|
||||
***
|
||||
@ -0,0 +1,138 @@
|
||||
## ClassDef DefaultKBService
|
||||
**DefaultKBService**: DefaultKBService 类是用于提供默认的知识库服务实现。
|
||||
|
||||
**属性**:
|
||||
此类继承自KBService,因此继承了KBService的所有属性,包括知识库名称(kb_name)、知识库信息(kb_info)、嵌入模型名称(embed_model)、知识库路径(kb_path)和文档路径(doc_path)等。
|
||||
|
||||
**代码描述**:
|
||||
DefaultKBService 类是KBService的一个具体实现,提供了对知识库的基本操作,包括创建知识库、删除知识库、向知识库添加文档、清空知识库、获取知识库类型、初始化知识库、搜索知识库、批量插入知识、单个插入知识和删除文档等方法。这些方法在DefaultKBService中大多以空方法(pass)的形式存在,意味着需要由继承DefaultKBService的子类来具体实现这些方法的功能。
|
||||
|
||||
DefaultKBService通过继承KBService类,确保了与其他知识库服务实现相同的接口,这样做的目的是为了提供一种默认的知识库服务实现,方便在没有指定具体知识库服务类型时使用。
|
||||
|
||||
**注意**:
|
||||
- DefaultKBService类本身大多数方法未具体实现(使用pass),需要通过继承此类并重写这些方法来提供具体的功能。
|
||||
- 在使用DefaultKBService或其子类时,需要确保已经正确配置了知识库的相关信息,如知识库名称、嵌入模型名称等。
|
||||
- DefaultKBService类的实例化通常由KBServiceFactory类的get_service方法根据配置动态完成,而不是直接在代码中实例化。
|
||||
|
||||
**输出示例**:
|
||||
由于DefaultKBService类的方法大多未具体实现,因此没有直接的输出示例。具体的输出将取决于继承DefaultKBService的子类以及这些子类实现的方法。例如,如果子类实现了do_search方法,那么搜索文档的输出示例可能如下:
|
||||
```python
|
||||
[
|
||||
{"id": "doc1", "text": "文档1的内容", "score": 0.95},
|
||||
{"id": "doc2", "text": "文档2的内容", "score": 0.90}
|
||||
]
|
||||
```
|
||||
这表示在执行搜索操作时,返回了两个文档及其相关性得分。
|
||||
### FunctionDef do_create_kb(self)
|
||||
**do_create_kb**: 此函数的功能是创建知识库。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_create_kb` 函数是 `DefaultKBService` 类的一个方法,旨在创建一个知识库。在当前的代码实现中,此函数体为空,这意味着它尚未实现具体的功能。在实际应用中,开发者需要在此函数中添加创建知识库的逻辑,例如初始化知识库的结构,存储知识库的数据,或者配置知识库的相关设置等。此函数作为一个框架或者占位符存在,供将来扩展和具体实现使用。
|
||||
|
||||
**注意**: 使用此函数时,需要注意以下几点:
|
||||
- 由于当前函数体为空,直接调用此函数不会有任何效果。开发者需要根据具体需求,实现知识库的创建逻辑。
|
||||
- 在实现函数逻辑时,应考虑知识库的安全性、可扩展性和性能等因素,确保知识库的稳定和高效运行。
|
||||
- 如果项目中已经有现成的知识库服务或框架,开发者应评估是否直接使用或扩展现有服务,以避免重复工作和提高开发效率。
|
||||
***
|
||||
### FunctionDef do_drop_kb(self)
|
||||
**do_drop_kb**: 此函数的功能是删除知识库。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_drop_kb` 函数是 `DefaultKBService` 类的一个方法,用于实现知识库的删除操作。在当前的代码实现中,此函数体为空(使用了 `pass` 语句),这意味着它没有执行任何操作。在实际应用中,开发者需要在此函数中添加逻辑来实现知识库的具体删除操作,例如从数据库中删除知识库相关的数据或清理知识库使用的资源等。
|
||||
|
||||
**注意**: 虽然当前的实现为空,但开发者在使用此函数时应当注意,删除知识库是一个重要操作,可能会对系统中存储的数据产生不可逆的影响。因此,在实现和调用此函数时,应确保有充分的权限检查和必要的数据备份机制,以防止数据丢失或错误删除。此外,考虑到操作的敏感性,可能还需要实现相应的日志记录功能,以便于问题的追踪和审计。
|
||||
***
|
||||
### FunctionDef do_add_doc(self, docs)
|
||||
**do_add_doc**: 此函数的功能是向知识库中添加文档。
|
||||
|
||||
**参数**:
|
||||
- `docs`: 需要添加到知识库中的文档列表,类型为`List[Document]`。
|
||||
|
||||
**代码描述**:
|
||||
`do_add_doc`函数是`DefaultKBService`类的一个方法,旨在实现将一系列文档(`docs`)添加到知识库中的功能。该方法接受一个参数`docs`,这是一个`Document`对象的列表。每个`Document`对象代表了一个需要被添加到知识库的文档。
|
||||
|
||||
在当前的代码实现中,`do_add_doc`方法的具体逻辑尚未实现,仅提供了方法的定义和参数接收的框架。这意味着,如果你需要使用这个方法来向知识库添加文档,你需要在此基础上实现具体的添加文档到知识库的逻辑。
|
||||
|
||||
**注意**:
|
||||
- 在实际使用`do_add_doc`方法之前,需要确保每个`Document`对象都已经正确构造,并包含了所有必要的信息,以便能够被成功添加到知识库中。
|
||||
- 由于当前的实现是空的,调用此方法不会有任何实际效果,直到你实现了添加文档到知识库的具体逻辑。
|
||||
- 在实现具体逻辑时,需要考虑如何处理文档添加过程中可能出现的异常情况,例如文档格式不正确或添加到知识库失败等。
|
||||
***
|
||||
### FunctionDef do_clear_vs(self)
|
||||
**do_clear_vs**: 此函数的功能是清除视图状态。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_clear_vs`函数是`DefaultKBService`类的一个成员方法,目前其内部实现为空,即该方法被调用时不会执行任何操作。在`DefaultKBService`类中,此方法可能被设计为用于清除或重置与知识库服务相关的某些视图状态,但具体的实现细节尚未提供。这种设计通常用于在需要时重置服务的状态,或者在某些操作完成后清理资源。
|
||||
|
||||
**注意**: 虽然当前`do_clear_vs`方法的实现为空,但开发者在使用此方法时应注意其未来可能的更新或实现。在调用此方法之前,建议检查相关的文档或更新日志,以了解其最新的功能和使用方式。此外,由于该方法目前不执行任何操作,开发者应避免在生产环境中不必要地调用它,以免在未来的版本中引入潜在的副作用或性能问题。
|
||||
***
|
||||
### FunctionDef vs_type(self)
|
||||
**vs_type函数功能**: 返回当前知识库服务的类型。
|
||||
|
||||
**参数**: 此函数不接受任何参数。
|
||||
|
||||
**代码描述**: `vs_type`函数是`DefaultKBService`类的一个方法,用于标识当前使用的知识库服务类型。在这个上下文中,它被设计为返回一个字符串值`"default"`,意味着如果没有特别指定,将使用默认的知识库服务类型。这个设计允许在系统中可能存在多种知识库服务类型时,能够灵活地指定和使用不同的服务类型。通过返回一个明确的字符串标识符,系统的其他部分可以根据这个标识符来决定如何与知识库服务交互。
|
||||
|
||||
**注意**: 在使用`vs_type`方法时,需要注意它是如何与系统中其他部分的逻辑配合工作的。因为它返回一个固定的字符串值,如果系统扩展了更多的知识库服务类型,可能需要更新此方法以反映新的服务类型。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
"default"
|
||||
```
|
||||
这个输出示例展示了调用`vs_type`方法时会收到的返回值。在当前的实现中,每次调用此方法都会返回字符串`"default"`,表示使用默认的知识库服务类型。
|
||||
***
|
||||
### FunctionDef do_init(self)
|
||||
**do_init**: 此函数的功能是初始化DefaultKBService类的实例。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_init`函数是`DefaultKBService`类中的一个方法,目前其内部实现为空,即没有执行任何操作。这通常意味着该方法是为了将来的扩展而预留的,或者作为一个接口的一部分,具体的实现将在子类中完成。在面向对象编程中,这样的设计允许开发者在不修改现有代码的情况下,通过继承和重写方法来扩展功能。
|
||||
|
||||
**注意**: 虽然当前`do_init`方法没有执行任何操作,但在将来的开发中,如果需要对`DefaultKBService`类的实例进行初始化设置,比如配置参数的加载、资源的分配等,都可以在此方法中实现。因此,开发者在使用`DefaultKBService`类时,应当注意到`do_init`方法可能会在未来包含重要的初始化逻辑,应当在创建实例后调用它,以确保对象正确地被初始化。
|
||||
***
|
||||
### FunctionDef do_search(self)
|
||||
**do_search**: 此函数的功能是执行搜索操作。
|
||||
|
||||
**参数**: 此函数目前没有定义任何参数。
|
||||
|
||||
**代码描述**: `do_search` 函数是 `DefaultKBService` 类的一个成员方法,旨在实现搜索功能。根据函数体的实现,当前此函数体为空,即它未执行任何操作。这通常意味着该函数是一个待实现的功能桩,预留给开发者后续根据具体需求实现搜索逻辑。在实际应用中,开发者可能需要根据特定的搜索需求,如关键词搜索、模糊搜索或其他高级搜索功能,来填充此函数体。例如,可以通过查询数据库、调用外部搜索服务或应用搜索算法来实现具体的搜索逻辑。
|
||||
|
||||
**注意**: 虽然当前 `do_search` 函数未具体实现任何逻辑,但在将来的开发中,开发者应确保为其添加适当的参数和返回值,以满足搜索功能的需求。此外,考虑到性能和准确性是搜索功能的关键,开发时应注意优化搜索算法和处理大量数据的能力。在实现具体逻辑之前,建议先定义好函数的输入输出规范,以及可能涉及的错误处理机制。
|
||||
***
|
||||
### FunctionDef do_insert_multi_knowledge(self)
|
||||
**do_insert_multi_knowledge**: 此函数的功能是批量插入多条知识数据。
|
||||
|
||||
**参数**: 此函数目前不接受任何参数。
|
||||
|
||||
**代码描述**: `do_insert_multi_knowledge` 函数是 `DefaultKBService` 类的一个方法,设计用于处理批量插入知识数据的操作。当前,该函数的实现为空(使用了 `pass` 语句),这意味着它尚未实现具体的功能。在未来的开发中,此函数可能会被扩展以接受参数,如知识数据列表,并将这些数据批量插入到知识库中。这种批量插入操作通常比单条插入更高效,特别是当需要向知识库中添加大量数据时。
|
||||
|
||||
**注意**:
|
||||
- 由于当前 `do_insert_multi_knowledge` 函数的实现为空,调用此函数不会产生任何效果。开发者在使用此函数之前需要实现具体的插入逻辑。
|
||||
- 在实现批量插入逻辑时,需要考虑到数据的一致性和事务管理,确保数据的准确性和完整性。
|
||||
- 开发者在扩展此函数以实现具体功能时,应考虑到性能优化,例如,使用批处理技术减少数据库访问次数,提高数据插入效率。
|
||||
- 此函数在未来可能会更新以接受参数和返回值,开发者在使用时应关注相关文档的更新,以便正确使用。
|
||||
***
|
||||
### FunctionDef do_insert_one_knowledge(self)
|
||||
**do_insert_one_knowledge**: 此函数的功能是插入单条知识记录。
|
||||
|
||||
**参数**: 此函数目前不接受任何参数。
|
||||
|
||||
**代码描述**: `do_insert_one_knowledge` 函数是 `DefaultKBService` 类的一个成员方法,旨在向知识库中插入一条新的知识记录。当前版本的函数体为空,这意味着它尚未实现具体的插入逻辑。在未来的版本中,此函数可能会被扩展以包含与数据库交互的代码,用于实际将知识记录插入到后端存储系统中。这可能涉及到构造数据库查询、处理数据模型以及管理数据库连接和事务等操作。
|
||||
|
||||
**注意**:
|
||||
- 由于当前函数体为空,调用此函数不会产生任何效果。开发者在使用此函数时需要注意其实现状态,避免在生产环境中直接使用尚未完成的功能。
|
||||
- 在未来的实现中,开发者可能需要关注函数参数的设计,以便能够灵活地传递要插入的知识记录数据。
|
||||
- 此外,考虑到数据的一致性和完整性,实现此功能时可能需要处理错误和异常情况,确保知识记录的正确插入。
|
||||
***
|
||||
### FunctionDef do_delete_doc(self)
|
||||
**do_delete_doc**: 此函数的功能是删除文档。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_delete_doc` 函数是 `DefaultKBService` 类的一个方法,目前其内部实现为空,即函数体中没有任何执行代码。这通常意味着该方法是一个待实现的功能占位符,或者在当前版本的代码中,删除文档的具体逻辑尚未被定义。在面向对象编程中,这种做法常用于定义接口或抽象类,预留方法供子类实现具体功能。然而,根据此函数所在的上下文——位于`default_kb_service.py`文件中的`DefaultKBService`类,我们可以推断`do_delete_doc`方法旨在提供一个删除知识库中特定文档的功能。在未来的版本中,开发者可能会在此方法中添加代码来实现从数据库或存储系统中删除特定文档的逻辑。
|
||||
|
||||
**注意**: 虽然当前`do_delete_doc`方法的实现为空,但在使用此方法之前,开发者应确保理解其预期的功能和实现逻辑。如果你是负责扩展或维护`DefaultKBService`类的开发者,那么在实现`do_delete_doc`方法时,需要考虑如何安全有效地从你的知识库服务中删除数据,包括处理可能的依赖关系和确保数据一致性等问题。此外,考虑到数据的重要性,实现删除功能时应提供充分的错误处理和日志记录,以便跟踪和恢复意外删除的数据。
|
||||
***
|
||||
282
markdown_docs/server/knowledge_base/kb_service/es_kb_service.md
Normal file
@ -0,0 +1,282 @@
|
||||
## ClassDef ESKBService
|
||||
**ESKBService**: ESKBService 类用于实现基于 Elasticsearch 的知识库服务。
|
||||
|
||||
**属性**:
|
||||
- `kb_path`: 知识库路径。
|
||||
- `index_name`: Elasticsearch 索引名称。
|
||||
- `IP`: Elasticsearch 服务的 IP 地址。
|
||||
- `PORT`: Elasticsearch 服务的端口号。
|
||||
- `user`: 连接 Elasticsearch 服务的用户名。
|
||||
- `password`: 连接 Elasticsearch 服务的密码。
|
||||
- `dims_length`: 向量的维度。
|
||||
- `embeddings_model`: 本地加载的嵌入模型。
|
||||
- `es_client_python`: Elasticsearch 的 Python 客户端实例。
|
||||
- `db_init`: 用于初始化和创建索引的 ElasticsearchStore 实例。
|
||||
|
||||
**代码描述**:
|
||||
ESKBService 类继承自 KBService 类,专门用于操作和管理基于 Elasticsearch 的知识库。它提供了一系列方法来初始化服务、创建知识库、添加文档、删除文档、搜索文档等。
|
||||
|
||||
- `do_init` 方法用于初始化 Elasticsearch 客户端,包括连接到 Elasticsearch 服务、创建索引等。
|
||||
- `get_kb_path` 和 `get_vs_path` 静态方法用于获取知识库路径和向量存储路径。
|
||||
- `do_create_kb` 方法用于创建知识库,如果知识库路径不存在,则创建之。
|
||||
- `vs_type` 方法返回支持的向量存储类型,即 Elasticsearch。
|
||||
- `_load_es` 方法用于将文档加载到 Elasticsearch 中。
|
||||
- `do_search` 方法用于执行文本相似性搜索。
|
||||
- `get_doc_by_ids` 方法根据文档 ID 获取文档。
|
||||
- `del_doc_by_ids` 方法根据文档 ID 删除文档。
|
||||
- `do_delete_doc` 方法用于从知识库中删除指定的文档。
|
||||
- `do_add_doc` 方法用于向知识库添加文档。
|
||||
- `do_clear_vs` 方法用于从知识库中删除所有向量。
|
||||
- `do_drop_kb` 方法用于删除整个知识库。
|
||||
|
||||
**注意**:
|
||||
- 在使用 ESKBService 类之前,需要确保 Elasticsearch 服务已经启动并可访问。
|
||||
- 用户名和密码是可选的,如果 Elasticsearch 服务没有设置认证,可以不提供。
|
||||
- 创建索引时,需要指定向量的维度,这对于后续的向量搜索非常重要。
|
||||
|
||||
**输出示例**:
|
||||
由于 ESKBService 类主要与 Elasticsearch 交互,它的方法通常不直接返回具体的输出,而是影响 Elasticsearch 中的数据。例如,`do_add_doc` 方法成功执行后,将在 Elasticsearch 中创建或更新文档,但不会返回具体的输出。搜索方法 `do_search` 可能会返回如下格式的文档列表:
|
||||
```python
|
||||
[
|
||||
{"id": "doc1", "text": "文档1的内容", "score": 0.95},
|
||||
{"id": "doc2", "text": "文档2的内容", "score": 0.90}
|
||||
]
|
||||
```
|
||||
这表示在执行搜索操作时,返回了两个文档及其相关性得分。
|
||||
### FunctionDef do_init(self)
|
||||
**do_init**: 此函数的功能是初始化ESKBService类的实例,包括配置知识库路径、索引名称、连接Elasticsearch服务的参数以及加载本地嵌入模型。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `do_init` 方法首先通过调用 `get_kb_path` 方法获取知识库的完整路径,并从该路径中提取索引名称。然后,它根据 `vs_type` 方法返回的向量存储类型,从配置文件中获取Elasticsearch服务的主机地址、端口、用户、密码和向量维度长度。接着,`do_init` 方法使用 `load_local_embeddings` 函数加载本地嵌入模型,以支持后续的向量搜索功能。
|
||||
|
||||
此外,`do_init` 方法尝试建立与Elasticsearch服务的连接。如果提供了用户名和密码,则使用基本认证;否则,发出警告并尝试无认证连接。连接成功后,尝试创建Elasticsearch索引,如果遇到BadRequestError异常,则记录错误信息。
|
||||
|
||||
最后,`do_init` 方法尝试通过 `ElasticsearchStore` 类的实例 `db_init` 初始化Elasticsearch连接和索引,这一步骤同样考虑了认证信息。如果在任何连接尝试中遇到 `ConnectionError` 或其他异常,将记录错误信息并抛出异常。
|
||||
|
||||
**注意**:
|
||||
- 在调用 `do_init` 方法之前,确保已经正确配置了Elasticsearch服务的相关参数,包括主机地址、端口、用户、密码等。
|
||||
- `do_init` 方法在ESKBService类的实例化过程中自动调用,用于准备Elasticsearch服务的连接和配置,因此在使用ESKBService类之前不需要手动调用此方法。
|
||||
- 如果在连接Elasticsearch服务或创建索引时遇到问题,`do_init` 方法将记录错误信息并抛出异常,调用方应捕获并处理这些异常。
|
||||
- `do_init` 方法依赖于 `load_local_embeddings` 函数加载的本地嵌入模型,确保嵌入模型与Elasticsearch服务的向量搜索功能兼容。
|
||||
***
|
||||
### FunctionDef get_kb_path(knowledge_base_name)
|
||||
**get_kb_path**: 此函数的功能是获取知识库的完整路径。
|
||||
|
||||
**参数**:
|
||||
- knowledge_base_name: 字符串类型,代表知识库的名称。
|
||||
|
||||
**代码描述**:
|
||||
`get_kb_path` 函数接受一个参数 `knowledge_base_name`,这是一个字符串,代表知识库的名称。函数使用 `os.path.join` 方法将 `KB_ROOT_PATH`(一个在代码中预定义的常量,代表知识库根目录的路径)与 `knowledge_base_name` 拼接,从而构造出该知识库的完整路径。这个函数在项目中被用于构建知识库路径,以便于其他操作(如初始化、索引创建等)能够在正确的位置进行。
|
||||
|
||||
在项目中,`get_kb_path` 函数被 `do_init` 方法调用,用于确定知识库的存储路径,并据此设置索引名称和其他与 Elasticsearch 服务相关的配置。此外,它还被 `get_vs_path` 方法调用,后者进一步在知识库路径的基础上添加 "vector_store" 子目录,用于特定的向量存储操作。这表明 `get_kb_path` 函数是连接知识库基础设施与 Elasticsearch 服务操作的关键环节。
|
||||
|
||||
**注意**:
|
||||
- 确保 `KB_ROOT_PATH` 已经正确设置,且指向一个有效的文件系统路径,否则构建的知识库路径可能无效。
|
||||
- 在调用此函数之前,应确保传入的 `knowledge_base_name` 是唯一的,以避免路径冲突。
|
||||
|
||||
**输出示例**:
|
||||
如果 `KB_ROOT_PATH` 设置为 "/data/knowledge_bases",且传入的 `knowledge_base_name` 为 "my_kb",则函数返回的路径将会是 "/data/knowledge_bases/my_kb"。
|
||||
***
|
||||
### FunctionDef get_vs_path(knowledge_base_name)
|
||||
**get_vs_path**: 此函数的功能是获取知识库中向量存储的完整路径。
|
||||
|
||||
**参数**:
|
||||
- knowledge_base_name: 字符串类型,代表知识库的名称。
|
||||
|
||||
**代码描述**:
|
||||
`get_vs_path` 函数是用于构建知识库中向量存储位置的路径。它接受一个参数 `knowledge_base_name`,这是一个字符串,指定了知识库的名称。函数首先调用 `get_kb_path` 方法,该方法根据传入的知识库名称构建出知识库的根路径。然后,`get_vs_path` 函数使用 `os.path.join` 方法将这个根路径与 "vector_store" 字符串拼接,从而生成并返回向量存储的完整路径。
|
||||
|
||||
从功能角度来看,`get_vs_path` 函数与其调用的 `get_kb_path` 函数紧密相关。`get_kb_path` 提供了知识库的基础路径,而 `get_vs_path` 在此基础上进一步定位到知识库中用于存储向量数据的特定子目录。这种设计使得知识库的结构更加清晰,同时也便于管理和访问知识库中的向量数据。
|
||||
|
||||
**注意**:
|
||||
- 在使用 `get_vs_path` 函数之前,应确保传入的知识库名称 `knowledge_base_name` 是准确且存在的,因为这将直接影响到向量存储路径的正确性。
|
||||
- 由于 `get_vs_path` 函数依赖于 `get_kb_path` 函数来获取知识库的根路径,因此需要保证 `get_kb_path` 函数能够正常工作,包括确保知识库根目录的路径(`KB_ROOT_PATH`)已经被正确设置。
|
||||
|
||||
**输出示例**:
|
||||
假设知识库的根目录路径为 "/data/knowledge_bases",且传入的知识库名称为 "my_kb",那么 `get_vs_path` 函数将返回的路径将会是 "/data/knowledge_bases/my_kb/vector_store"。这个路径指向了 "my_kb" 知识库中用于存储向量数据的子目录。
|
||||
***
|
||||
### FunctionDef do_create_kb(self)
|
||||
**do_create_kb**: 此函数的功能是创建知识库所需的向量存储目录。
|
||||
|
||||
**参数**: 此函数没有参数。
|
||||
|
||||
**代码描述**: `do_create_kb` 函数首先检查文档路径(`self.doc_path`)是否存在。如果该路径存在,函数将继续检查知识库路径(`self.kb_path`)下是否存在名为 "vector_store" 的目录。如果 "vector_store" 目录不存在,则函数会在 `self.kb_path` 下创建该目录。如果 "vector_store" 目录已经存在,则会记录一条警告日志,提示目录已经存在。这个过程确保了知识库的向量存储目录被正确创建,以便后续操作可以在其中存储和管理知识库的向量数据。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用此函数之前,`self.doc_path` 和 `self.kb_path` 已经被正确设置,并且指向有效的文件系统路径。
|
||||
- 如果在创建 "vector_store" 目录时遇到文件系统权限问题,可能会导致目录创建失败。因此,确保应用程序具有足够的权限来创建和写入指定的路径。
|
||||
- 记录的警告信息可以帮助开发者了解知识库的当前状态,特别是在调试或者排查问题时。
|
||||
***
|
||||
### FunctionDef vs_type(self)
|
||||
**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。
|
||||
|
||||
**参数**: 该函数不接受任何参数。
|
||||
|
||||
**代码描述**: vs_type函数是ESKBService类的一个方法,它的主要作用是指明Elasticsearch (ES) 作为向量存储服务。该函数通过返回SupportedVSType枚举类中的ES属性值来实现这一点。在ESKBService类中,vs_type方法的返回值被用于配置和初始化Elasticsearch客户端,包括连接信息、索引名称、认证信息等。此外,vs_type方法的返回值还决定了向量维度长度、嵌入模型等配置的获取。这意味着,通过vs_type方法,ESKBService类能够明确其向量存储服务的类型,并据此进行相应的初始化和配置。
|
||||
|
||||
**注意**:
|
||||
- 在使用vs_type方法时,需要确保SupportedVSType枚举类中已定义了返回的向量存储类型,否则可能会影响知识库服务的初始化和配置。
|
||||
- vs_type方法的返回值直接影响到Elasticsearch客户端的配置,因此在修改该方法时应谨慎,以避免对知识库服务的正常操作产生不利影响。
|
||||
|
||||
**输出示例**: "es"
|
||||
***
|
||||
### FunctionDef _load_es(self, docs, embed_model)
|
||||
**_load_es**: 该函数的功能是将文档(docs)写入到Elasticsearch中。
|
||||
|
||||
**参数**:
|
||||
- docs: 需要写入Elasticsearch的文档列表。
|
||||
- embed_model: 用于生成文档嵌入向量的模型。
|
||||
|
||||
**代码描述**:
|
||||
`_load_es` 函数主要负责将一组文档(docs)通过嵌入模型(embed_model)处理后,写入到Elasticsearch数据库中。该函数首先检查是否提供了用户认证信息(用户名和密码),如果提供了,则使用这些信息来建立与Elasticsearch的安全连接。接着,根据是否提供了用户信息,选择相应的方式来初始化`ElasticsearchStore`对象,该对象负责将文档和它们的嵌入向量存储到指定的Elasticsearch索引中。在存储过程中,会设置一些参数,如索引名(`index_name`)、距离策略(`distance_strategy`)、查询字段(`query_field`)和向量查询字段(`vector_query_field`)等。
|
||||
|
||||
在存储文档到Elasticsearch的过程中,如果遇到连接错误(`ConnectionError`),会打印错误信息并记录日志。对于其他类型的异常,也会记录错误日志并打印异常信息。
|
||||
|
||||
该函数被`do_add_doc`方法调用,用于在向知识库添加文档的过程中,将文档写入Elasticsearch。`do_add_doc`方法首先打印待写入文档的数量,然后调用`_load_es`函数进行文档的写入操作。文档写入成功后,`do_add_doc`方法会继续执行一系列的操作,包括验证写入的文档是否能够被成功检索等。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用`_load_es`函数之前,`docs`参数中的文档已经准备好,并且`embed_model`模型能够正确生成文档的嵌入向量。
|
||||
- 在使用`_load_es`函数时,需要确保Elasticsearch服务是可用的,并且提供的用户认证信息(如果有的话)是正确的。
|
||||
- 该函数中捕获并处理了连接错误,但在实际使用中,还需要注意处理其他可能的异常情况,以确保系统的稳定性。
|
||||
***
|
||||
### FunctionDef do_search(self, query, top_k, score_threshold)
|
||||
**do_search**: 此函数用于执行基于文本相似性的搜索。
|
||||
|
||||
**参数**:
|
||||
- `query`: 字符串类型,表示搜索查询的文本。
|
||||
- `top_k`: 整型,指定返回的最相似文档数量。
|
||||
- `score_threshold`: 浮点型,设定的相似度分数阈值,用于过滤结果。
|
||||
|
||||
**代码描述**:
|
||||
`do_search` 函数通过接收一个查询字符串 `query`、一个整数 `top_k` 和一个浮点数 `score_threshold` 作为参数,执行文本相似性搜索。它首先调用 `db_init` 对象的 `similarity_search_with_score` 方法,该方法根据提供的查询 `query` 和指定的返回文档数量 `k=top_k` 来检索最相似的文档。此方法返回一个包含文档的列表,这些文档根据与查询的相似度得分进行排序。
|
||||
|
||||
**注意**:
|
||||
- 确保 `db_init` 已正确初始化并且可以访问相应的数据库或索引,以便执行相似性搜索。
|
||||
- `top_k` 应为正整数,表示需要返回的文档数量。
|
||||
- `score_threshold` 参数在此代码段中未直接使用,但可能在 `similarity_search_with_score` 方法内部用于过滤相似度得分低于某一阈值的文档。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
{'doc_id': '123', 'score': 0.95},
|
||||
{'doc_id': '456', 'score': 0.93},
|
||||
...
|
||||
]
|
||||
```
|
||||
此输出示例展示了一个可能的返回值,其中包含了文档的ID和与查询的相似度得分。返回的文档数量和具体得分取决于查询内容、`top_k` 的值以及数据库中存储的文档。
|
||||
***
|
||||
### FunctionDef get_doc_by_ids(self, ids)
|
||||
**get_doc_by_ids**: 此函数的功能是根据提供的文档ID列表从Elasticsearch中检索文档。
|
||||
|
||||
**参数**:
|
||||
- `ids`: 一个字符串列表,包含需要检索的文档的ID。
|
||||
|
||||
**代码描述**:
|
||||
`get_doc_by_ids` 函数接收一个文档ID列表作为输入参数,返回一个包含检索到的文档的列表。函数内部,通过遍历ID列表,使用Elasticsearch客户端的`get`方法根据每个ID检索文档。检索到的文档信息存储在变量`response`中,其中包含文档的源数据(`_source`)。函数假设每个文档包含`context`和`metadata`字段,分别用于存储文档的文本内容和元数据。如果检索成功,函数将创建一个`Document`对象,其中包含文档的文本内容和元数据,并将此对象添加到结果列表中。如果在检索过程中遇到异常,会通过日志记录错误信息,但不会中断整个检索过程。
|
||||
|
||||
**注意**:
|
||||
- 函数假设Elasticsearch中的文档具有`context`和`metadata`字段。如果文档结构不同,需要相应地调整源代码中的字段名称。
|
||||
- 在检索文档时遇到的任何异常都会被捕获并记录日志,但不会导致函数终止执行。这意味着即使某些文档ID可能因为错误而未能检索到文档,函数仍会继续尝试检索其余的文档ID。
|
||||
- 函数返回的是一个`Document`对象列表,每个对象包含一个文档的文本内容和元数据。如果某个文档ID检索失败,该ID对应的文档将不会出现在返回的列表中。
|
||||
|
||||
**输出示例**:
|
||||
假设有两个文档ID分别为"doc1"和"doc2",且这两个文档在Elasticsearch中成功检索到,函数可能返回如下列表:
|
||||
```python
|
||||
[
|
||||
Document(page_content="文档1的文本内容", metadata={"作者": "张三", "发布日期": "2023-01-01"}),
|
||||
Document(page_content="文档2的文本内容", metadata={"作者": "李四", "发布日期": "2023-02-01"})
|
||||
]
|
||||
```
|
||||
如果"doc2"的检索失败,那么返回的列表将只包含"doc1"对应的`Document`对象。
|
||||
***
|
||||
### FunctionDef del_doc_by_ids(self, ids)
|
||||
**del_doc_by_ids**: 此函数的功能是根据提供的文档ID列表删除Elasticsearch中的相应文档。
|
||||
|
||||
**参数**:
|
||||
- `ids`: 一个字符串列表,包含要从Elasticsearch中删除的文档的ID。
|
||||
|
||||
**代码描述**:
|
||||
`del_doc_by_ids`函数接收一个字符串列表`ids`作为参数,这个列表包含了需要从Elasticsearch索引中删除的文档的ID。函数遍历这个ID列表,对于列表中的每一个ID,它尝试使用`es_client_python.delete`方法从指定的索引`self.index_name`中删除对应的文档,并且设置`refresh=True`以确保删除操作立即生效。
|
||||
|
||||
如果在删除操作过程中遇到任何异常,函数会捕获这些异常并通过`logger.error`记录错误信息,包括异常的详细信息。这样做可以帮助开发者在出现问题时迅速定位和解决问题。
|
||||
|
||||
**注意**:
|
||||
- 确保在调用此函数之前,`self.es_client_python`已经被正确初始化,并且已经设置了正确的索引名称`self.index_name`。
|
||||
- 删除操作会立即影响Elasticsearch索引的状态,因此请谨慎使用此函数,确保不会误删除重要文档。
|
||||
- 如果提供的ID列表中包含不存在于索引中的ID,对应的删除操作将会被忽略,不会影响其他有效删除操作的执行。
|
||||
- 异常处理机制确保了函数的健壮性,但开发者应注意检查日志文件以了解是否有删除操作失败的情况,并根据需要采取相应措施。
|
||||
***
|
||||
### FunctionDef do_delete_doc(self, kb_file)
|
||||
**do_delete_doc**: 此函数的功能是从Elasticsearch索引中删除与给定知识库文件相关的文档。
|
||||
|
||||
**参数**:
|
||||
- `kb_file`: 需要删除的知识库文件对象,此对象应包含一个`filepath`属性,该属性用于在Elasticsearch中定位相关文档。
|
||||
- `**kwargs`: 关键字参数,用于提供额外的配置选项,虽然在当前实现中未直接使用,但保留了扩展性。
|
||||
|
||||
**代码描述**:
|
||||
此函数首先检查Elasticsearch中是否存在指定的索引。如果索引存在,它将构造一个查询,该查询使用`kb_file.filepath`作为关键字,查找所有与给定知识库文件路径匹配的文档。查询时,注意设置查询返回的文档数量`size`为50,这是为了确保能够找到所有相关的文档,而不是默认的前10个。
|
||||
|
||||
接下来,函数会从查询结果中提取文档的ID,并将这些ID存储在`delete_list`列表中。如果`delete_list`为空,即没有找到任何匹配的文档,函数将返回`None`。如果找到了匹配的文档,函数将遍历`delete_list`中的每个文档ID,并使用Elasticsearch的`delete`方法逐一删除这些文档。在删除过程中,如果遇到任何异常,将通过日志记录错误信息。
|
||||
|
||||
**注意**:
|
||||
- 确保`kb_file`对象有一个有效的`filepath`属性,因为它是定位和删除Elasticsearch中文档的关键。
|
||||
- 删除操作会即时刷新索引(通过`refresh=True`参数),这可能会对性能有一定影响,特别是在处理大量文档时。请根据实际情况评估是否需要即时刷新。
|
||||
- 异常处理部分仅记录错误信息,不会中断程序执行。开发者需要关注日志输出,以便了解删除操作是否遇到问题。
|
||||
|
||||
**输出示例**:
|
||||
此函数没有明确的返回值(在成功删除文档或没有找到匹配文档时返回`None`)。因此,函数的主要作用是执行操作,而不是返回数据。
|
||||
***
|
||||
### FunctionDef do_add_doc(self, docs)
|
||||
**do_add_doc**: 该函数的功能是向知识库添加文档。
|
||||
|
||||
**参数**:
|
||||
- docs: 文档列表,每个文档都是一个Document对象。
|
||||
- **kwargs: 接收可变数量的关键字参数。
|
||||
|
||||
**代码描述**:
|
||||
`do_add_doc` 函数首先打印输入的文档(docs)数量,然后调用 `_load_es` 方法将这些文档写入Elasticsearch。在文档写入过程中,会使用到`embeddings_model`模型来处理文档数据。文档成功写入后,函数会检查Elasticsearch索引是否存在,如果存在,则根据文档的`source`路径构造一个查询,以检索与该路径相匹配的文档。此查询默认返回最多50个结果。如果没有检索到任何文档,函数会抛出一个`ValueError`异常。最后,函数会从检索结果中提取文档的ID和元数据(metadata),并将这些信息以列表的形式返回。
|
||||
|
||||
该函数与 `_load_es` 方法的关系是,`do_add_doc` 调用 `_load_es` 方法来实现文档的写入操作。`_load_es` 方法负责将文档通过嵌入模型处理后,写入到Elasticsearch数据库中。这一步是`do_add_doc`实现其功能的关键部分。
|
||||
|
||||
**注意**:
|
||||
- 在调用`do_add_doc`函数之前,确保传入的`docs`参数中的文档已经准备好。
|
||||
- 该函数依赖于Elasticsearch的索引设置和查询功能,因此在使用前需要确保Elasticsearch服务是可用的,并且相关索引已经正确设置。
|
||||
- 函数中的错误处理包括检查召回元素个数是否为0,这是为了确保写入的文档能够被成功检索。在实际应用中,可能还需要考虑其他的异常情况。
|
||||
|
||||
**输出示例**:
|
||||
```python
|
||||
[
|
||||
{"id": "文档ID1", "metadata": {"source": "文档源路径1", "其他元数据": "值"}},
|
||||
{"id": "文档ID2", "metadata": {"source": "文档源路径2", "其他元数据": "值"}},
|
||||
...
|
||||
]
|
||||
```
|
||||
此输出示例展示了函数返回值的可能形式,即一个包含多个字典的列表,每个字典代表一个文档的ID和元数据信息。
|
||||
***
|
||||
### FunctionDef do_clear_vs(self)
|
||||
**do_clear_vs**: 该函数的功能是从知识库删除全部向量。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `do_clear_vs` 函数是 `ESKBService` 类的一个方法,用于从Elasticsearch知识库中删除所有的向量数据。首先,该函数通过调用 `self.es_client_python.indices.exists` 方法检查指定的索引(即知识库名称,存储在 `self.kb_name` 中)是否存在。如果索引存在,那么通过调用 `self.es_client_python.indices.delete` 方法删除该索引及其包含的所有数据。这一操作将清空知识库中存储的全部向量数据,实现知识库的初始化或清理。
|
||||
|
||||
**注意**:
|
||||
- 在执行此函数之前,确保已经正确设置了 `self.es_client_python` 和 `self.kb_name` 属性。`self.es_client_python` 应为一个有效的Elasticsearch客户端实例,而 `self.kb_name` 应为一个字符串,表示要操作的Elasticsearch索引名称。
|
||||
- 删除索引是一个不可逆的操作,一旦执行,索引中的所有数据将被永久删除。因此,在调用此函数之前,请确保已经做好了相应的数据备份或确认不再需要索引中的数据。
|
||||
- 由于这个操作会影响到整个知识库的数据,建议在执行此操作前进行充分的测试和评估,确保其对系统的影响是可接受的。
|
||||
***
|
||||
### FunctionDef do_drop_kb(self)
|
||||
**do_drop_kb**: 此函数用于删除知识库。
|
||||
|
||||
**参数**: 此函数不接受任何外部参数。
|
||||
|
||||
**代码描述**: `do_drop_kb` 函数是 `ESKBService` 类的一个方法,旨在删除指定的知识库目录。该函数首先检查 `self.kb_path`(知识库路径)是否存在。如果该路径存在,则使用 `shutil.rmtree` 方法删除该路径及其下的所有内容。这里的 `self.kb_path` 是一个类属性,代表了知识库文件存储的路径。
|
||||
|
||||
具体步骤如下:
|
||||
1. 通过 `self.kb_path` 获取知识库的存储路径。
|
||||
2. 使用 `os.path.exists` 函数检查该路径是否存在。
|
||||
3. 如果路径存在,调用 `shutil.rmtree` 函数删除该路径及其包含的所有文件和子目录。
|
||||
|
||||
**注意**: 在使用此函数删除知识库之前,确保已经做好了相应的数据备份,以防不小心删除重要数据。此外,此操作不可逆,请谨慎操作。
|
||||
***
|
||||