This commit is contained in:
jack ning
2025-08-09 21:01:27 +08:00
parent 9bed8249d6
commit 823d8f4661
77 changed files with 1 additions and 269365 deletions

View File

@@ -23,6 +23,7 @@ target/
/nbproject/private/
/nbbuild/
/dist/
bin/
/nbdist/
/.nb-gradle/
build/

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e63a53cfb9c4d291ebe3c2b0edacb7622bbc480326beaa5a0456e412f52f066a
size 62547

View File

@@ -1,2 +0,0 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +0,0 @@
# SpringAI RAG Controller 重构说明
## 问题描述
原有的 `SpringAIRagController` 使用了特定的 `OllamaChatModel`,当 Ollama 没有启用时会导致以下错误:
```
Parameter 2 of constructor in com.bytedesk.ai.springai.rag.SpringAIRagController required a bean of type 'org.springframework.ai.ollama.OllamaChatModel' that could not be found.
```
## 解决方案
将特定的 `OllamaChatModel` 替换为通用的 `ChatModel` 接口,使控制器能够适配任何 ChatModel 实现。
## 主要更改
### 1. SpringAIRagController.java
- **字段更改**: 将 `private final OllamaChatModel bytedeskOllamaChatModel` 改为 `private final ChatModel chatModel`
- **导入更改**: 移除 `OllamaChatModel` 导入,添加 `ChatModel` 导入
- **注解更改**: 添加 `@ConditionalOnBean(ChatModel.class)` 确保只有在有 ChatModel 可用时才创建控制器
- **方法更新**: 所有使用 `bytedeskOllamaChatModel` 的地方都替换为 `chatModel`
### 2. 新增配置类
#### ChatModelConfig.java
- 提供备用的 ChatModel 配置
- 只有在没有其他 ChatModel 实现时才创建 FallbackChatModel
-`bytedesk.features.java-ai=true` 配置控制
#### FallbackChatModel.java
- 简单的 ChatModel 实现作为备用
- 当没有其他 ChatModel 可用时返回友好的错误消息
- 提醒用户配置正确的 ChatModel 实现
## 兼容性
此更改向后兼容:
- 当 Ollama 启用时,会优先使用 OllamaChatModel
- 当其他 ChatModel 实现(如 OpenAI可用时会使用相应的实现
- 当没有任何 ChatModel 可用时,会使用 FallbackChatModel 避免启动错误
## 配置要求
确保在 `application.properties` 中设置:
```properties
bytedesk.features.java-ai=true
```
## 测试建议
1. 测试 Ollama 启用的情况
2. 测试 Ollama 禁用但有其他 ChatModel 的情况
3. 测试完全没有 ChatModel 的情况(应该使用 FallbackChatModel

View File

@@ -1,17 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-12-02 13:21:01
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-12-02 13:23:57
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# TODO
- [X] finished
- [ ] todo

308
modules/ai/bin/mvnw vendored
View File

@@ -1,308 +0,0 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

View File

@@ -1,205 +0,0 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

View File

@@ -1,328 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bytedesk</groupId>
<artifactId>modules</artifactId>
<version>${revision}</version>
</parent>
<groupId>com.bytedesk</groupId>
<artifactId>bytedesk-module-ai</artifactId>
<version>${revision}</version>
<name>bytedesk-module-ai</name>
<description>https://www.bytedesk.com</description>
<properties>
<ollama4j.version>1.0.100</ollama4j.version>
<!-- <spring-ai-alibaba.version>1.0.0-M6.1</spring-ai-alibaba.version> -->
<!-- <spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version> -->
<jsonp.version>1.18.3</jsonp.version>
<!-- <selenium.version>4.30.0</selenium.version> -->
<ai.djl.version>0.32.0</ai.djl.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-retry -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-retry</artifactId>
<version>${spring-ai.version}</version>
<!-- 排除 io.swagger.core.v3:swagger-annotations 依赖 -->
<exclusions>
<exclusion>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- rag -->
<!-- https://docs.spring.io/spring-ai/reference/api/retrieval-augmented-generation.html -->
<!--
https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-advisors-vector-store -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
<version>${spring-ai.version}</version>
<!-- 排除 io.swagger.core.v3:swagger-annotations 依赖 -->
<exclusions>
<exclusion>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-rag -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-rag</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- llm -->
<!-- https://docs.spring.io/spring-ai/reference/api/chat/deepseek-chat.html -->
<!--
https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-starter-model-openai -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!--
https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-starter-model-ollama -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!--
https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-starter-model-zhipuai -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- vector store -->
<!-- https://docs.spring.io/spring-ai/reference/api/vectordbs/elasticsearch.html -->
<!--
https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-starter-vector-store-elasticsearch -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-elasticsearch</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- mcp -->
<!-- https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-starter-mcp-client -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-starter-mcp-server -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- ///////////////////////////////////////////////////////////////////////////// -->
<dependency>
<groupId>com.bytedesk</groupId>
<artifactId>bytedesk-module-core</artifactId>
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.bytedesk</groupId>
<artifactId>bytedesk-module-kbase</artifactId>
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<!-- ///////////////////////////////////////////////////////////////////////////// -->
<!-- 开始:运行 Embedding 模型依赖 -->
<!-- https://github.com/deepjavalibrary/djl-demo -->
<!-- https://docs.djl.ai/master/docs/quick_start.html -->
<!-- <dependency>
<groupId>ai.djl</groupId>
<artifactId>api</artifactId>
<version>${ai.djl.version}</version>
</dependency>
<dependency>
<groupId>ai.djl.huggingface</groupId>
<artifactId>tokenizers</artifactId>
<version>${ai.djl.version}</version>
</dependency>
<dependency>
<groupId>ai.djl</groupId>
<artifactId>model-zoo</artifactId>
<version>${ai.djl.version}</version>
</dependency>
<dependency>
<groupId>ai.djl.pytorch</groupId>
<artifactId>pytorch-engine</artifactId>
<version>${ai.djl.version}</version>
</dependency>
<dependency>
<groupId>ai.djl.onnxruntime</groupId>
<artifactId>onnxruntime-engine</artifactId>
<version>${ai.djl.version}</version>
</dependency> -->
<!-- 结束:运行 Embedding 模型依赖 -->
<!-- https://java2ai.com/docs/1.0.0-M5.1/overview/?spm=5176.29160081.0.0.2856aa5cNBNg4X -->
<!-- https://github.com/alibaba/spring-ai-alibaba/blob/main/README-zh.md -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud.ai/spring-ai-alibaba-starter -->
<!-- <dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>${spring-ai-alibaba.version}</version>
<exclusions>
<exclusion>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
</exclusions>
</dependency> -->
<!-- https://open.bigmodel.cn/dev/api#sdk_install -->
<!-- https://github.com/MetaGLM/zhipuai-sdk-java-v4 -->
<!--
https://central.sonatype.com/artifact/cn.bigmodel.openapi/oapi-java-sdk/release-V4-2.3.1 -->
<!-- <dependency>
<groupId>cn.bigmodel.openapi</groupId>
<artifactId>oapi-java-sdk</artifactId>
<version>${zhipuai.version}</version>
</dependency> -->
<!-- https://ollama4j.github.io/ollama4j/intro -->
<!-- https://central.sonatype.com/artifact/io.github.ollama4j/ollama4j/overview -->
<dependency>
<groupId>io.github.ollama4j</groupId>
<artifactId>ollama4j</artifactId>
<version>${ollama4j.version}</version>
</dependency>
<!-- 抓取网页时使用 -->
<!-- https://jsoup.org/download -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsonp.version}</version>
</dependency>
<!-- Open Manus -->
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<!--
https://github.com/SeleniumHQ/seleniumhq.github.io/blob/trunk/examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java -->
<!-- <dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-manager</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-http</artifactId>
<version>${selenium.version}</version>
</dependency> -->
<!-- 添加Chrome 134版本对应的DevTools支持 -->
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-devtools-v134 -->
<!-- <dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-devtools-v134</artifactId>
<version>${selenium.version}</version>
</dependency> -->
<!-- ///////////////////////////////////////////////////////////////////////////// -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 添加Spring AI Chat Observation依赖 -->
<!-- <dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-autoconfigure-model-chat-observation</artifactId>
<version>${spring-ai.version}</version>
</dependency> -->
<!-- 添加Micrometer依赖 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation</artifactId>
</dependency>
</dependencies>
<!-- https://docs.spring.io/spring-ai/reference/getting-started.html -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin> -->
</plugins>
</build>
<repositories>
<!-- https://java2ai.com/docs/dev/get-started/ -->
<!-- <repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository> -->
<!-- https://docs.spring.io/spring-ai/reference/getting-started.html -->
<!-- https://repo.spring.io/ui/native/snapshot/org/springframework/ai/ -->
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<name>Central Portal Snapshots</name>
<id>central-portal-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@@ -1,24 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-02-02 09:32:36
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-07 15:44:57
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# ai module
## docs
- [spring-ai-getting-started](https://docs.spring.io/spring-ai/reference/getting-started.html)
- [spring-ai-agentic-patterns](https://spring.io/blog/2025/01/21/spring-ai-agentic-patterns)
- [spring-ai-examples](https://github.com/spring-projects/spring-ai-examples)
```bash
ollama --help
```

View File

@@ -1,67 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2025-03-11 11:18:50
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 11:58:37
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
-->
# 安全
## 1. 任务与指令
描述: 攻击者试图通过提示或操控输入来更改 AI 代理的指令或目标。
缓解措施: 执行验证检查和输入过滤,以检测潜在危险的提示,在它们被 AI 代理处理之前拦截。由于这类攻击通常需要频繁与代理交互,限制对话轮数也是防止此类攻击的有效方法。
## 2. 对关键系统的访问
描述: 如果 AI 代理可以访问存储敏感数据的系统和服务,攻击者可能会破坏代理与这些服务之间的通信。这可能是直接攻击,也可能是通过代理间接获取这些系统的信息。
缓解措施: AI 代理应仅在需要时访问相关系统,以防止此类攻击。代理与系统之间的通信应确保安全。实施身份验证和访问控制也是保护信息的有效手段。
## 3. 资源和服务过载
描述: AI 代理可以访问不同的工具和服务来完成任务。攻击者可能利用这一能力,通过代理发送大量请求来攻击这些服务,可能导致系统故障或高昂成本。
缓解措施: 实施策略以限制 AI 代理对服务的请求数量。限制对话轮数和请求次数也是防止此类攻击的另一种方法。
## 4. 知识库污染
描述: 这种攻击并不直接针对 AI 代理,而是针对代理将使用的知识库和其他服务。这可能包括篡改代理完成任务所需的数据或信息,导致代理向用户提供偏颇或意外的响应。
缓解措施: 定期验证 AI 代理在其工作流程中使用的数据。确保对这些数据的访问是安全的,并且只有受信任的人员才能更改,以避免此类攻击。
## 5. 连锁错误
描述: AI 代理依赖多种工具和服务来完成任务。攻击者引发的错误可能导致其他系统的故障,使攻击范围扩大且更难排查。
缓解措施: 一种避免方法是让 AI 代理在受限环境中运行,例如在 Docker 容器中执行任务,以防止直接系统攻击。创建回退机制和重试逻辑,以应对某些系统返回错误的情况,也是防止更大范围系统故障的有效手段。
# 成本管理
以下是一些在生产环境中部署AI代理的成本管理策略
## 缓存响应
- 识别常见请求和任务并在它们通过您的代理系统之前提供响应这是减少类似请求量的好方法。您甚至可以通过更基础的AI模型实现一个流程来判断某个请求与缓存请求的相似度。
## 使用小型模型
- 小型语言模型SLM在某些代理使用场景中表现良好并能显著降低成本。如前所述建立一个评估系统来确定并比较其与大型模型的性能是了解SLM在您的使用场景中表现的最佳方式。
## 使用路由模型
- 类似的策略是使用不同规模的模型组合。您可以使用LLM/SLM或无服务器函数根据请求的复杂性将其路由到最合适的模型。这不仅能降低成本还能确保复杂任务的性能表现。
## 限制对话轮数
## 参考
- [building-trustworthy-agents](https://github.com/pengjinning/ai-agents-for-beginners/tree/main/translations/zh/06-building-trustworthy-agents)
- [ai-agents](https://github.com/pengjinning/ai-agents-for-beginners/tree/main/translations/zh/10-ai-agents-production)

View File

@@ -1,57 +0,0 @@
# AI 模块
## 功能特性
### 1. 多模型支持
- OpenAI集成
- 智谱AI对接
- 文心一言集成
- Ollama本地部署
- 自定义模型接入
- 多模型协同工作
### 2. 智能客服
- 24/7全天候自动回复
- 多轮对话支持
- 情感分析
- 意图识别
- 智能问答推荐
- 人机协作服务
### 3. 智能体系统
- 角色定制
- 知识库对接
- 上下文管理
- 多智能体协作
- 任务规划执行
- 持续学习优化
### 4. 自动化工作流
- 流程自动化
- 智能任务分发
- 条件触发执行
- 多步骤编排
- 异常处理机制
- 执行监控分析
### 5. 知识库管理
- 知识库构建
- 文档智能导入
- 知识图谱
- 语义检索
- 实时更新
- 知识推理
### 6. 数据分析
- 对话质量分析
- 用户意图洞察
- 性能监控
- 效果评估
- 优化建议
- 趋势预测

View File

@@ -1,3 +0,0 @@
# alibaba examples
- [spring ai alibaba](https://github.com/springaialibaba/spring-ai-alibaba-examples)

View File

@@ -1,3 +0,0 @@
# Open Manus
## 功能介绍

View File

@@ -1,128 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-12-27 22:19:41
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-10 14:25:26
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 技术/商务联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# prompt
## 提示最佳实践模板
```md
在每个prompt前面添加下面这句话能够显著提高模型输出质量。
“Take a deep breath and work on this step by step.”
“深吸一口气,一步一步地完成这个任务。”
## 1. 任务描述
- **描述**:清晰地描述您希望模型完成的任务。
- **示例**`请生成一个关于可持续发展的简短介绍。`
## 2. 输入格式
- **格式**:指定输入的格式,例如文本、问题、指令等。
- **示例**`输入应为一段文本或一个问题。`
## 3. 输出期望
- **期望**:说明您期望模型返回的结果类型,例如简短回答、详细解释、列表等。
- **示例**`期望输出为一个简短的段落,包含关键点。`
## 4. 关键要素
- **要素**:列出在输出中应包含的关键要素或信息。
- **示例**
- 主题
- 主要观点
- 相关数据或事实
## 5. 示例
- **输入示例**:提供一个或多个示例,展示输入和期望的输出。
- **输入**`请解释什么是机器学习。`
- **输出**`机器学习是人工智能的一个子领域,涉及使用算法和统计模型使计算机系统能够执行特定任务,而无需使用明确的指令。`
## 6. 反馈机制
- **说明**:提供反馈机制,让用户能够根据模型的输出调整提示。
- **示例**`如果输出不符合预期,请尝试更具体的描述或提供更多上下文信息。`
## 7. 多样性
- **建议**:鼓励用户尝试不同的提示,以探索模型的能力和局限性。
- **示例**`尝试不同的提问方式,例如“请告诉我...”或“你能解释一下...吗?”`
```
## RAG智能客服提示最佳实践实例
```md
## 1. 任务描述
- **描述**:根据用户的查询,从知识库中检索相关信息,并生成详细的回答。
- **示例**`请根据用户的查询,从知识库中检索相关信息,并生成一个详细的回答,确保信息准确且易于理解。`
## 2. 输入格式
- **格式**:文本
- **示例**`输入应为用户的查询文本,例如“如何重置我的密码?”`
## 3. 输出期望
- **期望**:期望输出为一段清晰的文本,包含解决方案和相关步骤。
- **示例**`输出应包括重置密码的步骤、可能遇到的问题及解决方案,以及联系支持的方式。`
## 4. 关键要素
- **要素**
- 重置密码的步骤
- 可能遇到的常见问题(如邮箱未收到重置链接)
- 联系客服的方式(如电话、邮件等)
## 5. 示例
- **输入示例**
- `我忘记了我的密码,如何重置?`
- **输出示例**
- `要重置您的密码请按照以下步骤操作1. 访问登录页面点击“忘记密码”链接。2. 输入您的注册邮箱地址并提交。3. 检查您的邮箱您将收到一封重置密码的邮件。4. 点击邮件中的链接设置新密码。如果您没有收到邮件请检查垃圾邮件文件夹或联系支持团队电话400-123-4567。`
## 6. 反馈机制
- **说明**:如果输出不符合预期,请尝试更具体的描述或提供更多上下文信息。
- **示例**`如果用户的查询不够明确,可以引导用户提供更多信息,例如他们的用户名或注册邮箱。`
## 7. 多样性
- **建议**鼓励用户尝试不同的提问方式以探索RAG智能客服的能力。
- **示例**`可以尝试提问:“我如何更改我的账户信息?”或“如何查看我的订单历史?”`
```
## 代码实现
```ts
const generateResponse = (userQuery: string, chatHistory: string[], searchResults: string[]) => {
// RAG智能客服提示模板
const promptTemplate = `
任务描述:根据用户的查询,从知识库中检索相关信息,并结合历史聊天记录生成详细的回答。
用户查询: ${userQuery}
历史聊天记录:
${chatHistory.join('\n')}
搜索结果:
${searchResults.join('\n')}
请根据以上信息生成一个详细的回答,确保信息准确且易于理解。
`;
// 调用模型生成响应
const response = callModel(promptTemplate);
return response;
};
// 示例调用
const userQuery = "如何重置我的密码?";
const chatHistory = [
"用户:我忘记了我的密码。",
"客服:请提供您的注册邮箱。"
];
const searchResults = [
"重置密码步骤1. 访问登录页面2. 点击“忘记密码”链接3. 输入您的注册邮箱并提交4. 检查您的邮箱以获取重置链接。"
];
const response = generateResponse(userQuery, chatHistory, searchResults);
console.log(response);
```

View File

@@ -1,19 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2025-02-21 11:27:50
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-21 11:30:04
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
-->
# spring ai mcp
- [overview](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-overview.html)
- [mcp servers](https://github.com/modelcontextprotocol/servers)
- [mcp examples](https://github.com/spring-projects/spring-ai-examples)
- [building mcp with llms](https://modelcontextprotocol.io/tutorials/building-mcp-with-llms)

View File

@@ -1,123 +0,0 @@
# Robots Configuration Documentation
This document describes the structure and usage of the `robots.json` configuration file for the AI chatbot system.
## File Structure
The configuration file consists of the following main sections:
1. **Version Control**
- `version`: Semantic version number of the configuration
2. **JSON Schema**
- Defines the structure and validation rules for the configuration
- Ensures data integrity and consistency
3. **Categories**
- Standard category definitions for robots
- Mapped to internationalized module paths
4. **Robots Array**
- Collection of robot configurations
- Each robot has a unique identifier and multilingual support
## Robot Configuration
Each robot entry contains:
### Basic Information
- `uid`: Unique identifier for the robot
- `name`: Technical name used in the system
- `type`: Robot type (currently only "LLM")
- `category`: Robot category (must match defined categories)
### Internationalization (i18n)
Each robot supports multiple languages (en, zh_cn, zh_tw) with the following fields:
- `nickname`: Display name in the respective language
- `prompt`: Instruction template for the AI
- `description`: Functional description of the robot
## Prompt Variables
Some prompts support variable substitution:
- `{query}`: User's input query
- `{context}`: Context information or search results
- `{history}`: Chat history
- `{chunk}`: Text chunk for processing (used in FAQ generation)
## Category Types
1. **Service Module** (`i18n.module.service`)
- General customer service related bots
- Includes Q&A, analysis, and support functions
2. **Ticket Module** (`i18n.module.ticket`)
- Ticket management related bots
- Handles ticket generation and processing
3. **Void Module** (`i18n.module.void`)
- Basic empty bots
- Used for creating custom implementations
## Version History
- 1.0.0: Initial release with i18n support
- Added JSON Schema validation
- Standardized categories
- Implemented multilingual support
## Usage Example
```json
{
"uid": "1",
"name": "customer_service",
"type": "LLM",
"category": "i18n.module.service",
"i18n": {
"en": {
"nickname": "Customer Service Q&A",
"prompt": "Based on the provided document...",
"description": "Create a customer service Q&A bot"
},
"zh_cn": {
"nickname": "客服问答",
"prompt": "根据提供的文档信息...",
"description": "创建一个客服问答机器人"
}
}
}
```
## Best Practices
1. Always validate new entries against the JSON schema
2. Ensure all required translations are provided
3. Use consistent formatting for prompts
4. Test variable substitution in prompts
5. Keep descriptions clear and concise
## Development Guidelines
When adding new robots:
1. Assign a unique UID
2. Provide complete translations for all supported languages
3. Use appropriate category from standard categories
4. Include clear and detailed prompts
5. Test the configuration before deployment
## Error Handling
The system will validate:
- Schema compliance
- Required fields
- Category validity
- Language support completeness
Invalid configurations will be rejected with appropriate error messages.

View File

@@ -1,797 +0,0 @@
{
"ollama": [],
"deepseek": [
{
"name": "deepseek-chat",
"nickname": "DeepSeek-V3",
"description": "深度求索推出的通用大语言模型,擅长自然语言理解与生成",
"type": "CHAT"
},
{
"name": "deepseek-reasoner",
"nickname": "DeepSeek-R1",
"description": "专注于推理能力的大语言模型,具有强大的逻辑思维和分析能力",
"type": "REASONING"
}
],
"zhipu": [
{
"name": "glm-zero-preview",
"nickname": "GLM-Zero-Preview",
"description": "智谱最新推出的基础大模型,实现更强大的认知理解和推理能力",
"type": "CHAT"
},
{
"name": "glm-4-0520",
"nickname": "GLM-4-0520",
"description": "智谱GLM-4系列模型具备通用对话能力",
"type": "CHAT"
},
{
"name": "glm-4-long",
"nickname": "GLM-4-Long",
"description": "支持更长上下文的GLM-4变体适合长文本处理场景",
"type": "CHAT"
},
{
"name": "glm-4-plus",
"nickname": "GLM-4-Plus",
"description": "GLM-4的增强版本具有更强的理解能力和生成质量",
"type": "CHAT"
},
{
"name": "glm-4-air",
"nickname": "GLM-4-Air",
"description": "轻量级GLM-4变体适合快速响应的对话场景",
"type": "CHAT"
},
{
"name": "glm-4-airx",
"nickname": "GLM-4-AirX",
"description": "GLM-4-Air的扩展版本支持更多功能",
"type": "CHAT"
},
{
"name": "glm-4-flash",
"nickname": "GLM-4-Flash(免费)",
"description": "免费使用的快速响应GLM-4变体",
"type": "CHAT"
},
{
"name": "glm-4-flashx",
"nickname": "GLM-4-FlashX",
"description": "GLM-4-Flash的增强版本保持快速响应的同时提供更好的输出质量",
"type": "CHAT"
},
{
"name": "glm-4v",
"nickname": "GLM 4V",
"description": "支持视觉输入的多模态大模型,可以理解和分析图像",
"type": "VISION"
},
{
"name": "glm-4v-flash",
"nickname": "GLM-4V-Flash",
"description": "轻量级多模态视觉模型,提供快速的图像理解能力",
"type": "VISION"
},
{
"name": "glm-4v-plus",
"nickname": "GLM-4V-Plus",
"description": "增强版视觉语言模型,提供更精确的图像理解和详细描述能力",
"type": "VISION"
},
{
"name": "glm-4-alltools",
"nickname": "GLM-4-AllTools",
"description": "支持多种工具调用的GLM-4变体增强模型解决复杂任务的能力",
"type": "function"
},
{
"name": "embedding-3",
"nickname": "Embedding-3",
"description": "文本嵌入模型,将文本转换为向量表示,适用于检索和语义搜索",
"type": "EMBEDDING"
}
],
"dashscope": [
{
"name": "qwen-turbo",
"nickname": "Qwen Turbo",
"description": "通义千问的快速响应版本,提供高效率的对话体验",
"type": "CHAT"
},
{
"name": "qwen-plus",
"nickname": "Qwen Plus",
"description": "通义千问的增强版本,具有更强的理解能力和生成质量",
"type": "CHAT"
},
{
"name": "qwen-max",
"nickname": "Qwen Max",
"description": "通义千问的最高规格版本,提供最佳的能力和性能",
"type": "CHAT"
}
],
"silicon": [
{
"name": "Qwen/QwQ-32B",
"nickname": "Qwen/QwQ-32B",
"description": "基于32B参数量的通义千问模型变体专注于对话生成能力",
"type": "CHAT"
},
{
"name": "Qwen/Qwen2-7B-Instruct",
"nickname": "Qwen2-7B-Instruct",
"description": "通义千问第二代7B指令微调模型适合一般对话和指令执行任务",
"type": "CHAT"
},
{
"name": "Qwen/Qwen2-72B-Instruct",
"nickname": "Qwen2-72B-Instruct",
"description": "通义千问第二代72B参数量的大规模模型提供强大的对话和推理能力",
"type": "CHAT"
},
{
"name": "THUDM/glm-4-9b-chat",
"nickname": "GLM-4-9B-Chat",
"description": "清华大学开发的GLM-4系列9B参数量聊天模型平衡性能和效率",
"type": "CHAT"
},
{
"name": "deepseek-ai/DeepSeek-V2-Chat",
"nickname": "DeepSeek-V2-Chat",
"description": "深度求索第二代对话模型,提供自然流畅的交互体验",
"type": "CHAT"
},
{
"name": "deepseek-ai/DeepSeek-Coder-V2-Instruct",
"nickname": "DeepSeek-Coder-V2-Instruct",
"description": "专注于代码生成的指令微调模型,适合编程辅助场景",
"type": "CODE"
}
],
"gitee": [
{
"name": "DeepSeek-R1-Distill-Qwen-32B",
"nickname": "DeepSeek-R1-Distill-Qwen-32B",
"description": "DeepSeek-R1知识蒸馏到通义千问32B的模型兼具推理能力和基础性能",
"type": "REASONING"
},
{
"name": "DeepSeek-R1-Distill-Qwen-1.5B",
"nickname": "DeepSeek-R1-Distill-Qwen-1.5B",
"description": "DeepSeek-R1知识蒸馏到1.5B小型模型,适合轻量级推理场景",
"type": "REASONING"
},
{
"name": "DeepSeek-R1-Distill-Qwen-14B",
"nickname": "DeepSeek-R1-Distill-Qwen-14B",
"description": "DeepSeek-R1知识蒸馏到14B中型模型平衡推理能力和资源消耗",
"type": "REASONING"
},
{
"name": "DeepSeek-R1-Distill-Qwen-7B",
"nickname": "DeepSeek-R1-Distill-Qwen-7B",
"description": "DeepSeek-R1知识蒸馏到7B模型实现高效推理能力",
"type": "REASONING"
},
{
"name": "DeepSeek-V3",
"nickname": "DeepSeek-V3",
"description": "深度求索第三代大模型,全面提升理解和生成能力",
"type": "CHAT"
},
{
"name": "DeepSeek-R1",
"nickname": "DeepSeek-R1",
"description": "专注于推理能力的深度求索模型,解决复杂逻辑任务",
"type": "REASONING"
},
{
"name": "deepseek-coder-33B-instruct",
"nickname": "deepseek-coder-33B-instruct",
"description": "33B参数量的代码专用模型提供高质量代码生成和理解能力",
"type": "CODE"
},
{
"name": "Qwen2.5-72B-Instruct",
"nickname": "Qwen2.5-72B-Instruct",
"description": "通义千问2.5版72B参数规模的指令微调模型具备强大的通用能力",
"type": "CHAT"
},
{
"name": "Qwen2.5-14B-Instruct",
"nickname": "Qwen2.5-14B-Instruct",
"description": "通义千问2.5版14B参数规模的指令微调模型平衡性能和资源",
"type": "CHAT"
},
{
"name": "Qwen2-7B-Instruct",
"nickname": "Qwen2-7B-Instruct",
"description": "通义千问第二代7B参数量的指令微调模型适合一般对话任务",
"type": "CHAT"
},
{
"name": "Qwen2.5-32B-Instruct",
"nickname": "Qwen2.5-32B-Instruct",
"description": "通义千问2.5版32B参数规模的指令微调模型较大规模通用对话模型",
"type": "CHAT"
},
{
"name": "Qwen2-72B-Instruct",
"nickname": "Qwen2-72B-Instruct",
"description": "通义千问第二代72B参数量的大规模模型提供强大的对话和推理能力",
"type": "CHAT"
},
{
"name": "Qwen2-VL-72B",
"nickname": "Qwen2-VL-72B",
"description": "通义千问第二代72B参数量的视觉语言多模态模型支持图像理解",
"type": "VISION"
},
{
"name": "QwQ-32B-Preview",
"nickname": "QwQ-32B-Preview",
"description": "通义千问开发的预览版32B模型提供新一代对话体验",
"type": "CHAT"
},
{
"name": "Yi-34B-Chat",
"nickname": "Yi-34B-Chat",
"description": "01.AI推出的34B参数量聊天模型提供全面的对话能力",
"type": "CHAT"
},
{
"name": "glm-4-9b-chat",
"nickname": "glm-4-9b-chat",
"description": "智谱GLM-4系列9B参数量聊天模型平衡性能和资源消耗",
"type": "CHAT"
},
{
"name": "codegeex4-all-9b",
"nickname": "codegeex4-all-9b",
"description": "专注于代码生成的9B参数模型支持多种编程语言",
"type": "CODE"
},
{
"name": "InternVL2-8B",
"nickname": "InternVL2-8B",
"description": "8B参数量的视觉语言模型支持图像理解和多模态交互",
"type": "VISION"
},
{
"name": "InternVL2.5-26B",
"nickname": "InternVL2.5-26B",
"description": "2.5版本26B参数量的增强视觉语言模型提供更精确的图像分析",
"type": "VISION"
},
{
"name": "InternVL2.5-78B",
"nickname": "InternVL2.5-78B",
"description": "2.5版本78B大规模视觉语言模型具备高级视觉理解能力",
"type": "VISION"
},
{
"name": "bge-large-zh-v1.5",
"nickname": "bge-large-zh-v1.5",
"description": "中文大规模文本嵌入模型,适用于语义检索和相似度计算",
"type": "EMBEDDING"
},
{
"name": "bge-small-zh-v1.5",
"nickname": "bge-small-zh-v1.5",
"description": "轻量级中文文本嵌入模型,平衡性能和资源消耗",
"type": "EMBEDDING"
},
{
"name": "bge-m3",
"nickname": "bge-m3",
"description": "多语言、多模态的嵌入模型,支持跨语言和跨模态检索",
"type": "EMBEDDING"
},
{
"name": "bce-embedding-base_v1",
"nickname": "bce-embedding-base_v1",
"description": "基础版文本嵌入模型,将文本转换为向量表示",
"type": "EMBEDDING"
}
],
"tencent": [
{
"name": "hunyuan-pro",
"nickname": "hunyuan-pro",
"description": "腾讯混元专业版大模型,提供高质量的对话和理解能力",
"type": "CHAT"
},
{
"name": "hunyuan-standard",
"nickname": "hunyuan-standard",
"description": "腾讯混元标准版大模型,适合一般对话和内容生成任务",
"type": "CHAT"
},
{
"name": "hunyuan-lite",
"nickname": "hunyuan-lite",
"description": "腾讯混元轻量版大模型,优化速度和资源消耗",
"type": "CHAT"
},
{
"name": "hunyuan-standard-256k",
"nickname": "hunyuan-standard-256k",
"description": "支持256K超长上下文的混元标准版适合长文本处理场景",
"type": "CHAT"
},
{
"name": "hunyuan-vision",
"nickname": "hunyuan-vision",
"description": "腾讯混元视觉版大模型,支持图像理解和多模态交互",
"type": "VISION"
},
{
"name": "hunyuan-code",
"nickname": "hunyuan-code",
"description": "腾讯混元代码版大模型,专注于代码生成和程序理解",
"type": "CODE"
},
{
"name": "hunyuan-role",
"nickname": "hunyuan-role",
"description": "腾讯混元角色扮演大模型,支持多种角色和场景模拟",
"type": "CHAT"
},
{
"name": "hunyuan-turbo",
"nickname": "hunyuan-turbo",
"description": "腾讯混元高速版,提供快速响应的对话体验",
"type": "CHAT"
},
{
"name": "hunyuan-turbos-latest",
"nickname": "hunyuan-turbos-latest",
"description": "腾讯混元最新高速版,提供更快响应速度和优化体验",
"type": "CHAT"
},
{
"name": "hunyuan-embedding",
"nickname": "hunyuan-embedding",
"description": "腾讯混元文本嵌入模型,将文本转换为向量表示",
"type": "EMBEDDING"
}
],
"baidu": [
{
"name": "deepseek-r1",
"nickname": "DeepSeek R1",
"description": "百度提供的深度求索R1模型专注于推理和分析能力",
"type": "REASONING"
},
{
"name": "deepseek-v3",
"nickname": "DeepSeek V3",
"description": "百度提供的深度求索V3模型第三代通用对话模型",
"type": "CHAT"
},
{
"name": "ernie-4.0-8k-latest",
"nickname": "ERNIE-4.0",
"description": "百度文心一言4.0版本支持8K上下文提供全面的对话能力",
"type": "CHAT"
},
{
"name": "ernie-4.0-turbo-8k-latest",
"nickname": "ERNIE 4.0 Trubo",
"description": "百度文心一言4.0高速版,提供更快的响应速度",
"type": "CHAT"
},
{
"name": "ernie-speed-8k",
"nickname": "ERNIE Speed",
"description": "百度文心一言优化速度版本支持8K上下文和快速响应",
"type": "CHAT"
},
{
"name": "ernie-lite-8k",
"nickname": "ERNIE Lite",
"description": "百度文心一言轻量版,平衡性能和资源消耗",
"type": "CHAT"
},
{
"name": "bge-large-zh",
"nickname": "BGE Large ZH",
"description": "百度大规模中文文本嵌入模型,适用于语义检索",
"type": "EMBEDDING"
},
{
"name": "bge-large-en",
"nickname": "BGE Large EN",
"description": "百度大规模英文文本嵌入模型,适用于语义检索",
"type": "EMBEDDING"
}
],
"volcengine": [
{
"name": "doubao-1-5-vision-pro-32k-250115",
"nickname": "doubao-1.5-vision-pro",
"description": "火山引擎豆包1.5视觉专业版支持32K上下文和图像理解",
"type": "VISION"
},
{
"name": "doubao-1-5-pro-32k-250115",
"nickname": "doubao-1.5-pro-32k",
"description": "火山引擎豆包1.5专业版支持32K上下文的对话能力",
"type": "CHAT"
},
{
"name": "doubao-1-5-pro-32k-character-250228",
"nickname": "doubao-1.5-pro-32k-character",
"description": "火山引擎豆包1.5角色扮演专业版支持32K上下文",
"type": "CHAT"
},
{
"name": "doubao-1-5-pro-256k-250115",
"nickname": "Doubao-1.5-pro-256k",
"description": "火山引擎豆包1.5专业版支持256K超长上下文的对话能力",
"type": "CHAT"
},
{
"name": "deepseek-r1-250120",
"nickname": "DeepSeek-R1",
"description": "火山引擎提供的深度求索R1模型专注于推理能力",
"type": "REASONING"
},
{
"name": "deepseek-r1-distill-qwen-32b-250120",
"nickname": "DeepSeek-R1-Distill-Qwen-32B",
"description": "深度求索R1知识蒸馏到通义千问32B的模型版本",
"type": "REASONING"
},
{
"name": "deepseek-r1-distill-qwen-7b-250120",
"nickname": "DeepSeek-R1-Distill-Qwen-7B",
"description": "深度求索R1知识蒸馏到通义千问7B的轻量级模型",
"type": "REASONING"
},
{
"name": "deepseek-v3-250324",
"nickname": "DeepSeek-V3",
"description": "火山引擎提供的深度求索V3模型第三代通用对话能力",
"type": "CHAT"
},
{
"name": "doubao-pro-32k-241215",
"nickname": "Doubao-pro-32k",
"description": "火山引擎豆包专业版支持32K上下文的对话模型",
"type": "CHAT"
},
{
"name": "doubao-pro-32k-functioncall-241028",
"nickname": "Doubao-pro-32k-functioncall-241028",
"description": "支持函数调用的豆包专业版,适合开发工具型应用",
"type": "function"
},
{
"name": "doubao-pro-32k-character-241215",
"nickname": "Doubao-pro-32k-character-241215",
"description": "支持角色扮演的豆包专业版,适合定制化对话场景",
"type": "CHAT"
},
{
"name": "doubao-pro-256k-241115",
"nickname": "Doubao-pro-256k",
"description": "火山引擎豆包专业版支持256K超长上下文的对话模型",
"type": "CHAT"
},
{
"name": "doubao-lite-4k-character-240828",
"nickname": "Doubao-lite-4k-character-240828",
"description": "轻量级角色扮演豆包模型支持4K上下文",
"type": "CHAT"
},
{
"name": "doubao-lite-32k-240828",
"nickname": "Doubao-lite-32k",
"description": "火山引擎豆包轻量版支持32K上下文的高效对话模型",
"type": "CHAT"
},
{
"name": "doubao-lite-32k-character-241015",
"nickname": "Doubao-lite-32k-character-241015",
"description": "轻量级角色扮演豆包模型支持32K上下文",
"type": "CHAT"
},
{
"name": "doubao-lite-128k-240828",
"nickname": "Doubao-lite-128k",
"description": "火山引擎豆包轻量版支持128K上下文的对话模型",
"type": "CHAT"
},
{
"name": "doubao-1-5-lite-32k-250115",
"nickname": "Doubao-1.5-lite-32k",
"description": "火山引擎豆包1.5轻量版支持32K上下文的对话模型",
"type": "CHAT"
},
{
"name": "doubao-embedding-large-text-240915",
"nickname": "Doubao-embedding-large",
"description": "火山引擎豆包大规模文本嵌入模型,用于高质量文本向量化",
"type": "EMBEDDING"
},
{
"name": "doubao-embedding-text-240715",
"nickname": "Doubao-embedding",
"description": "火山引擎豆包文本嵌入模型,用于文本向量表示",
"type": "EMBEDDING"
},
{
"name": "doubao-embedding-vision-241215",
"nickname": "Doubao-embedding-vision",
"description": "火山引擎豆包视觉嵌入模型,用于图像特征向量化",
"type": "EMBEDDING"
},
{
"name": "doubao-vision-lite-32k-241015",
"nickname": "Doubao-vision-lite-32k",
"description": "火山引擎豆包视觉轻量版支持32K上下文的多模态模型",
"type": "VISION"
}
],
"openai": [
{
"name": "gpt-4o",
"nickname": " GPT-4o",
"description": "OpenAI最新的全能GPT-4o模型整合视觉和语言能力",
"type": "VISION"
},
{
"name": "gpt-4o-mini",
"nickname": " GPT-4o-mini",
"description": "GPT-4o的轻量版本保持核心能力的同时提高响应速度",
"type": "VISION"
},
{
"name": "gpt-4-turbo",
"nickname": " GPT-4 Turbo",
"description": "GPT-4的优化版本提供更快的响应速度和更新的知识",
"type": "CHAT"
},
{
"name": "gpt-4",
"nickname": " GPT-4",
"description": "OpenAI强大的大型语言模型具备卓越的理解和生成能力",
"type": "CHAT"
}
],
"openrouter": [
{
"name": "google/gemma-2-9b-it:free",
"nickname": "Google: Gemma 2 9B",
"description": "Google Gemma 2 9B指令微调模型平衡性能和资源消耗",
"type": "CHAT"
},
{
"name": "microsoft/phi-3-mini-128k-instruct:free",
"nickname": "Phi-3 Mini 128K Instruct",
"description": "Microsoft的Phi-3 Mini模型支持128K上下文的轻量级选择",
"type": "CHAT"
},
{
"name": "microsoft/phi-3-medium-128k-instruct:free",
"nickname": "Phi-3 Medium 128K Instruct",
"description": "Microsoft的Phi-3 Medium模型支持128K上下文的中型选择",
"type": "CHAT"
},
{
"name": "meta-llama/llama-3-8b-instruct:free",
"nickname": "Meta: Llama 3 8B Instruct",
"description": "Meta的Llama 3 8B指令微调模型高效开源选择",
"type": "CHAT"
},
{
"name": "mistralai/mistral-7b-instruct:free",
"nickname": "Mistral: Mistral 7B Instruct",
"description": "Mistral AI的7B指令微调模型高性能开源选择",
"type": "CHAT"
}
],
"gemini": [
{
"name": "gemini-1.5-flash",
"nickname": "Gemini 1.5 Flash",
"description": "Google Gemini 1.5系列的快速响应版本,平衡速度和性能",
"type": "CHAT"
},
{
"name": "gemini-1.5-pro-exp-0801",
"nickname": "Gemini 1.5 Pro Experimental 0801",
"description": "Google Gemini 1.5 Pro的实验版本提供前沿AI能力",
"type": "CHAT"
}
],
"anthropic": [
{
"name": "claude-3-5-sonnet-20240620",
"nickname": "Claude 3.5 Sonnet",
"description": "Anthropic最新的Claude 3.5 Sonnet模型平衡性能和效率",
"type": "CHAT"
},
{
"name": "claude-3-opus-20240229",
"nickname": "Claude 3 Opus",
"description": "Anthropic最强大的Claude 3 Opus模型提供顶级对话体验",
"type": "CHAT"
},
{
"name": "claude-3-sonnet-20240229",
"nickname": "Claude 3 Sonnet",
"description": "Claude 3中端版本平衡性能和响应速度",
"type": "CHAT"
},
{
"name": "claude-3-haiku-20240307",
"nickname": "Claude 3 Haiku",
"description": "Claude 3轻量版提供快速响应和高效对话",
"type": "CHAT"
}
],
"yi": [
{
"name": "yi-large",
"nickname": "Yi-Large",
"description": "01.AI的大规模Yi模型提供强大的对话和理解能力",
"type": "CHAT"
},
{
"name": "yi-large-turbo",
"nickname": "Yi-Large-Turbo",
"description": "Yi大模型的高速版本提供更快的响应体验",
"type": "CHAT"
},
{
"name": "yi-large-rag",
"nickname": "Yi-Large-Rag",
"description": "专为检索增强生成优化的Yi大模型变体",
"type": "rag"
},
{
"name": "yi-medium",
"nickname": "Yi-Medium",
"description": "01.AI的中型Yi模型平衡性能和资源消耗",
"type": "CHAT"
},
{
"name": "yi-medium-200k",
"nickname": "Yi-Medium-200k",
"description": "支持200K超长上下文的中型Yi模型适合长文本处理",
"type": "CHAT"
},
{
"name": "yi-spark",
"nickname": "Yi-Spark",
"description": "Yi系列的轻量快速版本提供即时响应的对话体验",
"type": "CHAT"
}
],
"moonshot": [
{
"name": "moonshot-v1-8k",
"nickname": "Moonshot V1 8k",
"description": "Moonshot AI的基础模型支持8K上下文窗口",
"type": "CHAT"
},
{
"name": "moonshot-v1-32k",
"nickname": "Moonshot V1 32k",
"description": "支持32K上下文的Moonshot模型适合处理更长文本",
"type": "CHAT"
},
{
"name": "moonshot-v1-128k",
"nickname": "Moonshot V1 128k",
"description": "支持128K超长上下文的Moonshot模型适合大规模文本分析",
"type": "CHAT"
}
],
"baichuan": [
{
"name": "Baichuan4",
"nickname": "Baichuan4",
"description": "百川智能第四代大语言模型,全面提升理解和生成能力",
"type": "CHAT"
},
{
"name": "Baichuan3-Turbo",
"nickname": "Baichuan3 Turbo",
"description": "百川智能第三代加速版模型,提供快速响应的对话体验",
"type": "CHAT"
},
{
"name": "Baichuan3-Turbo-128k",
"nickname": "Baichuan3 Turbo 128k",
"description": "支持128K上下文的百川3加速版适合长文本处理",
"type": "CHAT"
}
],
"stepfun": [
{
"name": "step-1-8k",
"nickname": "Step 1 8K",
"description": "Step函数团队开发的基础大模型支持8K上下文窗口",
"type": "CHAT"
},
{
"name": "step-1-flash",
"nickname": "Step 1 Flash",
"description": "Step函数团队的快速响应模型优化速度和效率",
"type": "CHAT"
}
],
"minimax": [
{
"name": "abab6.5s-chat",
"nickname": "abab6.5s",
"description": "MiniMax的abab 6.5标准版聊天模型,提供全面对话能力",
"type": "CHAT"
},
{
"name": "abab6.5g-chat",
"nickname": "abab6.5g",
"description": "MiniMax的abab 6.5高级版聊天模型,提供增强对话能力",
"type": "CHAT"
},
{
"name": "abab6.5t-chat",
"nickname": "abab6.5t",
"description": "MiniMax的abab 6.5旗舰版聊天模型,提供最强对话体验",
"type": "CHAT"
},
{
"name": "abab5.5s-chat",
"nickname": "abab5.5s",
"description": "MiniMax的abab 5.5标准版聊天模型,经典稳定的对话能力",
"type": "CHAT"
}
],
"aihubmix": [
{
"name": "gpt-4o-mini",
"nickname": "GPT-4o Mini",
"description": "AIHubMix提供的GPT-4o Mini版本平衡性能和响应速度",
"type": "VISION"
},
{
"name": "aihubmix-Llama-3-70B-Instruct",
"nickname": "Llama 3 70B Instruct",
"description": "AIHubMix提供的Meta Llama 3 70B指令微调版本强大的开源模型",
"type": "CHAT"
}
],
"groq": [
{
"name": "llama3-8b-8192",
"nickname": "LLaMA3 8B",
"description": "Groq加速的Meta Llama 3 8B模型支持8192上下文",
"type": "CHAT"
},
{
"name": "llama3-70b-8192",
"nickname": "LLaMA3 70B",
"description": "Groq加速的Meta Llama 3 70B大型模型支持8192上下文",
"type": "CHAT"
},
{
"name": "mixtral-8x7b-32768",
"nickname": "Mixtral 8x7B",
"description": "Groq加速的Mixtral 8x7B混合专家模型支持32768上下文",
"type": "CHAT"
},
{
"name": "gemma-7b-it",
"nickname": "Gemma 7B",
"description": "Groq加速的Google Gemma 7B指令微调模型高效开源选择",
"type": "CHAT"
}
]
}

View File

@@ -1,149 +0,0 @@
{
"ollama": {
"nickname": "Ollama",
"logo": "ollama.png",
"apiUrl": "http://127.0.0.1:11434",
"webUrl": "https://ollama.com/",
"status": "PRODUCTION"
},
"zhipu": {
"nickname": "智谱",
"logo": "zhipu.png",
"apiUrl": "https://open.bigmodel.cn/api/paas/v4/",
"webUrl": "https://open.bigmodel.cn/",
"status": "PRODUCTION"
},
"deepseek": {
"nickname": "DeepSeek",
"logo": "deepseek.png",
"apiUrl": "https://api.deepseek.com",
"webUrl": "https://deepseek.com/",
"status": "PRODUCTION"
},
"dashscope": {
"nickname": "通义千问",
"logo": "dashscope.png",
"apiUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1/",
"webUrl": "https://dashscope.aliyun.com/",
"status": "PRODUCTION"
},
"silicon": {
"nickname": "硅基流动",
"logo": "silicon.png",
"apiUrl": "https://cloud.siliconflow.cn",
"webUrl": "https://www.siliconflow.cn/",
"status": "PRODUCTION"
},
"gitee": {
"nickname": "Gitee魔力方舟",
"logo": "gitee.svg",
"apiUrl": "https://api.gitee.com",
"webUrl": "https://ai.gitee.com/",
"status": "PRODUCTION"
},
"tencent": {
"nickname": "腾讯混元",
"logo": "hunyuan.png",
"apiUrl": "https://hunyuan.tencent.com/",
"webUrl": "https://hunyuan.tencent.com/",
"status": "PRODUCTION"
},
"baidu": {
"nickname": "百度千帆",
"logo": "yiyan.png",
"apiUrl": "https://yiyan.baidu.com/",
"webUrl": "https://yiyan.baidu.com/",
"status": "PRODUCTION"
},
"volcengine": {
"nickname": "火山引擎",
"logo": "doubao.png",
"apiUrl": "https://ark.cn-beijing.volces.com/api/v3/",
"webUrl": "https://console.volcengine.com/ark/",
"status": "PRODUCTION"
},
"openai": {
"nickname": "OpenAI",
"logo": "openai.png",
"apiUrl": "https://api.openai.com",
"webUrl": "https://openai.com/",
"status": "PRODUCTION"
},
"openrouter": {
"nickname": "OpenRouter",
"logo": "openrouter.png",
"apiUrl": "https://openrouter.ai/api/v1/",
"webUrl": "https://openrouter.ai/",
"status": "PRODUCTION"
},
"xinghuo": {
"nickname": "讯飞星火",
"logo": "xinghuo.png",
"apiUrl": "https://xinghuo.xfyun.cn/sparkapi",
"webUrl": "https://xinghuo.xfyun.cn/sparkapi",
"status": "DEVELOPMENT"
},
"moonshot": {
"nickname": "Kimi",
"logo": "moonshot.jpg",
"apiUrl": "https://api.moonshot.cn",
"webUrl": "https://moonshot.ai/",
"status": "DEVELOPMENT"
},
"baichuan": {
"nickname": "百小应",
"logo": "baichuan.png",
"apiUrl": "https://api.baichuan-ai.com",
"webUrl": "https://www.baichuan-ai.com/",
"status": "DEVELOPMENT"
},
"minimax": {
"nickname": "Minimax",
"logo": "minimax.png",
"apiUrl": "https://api.minimax.chat/v1/",
"webUrl": "https://platform.minimaxi.com/",
"status": "DEVELOPMENT"
},
"yi": {
"nickname": "Yi",
"logo": "yi.png",
"apiUrl": "https://api.lingyiwanwu.com",
"webUrl": "https://platform.lingyiwanwu.com/",
"status": "DEVELOPMENT"
},
"stepfun": {
"nickname": "StepFun",
"logo": "stepfun.png",
"apiUrl": "https://api.stepfun.com",
"webUrl": "https://platform.stepfun.com/",
"status": "DEVELOPMENT"
},
"groq": {
"nickname": "Groq",
"logo": "groq.png",
"apiUrl": "https://api.groq.com/openai",
"webUrl": "https://groq.com/",
"status": "DEVELOPMENT"
},
"anthropic": {
"nickname": "Anthropic",
"logo": "anthropic.jpeg",
"apiUrl": "https://api.anthropic.com/",
"webUrl": "https://anthropic.com/",
"status": "DEVELOPMENT"
},
"gemini": {
"nickname": "Gemini",
"logo": "gemini.png",
"apiUrl": "https://generativelanguage.googleapis.com",
"webUrl": "https://gemini.google.com/",
"status": "DEVELOPMENT"
},
"aihubmix": {
"nickname": "AIHubMix",
"logo": "aihubmix.jpg",
"apiUrl": "https://aihubmix.com",
"webUrl": "https://aihubmix.com/",
"status": "DEVELOPMENT"
}
}

View File

@@ -1,92 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2025-01-16 19:09:08
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-22 10:41:16
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
*
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
-->
# ai module
## 机器人
### 机器人分类
- 客服问答:你是访客问答助手。根据提供的文档信息以及历史记录回答问题,文档信息如下: {context} 问题: {query} 当用户提出的问题无法根据文档内容进行回复或者你也不清楚时,回复:未查找到相关问题答案.
- 问题扩写:根据用户的问题,生成多个不同表述的问题,确保问题的多样性。
- 意图改写:根据用户的问题,生成多个不同表述的问题,确保问题的多样性。
- 意图识别:根据用户的问题,识别用户的意图,并返回意图的类型。
- 情绪分析:根据用户的问题,识别用户的情绪,并返回情绪的类型。
- 机器人质检:对机器人回答的问题进行评测,并给出评测结果。
- 客服质检:对客服的回答进行质检,并给出质检结果。
- 会话小结:对会话进行总结,并给出总结结果。
- 工单助手:从会话记录中提取工单信息,自动填写工单表单。可用于访客端和客服端。
- 工单解决方案推荐访客填写完工单标题和描述后自动搜索解决方案和FAQ通过大模型给出解决方案同时适用于访客端和客服端。
- 工单小结对工单进行总结并给出总结结果。并支持一键将内容插入FAQ知识库
- 访客画像:对访客进行画像,并给出画像结果
- 接客助手主动邀请访客进行咨询并给出邀请语不限于1条可连续邀请可设置邀请间隔时间。
- 导购助手:针对电商网站,根据访客的浏览行为,给出推荐商品,并给出推荐理由。
- 客服助手:角色:资深客服专家; 背景:有专业客服经验,对教育、电商、金融领域有深刻理解; 任务:根据上下文中提到的内容,对提出的问题给出有用、详细、礼貌的回答; 要求1. 解决客户提出的问题2. 安抚客户情绪3. 提升客户满意度"
- 售前客服:针对售前咨询的客户,给出专业的解答,并给出推荐商品,并给出推荐理由。
- 售后客服:针对售后咨询的客户,给出专业的解答,并给出解决方案,并给出解决方案的理由。
- 物流客服:针对物流咨询的客户,给出专业的解答,并给出解决方案,并给出解决方案的理由。
- 语言翻译:针对不同的语言,给出翻译结果。
- 语言识别:针对不同的语言,给出识别结果。
- 语义分析:从会话记录中提取语义信息,并给出语义信息。
- 实体识别:从会话记录中提取实体信息,并给出实体信息。
- 情感分析:从会话记录中提取情感信息,并给出情感信息。
- 会话摘要:从会话记录中提取摘要信息,在会话结束后,快速生成会话摘要,包含客户问题及解决方案,同时支持人工校审和进一步编辑。
- 会话分类:根据会话内容,在会话结束后,会自动将会话进行归类,同时支持客服手动更正
- 生成工单:根据当前会话,如果需要提交工单跟进后续服务时,可以根据工单所需的字段,一键提取会话中的关联内容,如客户名字、关联订单、联系方式、工单内容等,还可以通过识别访客情绪,建议工单的优先级。
- 客服专家:任务描述:根据用户的查询和文档信息回答问题,并结合历史聊天记录生成简要的回答。
- 生成FAQ: 基于以下给定的文本,生成一组高质量的问答对。
- 公众号写作助手:给定一段文本,生成一篇公众号文章。
- 小红书写作助手:给定一段文本,生成一篇小红书文章。
- 客服助手:你是客服人员的工作助手。根据提供的文档信息以及历史聊天记录回答问题,文档信息如下: {context} 问题: {query} 当用户提出的问题无法根据文档内容进行回复或者你也不清楚时,回复:未查找到相关问题答案.
- 会话小结:根据会话历史记录,生成会话小结
- 输入补全:根据会话历史记录,以及用户实时输入内容,补全用户输入
- 中文分词:将中文文本切分成有语义的词语序列,用于文本理解和处理的基础。
- 词性标注:识别文本中每个词的词性(如名词、动词、形容词等),为文本分析提供语法信息。
- 命名实体识别:从文本中识别并提取人名、地名、组织名等实体信息。
- 依存句法分析:分析句子中词语之间的依存关系,确定句子的语法结构。
- 成分句法分析:将句子解析为词组和子句的层次结构,反映语法成分间的关系。
- 语义依存分析:分析文本中词语之间的语义关系,揭示词语间的深层语义联系。
- 语义角色标注:识别句子中的谓词及其相关的语义角色(如施事者、受事者等)。
- 抽象意义表示:将文本转换为抽象的语义表示形式,便于跨语言理解和处理。
- 指代消解:确定文本中代词或其他指代表达所指向的实体或概念。
- 语义文本相似度:计算文本之间的语义相似程度,用于文本匹配和检索。
- 文本风格转换:将文本从一种风格转换为另一种风格,如正式语体转换为口语化表达。
- 关键词短语提取:从文本中提取关键词和短语,概括文本的核心内容。
- 文本纠错:自动检测并修正文本中的拼写、语法或表达错误。
- 文本分类:根据内容将文本划分到不同的类别,如主题分类或情感分类。
### 专门用于客户支持流程的代理
客户代理Customer agent此代理代表客户负责启动支持流程。
卖家代理 (Seller agent):代表卖家,负责处理退款。
支付代理 (Payment agent):代表支付流程,负责退还客户的付款。
解决方案代理 (Solution agent):代表问题解决流程,负责解决退款流程中出现的任何问题。
物流代理 (Logistics agent):代表物流流程,负责将产品退回给卖家。该代理既可以用于退款流程,也可以用于例如购买时的物流。
支持代理Support agent此代理代表支持流程负责为客户提供协助。
升级代理Escalation agent此代理代表升级流程负责将问题升级到更高级别的支持。
解决代理Resolution agent此代理代表解决流程负责解决支持流程中出现的任何问题。
反馈代理Feedback agent此代理代表反馈流程负责收集客户的反馈意见。
通知代理Notification agent此代理代表通知流程负责在支持流程的各个阶段向客户发送通知。
分析代理Analytics agent此代理代表分析流程负责分析与支持流程相关的数据。
审计代理Audit agent此代理代表审计流程负责审查支持流程以确保其正确执行。
报告代理Reporting agent此代理代表报告流程负责生成有关支持流程的报告。
知识代理Knowledge agent此代理代表知识流程负责维护与支持流程相关的信息知识库。
安全代理Security agent此代理代表安全流程负责确保支持流程的安全性。
质量代理Quality agent此代理代表质量流程负责确保支持流程的质量。
合规代理Compliance agent此代理代表合规流程负责确保支持流程符合相关法规和政策。
培训代理Training agent此代理代表培训流程负责培训支持代理如何为客户提供帮助。
## 参考
- [ticket](https://mp.weixin.qq.com/s/MNZR2tkVANfQKWqyAKlSPQ)
- [multi-agent](https://github.com/pengjinning/ai-agents-for-beginners/blob/main/translations/zh/08-multi-agent/solution/solution.md)

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
# 智能机票助手

View File

@@ -1,57 +0,0 @@
# AI 模块
## 功能特性
### 1. 多模型支持
- OpenAI集成
- 智谱AI对接
- 文心一言集成
- Ollama本地部署
- 自定义模型接入
- 多模型协同工作
### 2. 智能客服
- 24/7全天候自动回复
- 多轮对话支持
- 情感分析
- 意图识别
- 智能问答推荐
- 人机协作服务
### 3. 智能体系统
- 角色定制
- 知识库对接
- 上下文管理
- 多智能体协作
- 任务规划执行
- 持续学习优化
### 4. 自动化工作流
- 流程自动化
- 智能任务分发
- 条件触发执行
- 多步骤编排
- 异常处理机制
- 执行监控分析
### 5. 知识库管理
- 知识库构建
- 文档智能导入
- 知识图谱
- 语义检索
- 实时更新
- 知识推理
### 6. 数据分析
- 对话质量分析
- 用户意图洞察
- 性能监控
- 效果评估
- 优化建议
- 趋势预测

View File

@@ -1,156 +0,0 @@
# 微语 - 对话即服务
企业级多租户即时通讯解决方案
:::tip
微语仍处于早期的快速迭代阶段,文档可能落后于开发,导致功能描述可能不符,以最新发布的软件版本为准
:::
## 介绍
### [企业IM](./team/readme.zh.md)
- 局域网即时通讯
- 企业成员管理
- 聊天记录监控
- ...
### [全渠道客服](./service/readme.zh.md)
- 多渠道接入
- 人工客服
- 统计报表
- ...
### [知识库](./kbase/readme.zh.md)
- 对接大模型L
- 自定义知识库
- AI对话
- ...
### [工单系统](./ticket/readme.zh.md)
- 工单管理
- 工单SLA管理
- 工单统计和报表
- ...
### [AI大模型](./ai/readme.zh.md)
- Ollama/DeepSeek/ZhipuAI/...
- 智能体
- 工作流
- ...
### [社交群组](./social/readme.zh.md)
- 类似 Discord
- ...
### 多租户
- 多租户管理
- 租户隔离
- 租户统计
- ...
## Docker 快速开始
### 克隆项目并启动docker compose容器
```bash
git clone https://gitee.com/270580156/weiyu.git && cd weiyu/deploy/docker && docker compose -p weiyu -f docker-compose.yaml up -d
```
### 或者 使用 docker compose ollama
```bash
git clone https://gitee.com/270580156/weiyu.git && cd weiyu/deploy/docker && docker compose -p weiyu -f docker-compose-ollama.yaml up -d
# 运行模型
# docker exec ollama-bytedesk ollama pull deepseek-r1
docker exec ollama-bytedesk ollama pull qwen3:0.6b
```
### 因项目默认使用ollama qwen3:0.6b模型,所以需要提前拉取模型
```bash
ollama pull deepseek-r1:1.5b
ollama pull qwen3:0.6b
```
### 停止容器
```bash
docker compose -p weiyu -f docker-compose.yaml stop
```
### 修改配置,否则上传图片、文件和知识库无法正常显示
- 修改 `docker-compose.yaml` 文件
```bash
# 请将服务器127.0.0.1替换为你的服务器ip
BYTEDESK_UPLOAD_URL: http://127.0.0.1:9003
BYTEDESK_KBASE_API_URL: http://127.0.0.1:9003
```
### 宝塔面板
- [宝塔面板部署](https://www.weiyuai.cn/docs/zh-CN/docs/deploy/baota)
## 演示
本地预览
```bash
# 请将127.0.0.1替换为你的服务器ip
http://127.0.0.1:9003/
# 开放端口9003, 9885
```
- [线上预览](https://www.weiyuai.cn/admin/)
## 开源客户端
- [桌面客户端](https://github.com/Bytedesk/bytedesk-desktop)
- [移动客户端](https://github.com/Bytedesk/bytedesk-mobile)
## 开源SDK
| Project | Description | Forks | Stars |
|-------------|-----------------------|----------------|-------------------|
| [iOS](https://github.com/bytedesk/bytedesk-swift) | iOS | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-swift) | ![GitHub Repo stars](https://img.shields.io/github/stars/Bytedesk/bytedesk-swift) |
| [Android](https://github.com/bytedesk/bytedesk-android) | Android | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-android) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-android) |
| [Flutter](https://github.com/bytedesk/bytedesk-flutter) | Flutter | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-flutter)| ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-flutter) |
| [UniApp](https://github.com/bytedesk/bytedesk-uniapp) | Uniapp | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-uniapp) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-uniapp) |
| [Web](https://github.com/bytedesk/bytedesk-web) | Vue/React/Angular/Next.js/JQuery/... | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-web) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-web) |
| [Wordpress](https://github.com/bytedesk/bytedesk-wordpress) | Wordpress | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-wordpress) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-wordpress) |
| [Woocommerce](https://github.com/bytedesk/bytedesk-woocommerce) | woocommerce | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-woocommerce) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-woocommerce) |
| [Magento](https://github.com/bytedesk/bytedesk-magento) | Magento | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-magento) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-magento) |
| [Prestashop](https://github.com/bytedesk/bytedesk-prestashop) | Prestashop | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-prestashop) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-prestashop) |
| [Shopify](https://github.com/bytedesk/bytedesk-shopify) | Shopify | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-shopify) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-shopify) |
| [Opencart](https://github.com/bytedesk/bytedesk-opencart) | Opencart | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-opencart) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-opencart) |
| [Laravel](https://github.com/bytedesk/bytedesk-laravel) | Laravel | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-laravel) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-laravel) |
| [Django](https://github.com/bytedesk/bytedesk-django) | Django | ![GitHub forks](https://img.shields.io/github/forks/bytedesk/bytedesk-django) | ![GitHub Repo stars](https://img.shields.io/github/stars/bytedesk/bytedesk-django) |
## 链接
- [下载](https://www.weiyuai.cn/download.html)
- [文档](https://www.weiyuai.cn/docs/zh-CN/)
## 技术栈
- [springboot-3.x for 后端](https://github.com/Bytedesk/bytedesk)
- [react for web前端](https://github.com/Bytedesk/bytedesk-web)
- [flutter for 移动客户端(ios&android)](https://github.com/Bytedesk/bytedesk-mobile)
- [electron for 桌面客户端(windows&mac&linux)](https://github.com/Bytedesk/bytedesk-desktop)
## 联系
- [网站](https://www.weiyuai.cn)
## 版权
- [Apache License 2.0](./LICENSE.txt)
- 此为开源社区版,支持免费商用

View File

@@ -1,203 +0,0 @@
# 企业知识库系统功能设计
## 1. 内容管理
### 1.1 文档管理
- 文档类型
- Markdown文档
- 富文本文档
- Office文档
- PDF文档
- 图文混排
- 代码文档
- 文档操作
- 在线创建/编辑
- 版本控制
- 文档导入/导出
- 文档模板
- 批量处理
- 文档预览
### 1.2 知识分类
- 分类体系
- 多级分类
- 标签管理
- 自定义属性
- 动态分类
- 关联关系
- 组织方式
- 树形结构
- 知识图谱
- 标签云
- 相关推荐
- 热门排序
## 2. 协同管理
### 2.1 权限控制
- 角色权限
- 超级管理员
- 分类管理员
- 文档管理员
- 普通用户
- 访客
- 权限维度
- 文档权限
- 分类权限
- 操作权限
- 数据权限
- 审核权限
### 2.2 工作流
- 文档流程
- 创建审核
- 修改审核
- 删除审核
- 发布审核
- 流程配置
- 协作流程
- 任务分配
- 协同编辑
- 评论反馈
- 变更通知
- 订阅推送
## 3. 智能功能
### 3.1 智能搜索
- 搜索功能
- 全文检索
- 语义搜索
- 相关搜索
- 高级筛选
- 搜索历史
- 搜索优化
- 关键词提取
- 同义词扩展
- 热门推荐
- 个性化排序
- 搜索建议
### 3.2 AI 赋能
- 内容生成
- AI写作助手
- 自动摘要
- 关键词提取
- 标签推荐
- 分类建议
- 智能应用
- 智能问答
- 知识推荐
- 相似文档
- 智能纠错
- 机器翻译
## 4. 知识应用
### 4.1 知识复用
- 内容引用
- 文档引用
- 片段引用
- 知识组件
- 模板复用
- 版本追踪
- 知识沉淀
- 最佳实践
- 案例库
- 问题库
- 方案库
- 培训资料
### 4.2 知识服务
- 对内服务
- 企业培训
- 新员工入职
- 技能提升
- 知识认证
- 内部分享
- 对外服务
- 产品文档
- API文档
- 帮助中心
- 客户支持
- 合作伙伴
## 5. 系统功能
### 5.1 数据管理
- 存储管理
- 文件存储
- 数据备份
- 垃圾清理
- 容量控制
- 存储优化
- 数据分析
- 使用统计
- 热点分析
- 趋势分析
- 用户画像
- 效果评估
### 5.2 系统集成
- 基础集成
- 单点登录
- 消息通知
- 文件预览
- 全文检索
- 在线编辑
- 业务集成
- OA系统
- CRM系统
- 项目管理
- 客服系统
- 培训系统
## 关键技术点
### 1.内容管理
文档版本控制
全文检索引擎
在线预览转换
协同编辑控制
### 2. 智能处理
NLP算法
机器学习模型
知识图谱
语义分析
### 3. 系统架构
分布式存储
缓存策略
搜索优化
权限控制
### 4. 业务集成
API接口设计
数据同步
消息通知
单点登录

View File

@@ -1,123 +0,0 @@
# 客服管理模块详细设计
## 1. 客服账号管理
### 1.1 账号基础信息
- 账号ID/工号
- 姓名/昵称
- 登录账号/密码
- 头像/个人简介
- 联系方式(手机/邮箱)
- 账号状态(启用/禁用)
### 1.2 账号操作管理
- 新建客服账号
- 编辑账号信息
- 重置密码
- 启用/禁用账号
- 删除账号
- 账号导入/导出
## 2. 客服分组管理
### 2.1 分组基础功能
- 创建客服组
- 设置组长/管理员
- 组内成员管理
- 组间成员调动
- 分组解散/合并
### 2.2 分组属性设置
- 分组名称/描述
- 服务类型标签
- 最大接待量
- 工作时间设置
- 自动分配规则
- 组内优先级
## 3. 客服权限管理
### 3.1 角色管理
- 超级管理员
- 组长/主管
- 普通客服
- 见习客服
- 质检人员
### 3.2 功能权限
- 会话管理权限
- 客户资料权限
- 知识库权限
- 报表统计权限
- 系统设置权限
- 质检评分权限
## 4. 客服状态管理
### 4.1 在线状态
- 在线/离线
- 忙碌/示闲
- 离开/小休
- 会议中
- 培训中
### 4.2 状态切换规则
- 手动切换
- 自动切换条件
- 强制状态变更
- 状态保持时长
- 状态变更通知
## 5. 工作时间管理
### 5.1 排班管理
- 固定班次设置
- 弹性工作制
- 轮班制度
- 临时调班
- 加班管理
- 请假管理
### 5.2 工作日历
- 法定节假日
- 工作日设置
- 特殊工作日
- 休息日设置
- 工作时段设置
## 6. 技能标签管理
### 6.1 技能体系
- 产品知识
- 业务类型
- 语言能力
- 专业领域
- 服务级别
- 解决能力
### 6.2 技能评级
- 技能等级划分
- 技能认证标准
- 技能考核指标
- 技能提升路径
- 技能匹配规则
### 6.3 技能应用
- 智能分配依据
- 会话转接条件
- 培训需求分析
- 绩效考核维度
- 晋升评估标准

View File

@@ -1,262 +0,0 @@
# 集成接口模块详细设计
## 1. REST API接口
### 1.1 认证鉴权
- 认证方式
- API Key认证
- OAuth2认证
- JWT认证
- 签名认证
- 权限控制
- 接口权限
- 数据权限
- 频率限制
- IP白名单
### 1.2 核心接口
- 客服管理接口
```http
POST /api/v1/agents # 创建客服账号
GET /api/v1/agents/{id} # 获取客服信息
PUT /api/v1/agents/{id} # 更新客服信息
DELETE /api/v1/agents/{id} # 删除客服账号
```
- 会话管理接口
```http
POST /api/v1/conversations # 创建会话
GET /api/v1/conversations/{id} # 获取会话信息
PUT /api/v1/conversations/{id} # 更新会话状态
DELETE /api/v1/conversations/{id} # 结束会话
```
- 消息管理接口
```http
POST /api/v1/messages # 发送消息
GET /api/v1/messages/{id} # 获取消息
PUT /api/v1/messages/{id} # 更新消息
DELETE /api/v1/messages/{id} # 删除消息
```
## 2. WebSocket接口
### 2.1 连接管理
- 连接建立
```javascript
// 建立WebSocket连接
const ws = new WebSocket('wss://api.bytedesk.com/ws?token=xxx')
// 连接事件处理
ws.onopen = () => {}
ws.onclose = () => {}
ws.onerror = () => {}
```
- 心跳机制
```javascript
// 发送心跳
setInterval(() => {
ws.send(JSON.stringify({type: 'ping'}))
}, 30000)
```
### 2.2 消息协议
- 消息格式
```json
{
"type": "message", // 消息类型
"action": "send", // 动作类型
"data": { // 消息内容
"from": "user_id",
"to": "agent_id",
"content": "消息内容",
"timestamp": 1635232823
}
}
```
- 事件通知
```json
{
"type": "event",
"action": "status_change",
"data": {
"agent_id": "xxx",
"status": "online",
"timestamp": 1635232823
}
}
```
## 3. 事件回调接口
### 3.1 回调配置
- 回调地址配置
- 回调验证方式
- 重试机制
- 超时设置
### 3.2 事件类型
- 会话事件
```json
{
"event": "conversation.created",
"timestamp": 1635232823,
"data": {
"conversation_id": "xxx",
"visitor_id": "xxx",
"agent_id": "xxx"
}
}
```
- 消息事件
```json
{
"event": "message.received",
"timestamp": 1635232823,
"data": {
"message_id": "xxx",
"conversation_id": "xxx",
"content": "xxx"
}
}
```
- 状态事件
```json
{
"event": "agent.status_changed",
"timestamp": 1635232823,
"data": {
"agent_id": "xxx",
"status": "online"
}
}
```
## 4. 第三方系统集成
### 4.1 CRM系统集成
- 客户数据同步
```json
{
"customer_id": "xxx",
"name": "张三",
"phone": "13800138000",
"level": "VIP",
"tags": ["重要客户"]
}
```
- 订单数据关联
```json
{
"order_id": "xxx",
"customer_id": "xxx",
"amount": 9999,
"status": "paid",
"create_time": "2023-10-26 12:00:00"
}
```
### 4.2 工单系统集成
- 工单创建
```json
{
"ticket_id": "xxx",
"title": "产品咨询",
"content": "详细内容...",
"priority": "high",
"category": "产品"
}
```
- 工单状态同步
```json
{
"ticket_id": "xxx",
"status": "processing",
"handler": "agent_id",
"update_time": "2023-10-26 12:00:00"
}
```
### 4.3 统计分析集成
- 数据推送接口
```http
POST /api/v1/statistics/push
Content-Type: application/json
{
"type": "conversation",
"metrics": {
"total": 100,
"success": 90,
"avg_duration": 300
},
"dimension": {
"date": "2023-10-26",
"agent_id": "xxx"
}
}
```
- 报表获取接口
```http
GET /api/v1/statistics/report?
type=conversation&
start_date=2023-10-01&
end_date=2023-10-31&
dimensions=agent,category
```
## 关键技术点
接口安全性
加密传输
身份认证
权限控制
防攻击措施
接口性能
连接池管理
缓存策略
限流措施
负载均衡
接口可用性
故障转移
服务降级
熔断机制
监控告警
接口扩展性
版本控制
协议兼容
数据格式
错误处理

View File

@@ -1,130 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-12-06 17:14:56
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-12-06 17:15:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# 自动化功能详细设计
## 1. 智能分配规则
### 1.1 基础分配策略
- 轮询分配 - 按顺序轮流分配给客服
- 最少会话优先 - 分配给当前会话数最少的客服
- 最长空闲优先 - 分配给空闲时间最长的客服
- 技能组优先 - 根据访客问题类型分配给对应技能组
### 1.2 高级分配规则
- 客服评分权重 - 根据客服历史服务评分加权分配
- 客服繁忙度 - 考虑客服当前会话数和状态
- VIP访客优先 - 重要访客优先分配给资深客服
- 历史会话优先 - 优先分配给曾经服务过的客服
## 2. 自动欢迎语
### 2.1 欢迎语触发条件
- 首次访问触发
- 重复访问差异化欢迎语
- 不同时段差异化欢迎语
- 不同页面差异化欢迎语
### 2.2 欢迎语内容配置
- 支持文本/图片/链接
- 支持变量替换(访客名称等)
- 支持多语言
- 支持A/B测试
## 3. 智能自动回复
### 3.1 规则配置
- 关键词匹配规则
- 相似度匹配
- 正则表达式匹配
- 意图识别
### 3.2 回复内容
- 标准答案库
- 知识库关联
- 常见问题推荐
- 智能推荐相关问题
### 3.3 触发条件
- 访客无响应时
- 客服离线时
- 排队等待时
- 指定时间段
## 4. 排队机制
### 4.1 排队策略
- 先进先出
- VIP优先
- 紧急程度优先
- 综合权重排序
### 4.2 排队提醒
- 定时发送排队位置
- 预计等待时间
- 推荐自助服务
- 留言提醒
## 5. 超时提醒
### 5.1 访客超时
- 无响应超时提醒
- 会话即将结束提醒
- 自动结束会话
- 邀请评价
### 5.2 客服超时
- 未回复提醒
- 会话转接提醒
- 工作量预警
- 绩效影响提醒
## 6. 满意度评价
### 6.1 评价触发
- 会话结束自动触发
- 手动邀请评价
- 定时发送评价
- 多轮会话评价
### 6.2 评价维度
- 整体满意度
- 响应速度
- 服务态度
- 解决效果
### 6.3 评价反馈
- 评价结果统计
- 不满意原因分析
- 客服绩效关联
- 改进建议收集
这些自动化功能可以:
提高客服效率,减少人工干预
提升访客体验,快速响应需求
保证服务质量,标准化服务流程
收集数据分析,持续优化服务

View File

@@ -1,195 +0,0 @@
# 系统配置模块详细设计
## 1. 工作时间配置
### 1.1 基础时间设置
- 工作日设置
- 周一至周五
- 自定义工作日
- 法定节假日
- 特殊工作日
- 时间段设置
- 上午工作时间
- 下午工作时间
- 午休时间
- 加班时间
### 1.2 高级配置
- 时区设置
- 多时区支持
- 自动时区转换
- 班次管理
- 固定班次
- 弹性工作制
- 轮班制度
- 排班规则
## 2. 分配规则配置
### 2.1 基础分配规则
- 轮询分配
- 顺序轮询
- 权重轮询
- 随机轮询
- 智能分配
- 最少会话优先
- 最长空闲优先
- 技能优先匹配
- 评分权重分配
### 2.2 高级分配规则
- 客户等级规则
- VIP客户优先
- 老客户优先
- 特殊客户定向
- 业务类型规则
- 产品类型匹配
- 问题类型匹配
- 专业技能匹配
- 语言能力匹配
## 3. 自动回复配置
### 3.1 触发条件
- 时间触发
- 非工作时间
- 等待超时
- 指定时段
- 场景触发
- 首次访问
- 排队等待
- 转接过程
- 结束会话
### 3.2 回复内容
- 消息模板
- 文本模板
- 图片模板
- 链接模板
- 商品卡片
- 智能回复
- 关键词匹配
- 相似度匹配
- 意图识别
- 知识库关联
## 4. 评价配置
### 4.1 评价触发
- 自动触发
- 会话结束
- 超时触发
- 定时触发
- 手动触发
- 客服邀请
- 访客主动
- 管理员触发
### 4.2 评价内容
- 评分设置
- 星级评分
- 满意度评分
- 多维度评分
- 评价表单
- 问题选项
- 建议反馈
- 标签选择
- 文字评价
## 5. 提醒配置
### 5.1 提醒类型
- 客服提醒
- 新会话提醒
- 等待超时提醒
- 转接提醒
- 评价提醒
- 访客提醒
- 排队提醒
- 等待提醒
- 会话即将结束
- 满意度评价
### 5.2 提醒方式
- 站内提醒
- 消息提醒
- 弹窗提醒
- 声音提醒
- 外部提醒
- 邮件通知
- 短信通知
- APP推送
- 微信通知
## 6. 黑名单配置
### 6.1 黑名单规则
- 自动拦截
- IP限制
- 设备限制
- 账号限制
- 行为限制
- 人工管理
- 手动添加
- 批量导入
- 定期清理
- 白名单
### 6.2 处理策略
- 拦截方式
- 完全拒绝
- 限制访问
- 转机器人
- 特殊队列
- 解封机制
- 自动解封
- 申诉解封
- 人工审核
- 永久封禁
## 关键技术点
配置管理
配置持久化
配置热更新
配置版本控制
配置同步机制
规则引擎
规则解析
规则匹配
规则执行
规则优先级
系统集成
消息系统
通知系统
评价系统
权限系统
监控告警
配置变更监控
规则执行监控
系统性能监控
异常告警

View File

@@ -1,87 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-12-02 13:21:01
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-12-06 17:56:08
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# 在线客服模块主要功能
- agent一对一人工客服不支持机器人接待
- robot机器人客服不支持转人工
- workgroup工作组支持机器人接待支持转人工
## 1. [客服管理](./readme.zh.account.md)
- 客服账号管理(添加/删除/禁用客服)
- 客服分组管理
- 客服权限管理
- 客服状态管理(在线/离线/忙碌等)
- 客服工作时间管理
- 客服技能标签管理
## 2. [会话管理](./readme.zh.thread.md)
- 访客会话分配
- 会话排队管理
- 会话转接
- 会话监控
- 会话记录存储
- 历史会话查询
## 3. [消息管理](./readme.zh.message.md)
- 实时消息收发
- 消息类型支持(文本/图片/文件等)
- 消息存储
- 消息撤回
- 敏感词过滤
- 消息记录查询
## 4. [访客管理](./readme.zh.visitor.md)
- 访客信息采集
- 访客轨迹记录
- 访客黑名单管理
- 访客标签管理
- 访客分流规则
## 5. [自动化功能管理](./readme.zh.automation.md)
- 智能分配规则
- 自动欢迎语
- 自动回复
- 排队提醒
- 超时提醒
- 满意度评价
## 6. [统计分析](./readme.zh.statistic.md)
- 客服工作量统计
- 会话量统计
- 响应时间统计
- 满意度统计
- 分流统计
- 客服绩效分析
## 7. [系统配置](./readme.zh.config.md)
- 工作时间配置
- 分配规则配置
- 自动回复配置
- 评价配置
- 提醒配置
- 黑名单配置
## 8. [集成接口](./readme.zh.api.md)
- REST API接口
- WebSocket接口
- 事件回调接口
- 第三方系统集成

View File

@@ -1,156 +0,0 @@
# 消息管理模块详细设计
## 1. 实时消息收发
### 1.1 消息通道
- WebSocket长连接
- HTTP轮询备选
- Server-Sent Events
- Signal协议加密通道
- 消息推送通道(APP)
### 1.2 消息处理流程
- 消息发送确认(ACK)
- 消息送达回执
- 消息读取状态
- 消息重发机制
- 消息排序处理
- 消息限流控制
## 2. 消息类型支持
### 2.1 基础消息类型
- 文本消息
- 纯文本
- 富文本
- Markdown
- 表情/贴纸
- 媒体消息
- 图片(JPG/PNG/GIF)
- 语音(MP3/WAV)
- 视频(MP4)
- 文件(PDF/DOC等)
### 2.2 特殊消息类型
- 系统消息
- 会话状态变更
- 客服转接通知
- 评价邀请
- 排队提醒
- 交互消息
- 商品卡片
- 订单信息
- 支付链接
- 位置信息
- 快捷回复
- 满意度评价
## 3. 消息存储
### 3.1 存储架构
- 分布式消息队列
- 实时数据库
- 对象存储(媒体文件)
- 时序数据库
- 冷热数据分离
### 3.2 存储策略
- 消息分片存储
- 多副本备份
- 压缩加密
- 定期归档
- 分级存储
- 容灾备份
## 4. 消息撤回
### 4.1 撤回规则
- 时间限制(如2分钟内)
- 权限控制
- 撤回次数限制
- 特殊消息限制
- 双向撤回
### 4.2 撤回处理
- 消息标记
- 历史记录保留
- 撤回通知
- 客户端同步
- 离线处理
- 撤回失败处理
## 5. 敏感词过滤
### 5.1 过滤机制
- 关键词匹配
- 正则表达式
- 语义分析
- 机器学习模型
- 图片OCR识别
- 声纹识别
### 5.2 处理策略
- 实时拦截
- 替换屏蔽
- 警告提醒
- 人工审核
- 账号惩罚
- 日志记录
## 6. 消息记录查询
### 6.1 查询功能
- 多维度检索
- 时间范围
- 会话ID
- 消息类型
- 关键词
- 参与者
- 高级过滤
- 消息状态
- 敏感级别
- 已读未读
- 是否撤回
- 是否加密
### 6.2 查询优化
- 索引优化
- 缓存策略
- 分页加载
- 预加载
- 增量同步
- 导出备份
## 关键技术要点
实时性保证
WebSocket集群
消息队列
分布式缓存
可靠性保证
消息持久化
ACK机制
失败重试
安全性保证
端到端加密
敏感词过滤
访问控制
4. 性能保证
分库分表
读写分离
索引优化

View File

@@ -1,178 +0,0 @@
# 统计分析模块详细设计
## 1. 客服工作量统计
### 1.1 时间维度统计
- 实时工作量
- 当前会话数
- 排队人数
- 等待处理数
- 超时会话数
- 历史工作量
- 日统计
- 周统计
- 月统计
- 季度统计
- 年度统计
### 1.2 业务维度统计
- 会话处理量
- 接待总量
- 成功会话
- 失败会话
- 转接会话
- 消息处理量
- 发送消息数
- 接收消息数
- 平均消息数
- 消息类型占比
## 2. 会话量统计
### 2.1 会话分析
- 会话总量
- 总会话数
- 有效会话数
- 无效会话数
- 人工会话数
- 机器人会话数
- 会话分布
- 时段分布
- 渠道分布
- 地域分布
- 终端分布
- 来源分布
### 2.2 会话质量
- 会话时长
- 平均时长
- 最长时长
- 最短时长
- 异常时长
- 会话效果
- 解决率
- 转化率
- 流失率
- 重复率
## 3. 响应时间统计
### 3.1 首次响应
- 平均首响时间
- 最长首响时间
- 首响达标率
- 超时统计
- 分时段分析
### 3.2 消息响应
- 平均响应时间
- 消息间隔时间
- 响应速度分布
- 等待时间分析
- 超时预警统计
## 4. 满意度统计
### 4.1 评价维度
- 整体满意度
- 评价率
- 满意率
- 不满意率
- 平均分
- 细分维度
- 服务态度
- 专业程度
- 响应速度
- 解决效果
### 4.2 满意度分析
- 趋势分析
- 客服对比
- 问题类型
- 时段分析
- 渠道分析
- 客群分析
## 5. 分流统计
### 5.1 分配分析
- 分配成功率
- 平均分配时间
- 转接统计
- 排队统计
- 溢出统计
### 5.2 分流效果
- 技能组分析
- 客服匹配度
- 分流准确率
- 客户满意度
- 解决效率
## 6. 客服绩效分析
### 6.1 工作指标
- 工作时长
- 在线时长
- 忙碌时长
- 空闲时长
- 离线时长
- 工作效率
- 会话量
- 消息量
- 解决率
- 转化率
### 6.2 质量指标
- 服务质量
- 满意度评分
- 投诉率
- 表扬数
- 质检得分
- KPI指标
- 目标完成率
- 绩效得分
- 排名情况
- 奖惩记录
## 关键技术点
数据采集层
实时数据收集
历史数据同步
多维度采集
数据清洗
数据存储层
实时数据库
数据仓库
数据湖
多维分析
数据计算层
实时计算
离线计算
指标计算
数据建模
数据展示层
实时看板
统计报表
趋势图表
钻取分析

View File

@@ -1,127 +0,0 @@
# 会话管理模块详细设计
## 1. 访客会话分配
### 1.1 分配策略
- 轮询分配(Round Robin)
- 最少会话优先(Least Connection)
- 最长空闲优先(Longest Idle)
- 技能组优先(Skill Based)
- 客服评分权重(Rating Based)
### 1.2 分配规则引擎
- 访客等级规则
- 产品类型规则
- 来源渠道规则
- 地域规则
- 客服状态规则
- 工作时间规则
## 2. 会话排队管理
### 2.1 排队机制
- 优先级队列
- 多级队列
- VIP快速通道
- 超时升级机制
- 排队限制策略
### 2.2 排队体验优化
- 实时排队位置
- 预计等待时间
- 排队提醒消息
- 智能分流建议
- 留言转工单
- 机器人答疑
## 3. 会话转接
### 3.1 转接类型
- 手动转接
- 自动转接
- 技能组转接
- 会话升级
- 跨部门转接
### 3.2 转接流程
- 转接前确认
- 转接原因记录
- 会话记录传递
- 客服交接确认
- 访客通知提醒
- 转接失败处理
## 4. 会话监控
### 4.1 实时监控
- 在线会话列表
- 排队情况监控
- 客服状态监控
- 会话质量监控
- 敏感词监控
- 异常行为监控
### 4.2 质量管理
- 会话内容审查
- 服务质量评估
- 响应时间监控
- 满意度跟踪
- 投诉处理
- 质检打分
## 5. 会话记录存储
### 5.1 存储内容
- 基础会话信息
- 消息记录
- 多媒体内容
- 系统事件
- 操作日志
- 客服备注
### 5.2 存储策略
- 分表分库
- 冷热数据分离
- 数据压缩
- 定期归档
- 加密存储
- 备份策略
## 6. 历史会话查询
### 6.1 查询维度
- 时间范围
- 客服/访客
- 会话状态
- 会话类型
- 满意度评价
- 关键词检索
### 6.2 高级功能
- 全文检索
- 多条件组合
- 导出报表
- 会话回放
- 统计分析
- 质检复查
## 关键技术点
分配算法的公平性和效率
排队机制的可扩展性
转接流程的无缝衔接
监控系统的实时性
存储系统的高性能
检索系统的易用性

View File

@@ -1,177 +0,0 @@
# 访客管理模块详细设计
## 1. 访客信息采集
### 1.1 基础信息采集
- 访客ID/标识
- 昵称/姓名
- 联系方式(手机/邮箱)
- IP地址/地理位置
- 设备信息
- 操作系统
- 浏览器类型
- 设备型号
- 分辨率
### 1.2 来源信息
- 访问来源
- 搜索引擎
- 社交媒体
- 外部链接
- 直接访问
- 落地页面
- 推广渠道
- UTM参数
- 关键词
### 1.3 用户画像
- 访问频次
- 停留时长
- 消费能力
- 兴趣偏好
- 行为特征
- 价值等级
## 2. 访客轨迹记录
### 2.1 行为轨迹
- 页面浏览
- 访问页面
- 停留时间
- 点击事件
- 滚动深度
- 功能操作
- 搜索记录
- 商品浏览
- 加购行为
- 订单操作
### 2.2 会话轨迹
- 历史会话
- 咨询问题
- 服务评价
- 投诉记录
- 购买记录
### 2.3 轨迹分析
- 行为分析
- 兴趣挖掘
- 意图识别
- 价值评估
- 流失预警
## 3. 访客黑名单管理
### 3.1 黑名单规则
- 加入条件
- 恶意骚扰
- 言语攻击
- 营销推广
- 刷单欺诈
- 重复投诉
- 黑名单级别
- 临时限制
- 永久封禁
- 部分限制
- 全站封禁
### 3.2 黑名单处理
- 自动识别
- 人工审核
- 申诉处理
- 解封机制
- 预警提醒
## 4. 访客标签管理
### 4.1 标签体系
- 系统标签
- 价值等级
- 活跃度
- 购买意向
- 服务偏好
- 业务标签
- 产品兴趣
- 咨询类型
- 问题分类
- 客户类型
- 自定义标签
- 客服备注
- 特殊标记
- 跟进状态
- 个性化标签
### 4.2 标签应用
- 智能分配
- 个性化服务
- 精准营销
- 数据分析
- 客户分层
## 5. 访客分流规则
### 5.1 分流维度
- 访客属性
- 新老客户
- 会员等级
- 消费能力
- 地理位置
- 业务属性
- 产品类型
- 咨询内容
- 紧急程度
- 特殊需求
### 5.2 分流策略
- 优先级策略
- VIP优先
- 老客户优先
- 紧急优先
- 技能匹配
- 产品专员
- 售后专员
- 技术支持
- 投诉专员
- 负载均衡
- 客服状态
- 工作量
- 服务质量
- 专业程度
## 关键技术点
数据采集
前端埋点
行为追踪
实时同步
数据处理
实时计算
标签系统
规则引擎
数据应用
智能分配
精准营销
个性化服务
数据安全
隐私保护
脱敏处理
访问控制

View File

@@ -1,183 +0,0 @@
# 企业IM系统功能设计
## 1. 即时通讯核心功能
### 1.1 单聊(一对一)
- 消息收发
- 文本消息
- 图片消息
- 语音消息
- 视频消息
- 文件消息
- 表情/贴纸
- @提醒功能
- 消息撤回
- 已读回执
- 会话管理
- 会话列表
- 置顶会话
- 免打扰设置
- 会话归档
- 消息搜索
- 历史记录
### 1.2 群聊功能
- 群组管理
- 创建群组
- 解散群组
- 群组设置
- 群公告
- 群头像
- 群分类
- 成员管理
- 邀请成员
- 移除成员
- 退出群组
- 群主转让
- 管理员设置
- 成员禁言
## 2. 组织架构管理
### 2.1 部门管理
- 部门结构
- 多级部门
- 部门主管
- 部门成员
- 跨部门设置
- 权限控制
- 部门权限
- 数据权限
- 功能权限
- 审批权限
### 2.2 成员管理
- 账号管理
- 账号创建
- 账号禁用
- 密码重置
- 角色分配
- 权限设置
- 员工信息
- 基本信息
- 联系方式
- 职位信息
- 工作状态
- 考勤打卡
## 3. 协作功能
### 3.1 工作协同
- 任务管理
- 任务分配
- 任务跟踪
- 任务提醒
- 任务报告
- 日程管理
- 日程创建
- 日程共享
- 日程提醒
- 会议预约
### 3.2 文件协作
- 文件管理
- 文件上传
- 文件共享
- 文件预览
- 版本控制
- 权限管理
- 知识库
- 文档创建
- 协同编辑
- 文档分类
- 全文检索
## 4. 安全管理
### 4.1 访问控制
- 登录安全
- 密码策略
- 双因素认证
- 登录限制
- 异地登录
- 数据安全
- 端到端加密
- 敏感词过滤
- 防泄密管理
- 审计日志
### 4.2 合规管理
- 消息审计
- 内容审核
- 行为监控
- 违规预警
- 报告导出
- 数据合规
- 数据备份
- 数据归档
- 隐私保护
- 合规报告
## 5. 系统集成
### 5.1 基础集成
- 单点登录(SSO)
- 通讯录同步
- 消息推送
- 文件存储
- 音视频服务
### 5.2 业务集成
- OA系统集成
- CRM系统集成
- 工单系统集成
- 考勤系统集成
- 审批系统集成
## 关键技术点
### 1. 实时通讯
WebSocket长连接
消息可靠投递
多端消息同步
离线消息处理
### 2. 高可用架构
分布式部署
负载均衡
故障转移
数据备份
### 3. 安全机制
数据加密
访问控制
安全审计
合规管理
### 4. 性能优化
消息分片
大文件传输
消息压缩
缓存策略

View File

@@ -1,74 +0,0 @@
# 工单系统
这个工单系统具有以下主要功能:
## 通知
- 钉钉
- 企业微信
- 飞书
- 邮件
- 短信
- 微信公众号
## 工单管理
- 创建、查看、更新、删除工单
- 工单分类和优先级管理
- 工单状态流转(开启->处理中->已解决->已关闭)
- 工单分配和转派
- 工单截止日期设置
- 工单附件上传和管理
- 工单导出Excel
- 工单分类
- 工单标签
- 工单模板
- 工单统计
- 工单报表
- 工单自动回复
## 评论系统
- 支持客户和客服的工单交互
- 内部评论功能(对客户不可见)
- 评论回复功能
- 评论附件支持
## SLA管理
- 服务级别协议设置
- 响应时限和解决时限监控
- 工作时间设置
- 超时提醒和升级
- SLA规则配置
- 响应时间和解决时间监控
- 自动升级处理
- 违规提醒
## 统计和报表
- 工单量统计
- 响应时间统计
- 解决时间统计
- 满意度统计
- 客服绩效统计
- 导出Excel/PDF报表
## 自动化功能
- 多种分配策略(轮询、最少活跃、负载均衡、技能匹配等)
- 自定义分配规则
- 考虑在线状态和工作负载
- 自动分类
- 自动提醒
- 工单升级规则
修复已知bug使项目能够运行
## 增值功能
- 消息通知:站内信、用户端推送等
- 关键数据:展示当前节点处理人最希望看到的数据
- 移动办公H5形式接入钉钉、微信服务号、企业微信等
- 增值操作:“协同”,即可以选择指定人(通常是助理),替自己处理一些审批
- 实时跟踪:可以实时查看当前所处节点,以及对应处理人,并可对其发起“催办”

View File

@@ -1,65 +0,0 @@
# 客户之声,意见反馈
## 功能设计
## 1. 反馈收集渠道
内部表单收集
社交媒体评论抓取
邮件反馈
第三方平台评论同步
小程序/APP内嵌反馈入口
## 2. 反馈类型管理
产品建议
服务投诉
功能需求
技术支持
其他
## 3. 反馈处理流程
```bash
graph TD
A[用户提交反馈] --> B{反馈类型}
B --> |产品建议| C[产品经理评审]
B --> |服务投诉| D[客服跟进]
B --> |功能需求| E[技术团队评估]
C --> F[分配处理人]
D --> F
E --> F
F --> G[跟踪处理]
G --> H[反馈回复]
H --> I[结案]
```
## 4. 通知机制
邮件通知
站内信
企业微信/钉钉机器人通知
## 5. 高级特性
敏感词过滤
自动分类
智能路由
满意度跟踪
## 6. 性能与安全考虑
使用异步处理
限流
数据脱敏
访问控制
## 实施步骤
- 先实现基础功能
- 逐步引入AI/机器学习能力
- 持续迭代优化
## 总结
该模块旨在构建一个全面、智能的客户反馈收集与处理系统,通过多渠道、智能分析,帮助企业更好地理解和响应客户需求。

View File

@@ -1,68 +0,0 @@
---
sidebar_label: 管理后台
sidebar_position: 4
---
# 管理后台
## [Nginx](./depend/nginx)
本地部署可不需要仅在生产环境推荐安装nginxnginx做反向代理
## 准备
- 将下载的 [server](https://www.weiyuai.cn/download/weiyu-server.zip) 文件解压,解压后的文件结构如下
```bash
(base) server % tree -L 1
.
├── admin
├── agent
├── bytedesk-starter-0.4.0.jar
├── chat
├── config
├── logs
├── readme.md
├── readme.zh.md
├── start.bat
├── start.sh
├── stop.bat
├── stop.sh
└── uploader
7 directories, 7 files
```
- 将其中的 adminagentchat 三个文件夹复制到 /var/www/html/weiyuai/ 文件夹下。
- 其中admin 为管理后台agent 为客户端chat 为访客端
- 三者默认访问的服务器地址为: http://127.0.0.1:9003, 发布到线上时需要修改才能够正常使用,具体修改方法如下:
- 找到 admin/config.json 、 agent/config.json 和 chat/config.json 三个文件
- config.json 文件内容如下:
```json
{
"enabled": true,
"apiUrl": "https://api.weiyuai.cn",
"websocketUrl": "wss://api.weiyuai.cn/websocket",
"htmlUrl": "https://www.weiyuai.cn"
}
```
- enabled 字段为是否启用自定义服务器地址,默认为 false。这里需要将 false 改为 true。只有修改为 true下面的 apiHost 和 htmlHost 才能生效
- apiUrl 字段为 api 地址默认为api.weiyuai.cn请替换为自己的域名
- websocketUrl 字段为 websocket 地址默认为ws://api.weiyuai.cn/websocket请替换为自己的域名
- htmlHost 字段为静态网页地址默认为www.weiyuai.cn请替换为自己的域名
## 替换为ip实例
- 将域名替换为ip
- 将https替换为http
```json
{
"enabled": false,
"apiUrl": "http://127.0.0.1:9003",
"websocketUrl": "ws://127.0.0.1:9885/websocket",
"htmlUrl": "http://127.0.0.1:9006"
}
```

View File

@@ -1,68 +0,0 @@
---
sidebar_label: 客户端Web
sidebar_position: 5
---
# 客户端Web
## [Nginx](./depend/nginx)
本地部署可不需要仅在生产环境推荐安装nginxnginx做反向代理
## 准备
- 将下载的 [server](https://www.weiyuai.cn/download/weiyu-server.zip) 文件解压,解压后的文件结构如下
```bash
(base) server % tree -L 1
.
├── admin
├── agent
├── bytedesk-starter-0.4.0.jar
├── chat
├── config
├── logs
├── readme.md
├── readme.zh.md
├── start.bat
├── start.sh
├── stop.bat
├── stop.sh
└── uploader
7 directories, 7 files
```
- 将其中的 adminagentchat 三个文件夹复制到 /var/www/html/weiyuai/ 文件夹下。
- 其中admin 为管理后台agent 为客户端chat 为访客端
- 三者默认访问的服务器地址为: http://127.0.0.1:9003, 发布到线上时需要修改才能够正常使用,具体修改方法如下:
- 找到 admin/config.json 、 agent/config.json 和 chat/config.json 三个文件
- config.json 文件内容如下:
```json
{
"enabled": false,
"apiUrl": "https://api.weiyuai.cn",
"websocketUrl": "wss://api.weiyuai.cn/websocket",
"htmlUrl": "https://www.weiyuai.cn"
}
```
- enabled 字段为是否启用自定义服务器地址,默认为 false。这里需要将 false 改为 true。只有修改为 true下面的 apiHost 和 htmlHost 才能生效
- apiUrl 字段为 api 地址默认为api.weiyuai.cn请替换为自己的域名
- websocketUrl 字段为 websocket 地址默认为ws://api.weiyuai.cn/websocket请替换为自己的域名
- htmlHost 字段为静态网页地址默认为www.weiyuai.cn请替换为自己的域名
## 替换为ip实例
- 将域名替换为ip
- 将https替换为http
```json
{
"enabled": false,
"apiUrl": "http://127.0.0.1:9003",
"websocketUrl": "ws://127.0.0.1:9885/websocket",
"htmlUrl": "http://127.0.0.1:9006"
}
```

View File

@@ -1,237 +0,0 @@
---
title: 宝塔面板部署
sidebar_label: 宝塔面板
sidebar_position: 9
description: 使用宝塔面板部署 ByteDesk
---
## 步骤一
- ![agent](/img/deploy/baota/baota_1.png)
## 步骤二:添加容器编排
- ![agent](/img/deploy/baota/baota_2.png)
### 复制如下编排内容
- [最新docker-compose.yaml](https://gitee.com/270580156/weiyu/blob/main/deploy/docker/docker-compose.yaml)
```bash
services:
bytedesk-mysql:
image: mysql:latest
container_name: mysql-bytedesk
environment:
MYSQL_DATABASE: bytedesk
MYSQL_ROOT_PASSWORD: r8FqfdbWUaN3
ports:
- "13306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- bytedesk-network
bytedesk-redis:
image: redis/redis-stack-server:latest
container_name: redis-bytedesk
ports:
- "16379:6379"
environment:
- REDIS_ARGS=--requirepass qfRxz3tVT8Nh
volumes:
- redis_data:/data
networks:
- bytedesk-network
bytedesk:
# image: bytedesk/bytedesk:latest # hub.docker.com enterprise
# image: bytedesk/bytedesk-ce:latest # hub.docker.com community
image: registry.cn-hangzhou.aliyuncs.com/bytedesk/bytedesk:latest # aliyun enterprise
# mage: registry.cn-hangzhou.aliyuncs.com/bytedesk/bytedesk-ce:latest # aliyun community
container_name: bytedesk
depends_on:
- bytedesk-mysql
- bytedesk-redis
environment:
# db config
SPRING_DATASOURCE_URL: jdbc:mysql://mysql-bytedesk:3306/bytedesk?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: r8FqfdbWUaN3
SPRING_JPA_HIBERNATE_DDL_AUTO: update
# redis config
SPRING_DATA_REDIS_HOST: redis-bytedesk
SPRING_DATA_REDIS_PORT: 6379
SPRING_DATA_REDIS_PASSWORD: qfRxz3tVT8Nh
SPRING_DATA_REDIS_DATABASE: 0
# bytedesk config
BYTEDESK_DEBUG: true
BYTEDESK_EDITION: enterprise
BYTEDESK_NAME:
BYTEDESK_LOGO:
BYTEDESK_DESCRIPTION: bytedesk description
BYTEDESK_VERSION: 0.6.2
# Admin config
BYTEDESK_ADMIN_EMAIL: admin@email.com
BYTEDESK_ADMIN_PASSWORD: admin
BYTEDESK_ADMIN_PASSWORD_DEFAULT: 123456
BYTEDESK_ADMIN_NICKNAME: SuperAdmin
BYTEDESK_ADMIN_MOBILE: 13345678000
BYTEDESK_ADMIN_MOBILE_WHITELIST: 18888888000,18888888001,18888888002,18888888003,18888888004,18888888005
BYTEDESK_ADMIN_EMAIL_WHITELIST: 100@email.com,101@email.com,102@email.com,103@email.com,104@email.com,105@email.com
BYTEDESK_ADMIN_VALIDATE_CODE: 123456
BYTEDESK_ADMIN_FORCE_VALIDATE_MOBILE: true
BYTEDESK_ADMIN_FORCE_VALIDATE_EMAIL: true
# Organization config
BYTEDESK_ORGANIZATION_NAME: MyCompany
BYTEDESK_ORGANIZATION_CODE: bytedesk
# Features config
BYTEDESK_FEATURES_JAVA_AI: false
BYTEDESK_FEATURES_PYTHON_AI: true
BYTEDESK_FEATURES_EMAIL_TYPE: javamail
BYTEDESK_FEATURES_ENABLE_REGISTRATION: false
BYTEDESK_FEATURES_AVATAR_BASE_URL:
# CORS config
# BYTEDESK_CORS_ALLOWED_ORIGINS: *
# JWT config
BYTEDESK_JWT_SECRET_KEY: 1dfaf8d004207b628a9a6b859c429f49a9a7ead9fd8161c1e60847aeef06dbd2
BYTEDESK_JWT_EXPIRATION: 2592000000
BYTEDESK_JWT_REFRESH_TOKEN_EXPIRATION: 5184000000
# Cache config
BYTEDESK_CACHE_LEVEL: 0
BYTEDESK_CACHE_PREFIX: bytedeskim
BYTEDESK_CACHE_REDIS_STREAM_KEY: bytedeskim:stream
# Upload config
BYTEDESK_UPLOAD_TYPE: local
BYTEDESK_UPLOAD_DIR: /app/uploads
# 上传文件的访问地址,请修改为服务器实际的地址
BYTEDESK_UPLOAD_URL: http://127.0.0.1:9003
# Knowledge base config
BYTEDESK_KBASE_THEME: default
BYTEDESK_KBASE_HTML_PATH: helpcenter
# 知识库的访问地址,请修改为服务器实际的地址
BYTEDESK_KBASE_API_URL: http://127.0.0.1:9003
# Socket config
BYTEDESK_SOCKET_HOST: 0.0.0.0
BYTEDESK_SOCKET_WEBSOCKET_PORT: 9885
BYTEDESK_SOCKET_LEAK_DETECTOR_LEVEL: SIMPLE
BYTEDESK_SOCKET_PARENT_EVENT_LOOP_GROUP_THREAD_COUNT: 1
BYTEDESK_SOCKET_CHILD_EVENT_LOOP_GROUP_THREAD_COUNT: 8
BYTEDESK_SOCKET_MAX_PAYLOAD_SIZE: 10240
# Cluster config
BYTEDESK_CLUSTER_ENABLED: false
# Push config
# BYTEDESK_PUSH_APNS_BUNDLE_ID: com.kefux.im
# BYTEDESK_PUSH_APNS_P12_URL: 123.p12
# BYTEDESK_PUSH_APNS_P12_PASSWORD: 123456
# Actuator security configuration
MANAGEMENT_ENDPOINTS_ENABLED_BY_DEFAULT: false
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: ''
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_EXCLUDE: '*'
MANAGEMENT_ENDPOINT_HEALTH_ENABLED: false
MANAGEMENT_ENDPOINT_INFO_ENABLED: false
MANAGEMENT_SERVER_PORT: -1
MANAGEMENT_ENDPOINTS_WEB_BASE_PATH: '/management'
SPRING_SECURITY_BASIC_ENABLED: true
# ai config
# zhipuai
SPRING_AI_ZHIPUAI_CHAT_ENABLED: false
SPRING_AI_ZHIPUAI_API_KEY: ''
SPRING_AI_ZHIPUAI_CHAT_OPTIONS_MODEL: glm-4-flash
SPRING_AI_ZHIPUAI_CHAT_OPTIONS_TEMPERATURE: 0.7
# ollama
SPRING_AI_OLLAMA_CHAT_ENABLED: true
SPRING_AI_OLLAMA_BASE_URL: http://host.docker.internal:11434
# SPRING_AI_OLLAMA_CHAT_OPTIONS_MODEL: qwen:7b
# SPRING_AI_OLLAMA_CHAT_OPTIONS_TEMPERATURE: 0.7
# SPRING_AI_OLLAMA_EMBEDDING_ENABLED: false
# openai/deepseek
# https://docs.spring.io/spring-ai/reference/api/chat/deepseek-chat.html
SPRING_AI_OPENAI_CHAT_ENABLED: false
SPRING_AI_OPENAI_API_KEY: ''
SPRING_AI_OPENAI_BASE_URL: https://api.deepseek.com
# SPRING_AI_OPENAI_CHAT_MODEL: deepseek-chat
SPRING_AI_OPENAI_CHAT_OPTIONS_MODEL: deepseek-chat
SPRING_AI_OPENAI_CHAT_OPTIONS_TEMPERATURE: 0.7
SPRING_AI_OPENAI_EMBEDDING_ENABLED: false
# moonshot
SPRING_AI_MOONSHOT_CHAT_ENABLED: false
SPRING_AI_MINIMAX_CHAT_ENABLED: false
# vector store
SPRING_AI_VECTORSTORE_REDIS_INITIALIZE_SCHEMA: true
SPRING_AI_VECTORSTORE_REDIS_URI: redis://:qfRxz3tVT8Nh@redis-bytedesk:6379
# wechat config
WECHAT_PAY_ENABLED: false
ports:
- 9003:9003
- 9885:9885
volumes:
- upload_data:/app/uploads
networks:
- bytedesk-network
volumes:
mysql_data:
redis_data:
upload_data:
networks:
bytedesk-network:
driver: bridge
```
### 因项目默认使用ollama qwen3:0.6b模型,所以需要提前拉取模型
```bash
ollama pull deepseek-r1:1.5b
ollama pull qwen3:0.6b
# 或docker拉取
# docker exec ollama pull qwen3:0.6b
```
### 修改配置,否则上传图片、文件和知识库无法正常显示
- 修改上述编排文件
```bash
# 请将服务器127.0.0.1替换为你的服务器ip
BYTEDESK_UPLOAD_URL: http://127.0.0.1:9003
BYTEDESK_KBASE_API_URL: http://127.0.0.1:9003
```
## 步骤三:等待中
- ![agent](/img/deploy/baota/baota_3.png)
## 步骤四:添加完成,关闭窗口
- ![agent](/img/deploy/baota/baota_4.png)
## 步骤五:安装成功
- ![agent](/img/deploy/baota/baota_5.png)
## 步骤六:开放端口
请开放内网入方向端口
- 9003
- 9885
## 步骤七:预览
```bash
# 请将127.0.0.1替换为你的服务器ip
http://127.0.0.1:9003/
```
## 修改默认密码
- 修改 `docker-compose.yaml` 文件
```bash
BYTEDESK_ADMIN_EMAIL: admin@email.com
BYTEDESK_ADMIN_PASSWORD: admin
```
- 或登录之后在个人资料修改密码

View File

@@ -1,9 +0,0 @@
---
sidebar_label: 集群
sidebar_position: 8
---
# 集群
- 开源社区版支持单机部署
- 企业版支持集群部署

View File

@@ -1,6 +0,0 @@
---
sidebar_label: 客户端桌面
sidebar_position: 6
---
# 客户端桌面

View File

@@ -1,70 +0,0 @@
---
sidebar_label: Docker部署
sidebar_position: 3
---
# Docker部署
:::tip
- 操作系统Ubuntu 20.04 LTS
- 服务器最低配置2核4G内存推荐配置4核8G内存
:::
## 宝塔面板部署
- [宝塔面板部署](./baota)
## 一行命令启动
```bash
git clone https://gitee.com/270580156/weiyu.git && cd weiyu/deploy/docker && docker compose -p weiyu -f docker-compose.yaml up -d
```
### 因项目默认使用ollama qwen3:0.6b模型,所以需要提前拉取模型
```bash
ollama pull deepseek-r1:1.5b
ollama pull qwen3:0.6b
# 或docker拉取
# docker exec ollama pull qwen3:0.6b
```
### 停止容器
```bash
docker compose -p weiyu -f docker-compose.yaml stop
```
### 修改配置,否则上传图片、文件和知识库无法正常显示
- 修改 `docker-compose.yaml` 文件
```bash
# 请将服务器127.0.0.1替换为你的服务器ip
BYTEDESK_UPLOAD_URL: http://127.0.0.1:9003
BYTEDESK_KBASE_API_URL: http://127.0.0.1:9003
```
## 演示
本地预览
```bash
# 请将127.0.0.1替换为你的服务器ip
http://127.0.0.1:9003/
```
## 修改默认密码
- 修改 `docker-compose.yaml` 文件
```bash
BYTEDESK_ADMIN_EMAIL: admin@email.com
BYTEDESK_ADMIN_PASSWORD: admin
```
- 或登录之后在个人资料修改密码
- [线上预览](https://www.weiyuai.cn/admin/)

View File

@@ -1,123 +0,0 @@
---
sidebar_label: Jar包部署
sidebar_position: 1
---
# Jar 包部署
:::tip
- 操作系统Ubuntu 20.04 LTS
- 服务器最低配置 2 核 4G 内存,推荐配置 4 核 8G 内存。
:::
## 前期准备
### [Jdk17](./depend/jdk)
因项目依赖 spring boot 3, 最低要求 jdk17, 请确保已安装
```bash
java --version
# java 17.0.4 2022-07-19 LTS
```
### [Mysql 8.0](./depend/mysql)
默认使用 mysql
```bash
# 修改application.properties
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/bytedesk
spring.datasource.username=root
spring.datasource.password=密码
```
### 或 [PostgreSQL 16](./depend/postgresql)
mysql 或 postgresql 任选其一, 默认使用 mysql
```bash
# 修改application.properties
spring.datasource.url=jdbc:postgresql://127.0.0.1:5433/bytedesk
spring.datasource.username=postgres
spring.datasource.password=密码
```
### [Redis](./depend/redis)
```bash
spring.data.redis.database=0
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=密码
```
## [Nginx](./depend/nginx)
本地部署可不需要仅在生产环境推荐安装nginxnginx做反向代理
## [AI](./depend/ai)
可选仅用于知识库对话可跳过。如果仅仅是对话大模型则直接在配置文件里面填写智谱AI的key就行
```bash
下载地址: https://github.com/Bytedesk/bytedesk-ai
```
<!-- ### [Ollama](./depend/ollama)可选 -->
## 下载 [im server](https://www.weiyuai.cn/download/weiyu-server.zip)
```bash
# 更多下载: https://www.weiyuai.cn/download
# 解压
unzip weiyu-server.zip
```
## 配置
```bash
# 编辑配置文件server/config/application.properties
# 修改数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/bytedesk
spring.datasource.username=root
spring.datasource.password=password
# 修改redis连接信息
spring.data.redis.database=0
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=password
# 赋予权限
chmod +x start.sh
chmod +x stop.sh
# 启动
# 在Mac或Linux上运行
./start.sh
# 在Windows上运行
start.bat
# 停止
# 在Mac或Linux上运行
./stop.sh
# 在Windows上运行
stop.bat
# 启动之后,稍等片刻。查看端口号,如果有 9003端口则启动成功
netstat -ntlp
# 查看日志
tail -f logs/bytedeskim.log
```
## 本地预览
```bash
web: http://127.0.0.1:9003/
开发者入口: http://127.0.0.1:9003/dev
管理后台: http://127.0.0.1:9003/admin, 用户名: admin@email.com, 密码: admin
客服端: http://127.0.0.1:9003/agent/chat, 用户名: admin@email.com, 密码: admin
访客: http://127.0.0.1:9003/chat?org=df_org_uid&t=0&sid=df_ag_uid&
api文档: http://127.0.0.1:9003/swagger-ui/index.html
数据库监控: http://127.0.0.1:9003/druid用户名: admin@email.com, 密码: admin
actuator: http://127.0.0.1:9003/actuator
```

View File

@@ -1,107 +0,0 @@
---
sidebar_label: 源码部署
sidebar_position: 2
---
# 源码部署
:::tip
- 操作系统Ubuntu 20.04 LTS
- 服务器最低配置2核4G内存推荐配置4核8G内存
:::
## 前期准备
### [Jdk17](./depend/jdk)
因项目依赖spring boot 3, 最低要求 jdk17, 请确保已安装
```bash
java --version
# java 17.0.4 2022-07-19 LTS
```
### [MySQL 8](./depend/mysql)
```bash
# 修改application.properties
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/bytedesk
spring.datasource.username=root
spring.datasource.password=密码
```
### 或 [PostgreSQL 16](./depend/postgresql)
mysql或postgresql任选其一, 默认使用mysql
```bash
# 修改application.properties
spring.datasource.url=jdbc:postgresql://127.0.0.1:5433/bytedesk
spring.datasource.username=postgres
spring.datasource.password=密码
```
### [Redis](./depend/redis)
```bash
spring.data.redis.database=0
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=密码
```
<!-- ### [Ollama](./depend/ollama)可选 -->
## [下载源码](https://github.com/Bytedesk/bytedesk),并编译
```bash
# 注意: 此开源版本处于早期阶段,许多功能尚未完善或测试未完成,文档尚待完善,请勿在生产环境使用
git clone https://github.com/bytedesk/bytedesk.git
# 配置文件: bytedesk/starter/src/main/resources/application-dev.properties
# 推荐开发环境vscode + maven
#
# java --version
# java 17.0.4 2022-07-19 LTS
#
# mvn --version
# Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
# OS name: "mac os x", version: "14.2.1", arch: "aarch64", family: "mac"
#
# 项目使用了protobuf可能需要安装 protobuf 编译工具
# protoc --version
# libprotoc 25.3
#
cd bytedesk
mvn install -Dmaven.test.skip=true
#
cd starter
mvn spring-boot:run
```
## 本地预览
```bash
web: http://127.0.0.1:9003/
开发者入口: http://127.0.0.1:9003/dev
管理后台: http://127.0.0.1:9003/admin, 用户名: admin@email.com, 密码: admin
客户端: http://127.0.0.1:9003/agent/chat, 用户名: admin@email.com, 密码: admin
访客端: http://127.0.0.1:9003/chat?org=df_org_uid&t=0&sid=df_ag_uid&
api文档: http://127.0.0.1:9003/swagger-ui/index.html
数据库监控: http://127.0.0.1:9003/druid用户名: admin@email.com, 密码: admin
actuator: http://127.0.0.1:9003/actuator
```
## 修改默认密码
- 修改 `starter/src/main/resources/application-dev.properties` 文件
```bash
# admin email
bytedesk.admin.email=admin@email.com
# admin password
bytedesk.admin.password=admin
```
- 或登录之后在个人资料修改密码

View File

@@ -1,68 +0,0 @@
---
sidebar_label: 访客端
sidebar_position: 7
---
# 访客端
## [Nginx](./depend/nginx)
本地部署可不需要仅在生产环境推荐安装nginxnginx做反向代理
## 准备
- 将下载的 [server](https://www.weiyuai.cn/download/weiyu-server.zip) 文件解压,解压后的文件结构如下
```bash
(base) server % tree -L 1
.
├── admin
├── agent
├── bytedesk-starter-0.4.0.jar
├── chat
├── config
├── logs
├── readme.md
├── readme.zh.md
├── start.bat
├── start.sh
├── stop.bat
├── stop.sh
└── uploader
7 directories, 7 files
```
- 将其中的 adminagentchat 三个文件夹复制到 /var/www/html/weiyuai/ 文件夹下。
- 其中admin 为管理后台agent 为客户端chat 为访客端
- 三者默认访问的服务器地址为: http://127.0.0.1:9003, 发布到线上时需要修改才能够正常使用,具体修改方法如下:
- 找到 admin/config.json 、 agent/config.json 和 chat/config.json 三个文件
- config.json 文件内容如下:
```json
{
"enabled": true,
"apiUrl": "https://api.weiyuai.cn",
"websocketUrl": "wss://api.weiyuai.cn/websocket",
"htmlUrl": "https://www.weiyuai.cn"
}
```
- enabled 字段为是否启用自定义服务器地址,默认为 false。这里需要将 false 改为 true。只有修改为 true下面的 apiHost 和 htmlHost 才能生效
- apiUrl 字段为 api 地址默认为api.weiyuai.cn请替换为自己的域名
- websocketUrl 字段为 websocket 地址默认为ws://api.weiyuai.cn/websocket请替换为自己的域名
- htmlHost 字段为静态网页地址默认为www.weiyuai.cn请替换为自己的域名
## 替换为ip实例
- 将域名替换为ip
- 将https替换为http
```json
{
"enabled": true,
"apiUrl": "http://127.0.0.1:9003",
"websocketUrl": "ws://127.0.0.1:9885/websocket",
"htmlUrl": "http://127.0.0.1:9006"
}
```

View File

@@ -1,85 +0,0 @@
---
sidebar_position: 1
---
# 介绍
:::tip
微语仍处于早期的快速迭代阶段,文档可能落后于开发,导致功能描述可能不符,以最新发布的软件版本为准
:::
## 微语是什么?
- 一款开源聊天软件
- 支持企业IM、在线客服、知识库、工单系统、AI Agent等
- 致力于实现企业管理软件一站式解决方案
## 具有哪些功能?
### 1. 企业IM
- 多层组织架构
- 角色管理
- 权限管理
- 聊天记录管理
- 同事对话
- 群组管理
### 2. 智能客服
- 人工客服
- AI智能客服基于大模型LLM && RAG
- 支持多渠道:
- [平台渠道](category/平台渠道)
- [Web/H5](develop/visitor/platform/web)
- [React](develop/visitor/platform/react)
- [Android](develop/visitor/platform/android)
- [iOS](develop/visitor/platform/ios)
- [Uniapp](develop/visitor/platform/uniapp)
- [Flutter](develop/visitor/platform/flutter)
- [社交渠道](category/社交渠道)
- 微信公众号
- 小程序
- 企业微信
- 小红书
- 抖音
- 快手
- 百度
- 微博
- 知乎
- [电商渠道](category/电商渠道)
- 淘宝
- 天猫
- 京东
- 千牛
- 抖店
- [海外渠道](category/海外渠道)
- Facebook
- Instagram
- Whatsapp
- Line
- 多种路由策略、
- 详细考核指标
- 坐席工作台、
- 工单系统、
- 坐席管理、
- 数据看板、
- 人工知识库、
- 技能组管理、
- 实时监控、
- 公告、
- 敏感词、
- CRM、
- 报表功能,
### 3. AI Agent
- 更适合团队使用,一人配置,多人使用
### 4. 知识库
基于大模型 LLM && RAG 的知识库问答
### 5. 帮助中心
### 6. 工单系统

View File

@@ -1,71 +0,0 @@
---
sidebar_label: "费用相关"
---
# 费用相关
## 功能对比
### 企业IM
| 功能 | 开源 | 企业版 |
| --------- | ----- | ------ |
| Header | Title | Title |
| Paragraph | Text | Text |
### AI Agent
| 功能 | 开源 | 企业版 |
| --------- | ----- | ------ |
| Header | Title | Title |
| Paragraph | Text | Text |
### 智能客服
| 功能 | 开源 | 企业版 |
| --------- | ----- | ------ |
| Header | Title | Title |
| Paragraph | Text | Text |
### 知识库
| 功能 | 开源 | 企业版 |
| --------- | ----- | ------ |
| Header | Title | Title |
| Paragraph | Text | Text |
### 帮助中心
| 功能 | 开源 | 企业版 |
| --------- | ----- | ------ |
| Header | Title | Title |
| Paragraph | Text | Text |
### 工单系统
| 功能 | 开源 | 企业版 |
| --------- | ----- | ------ |
| Header | Title | Title |
| Paragraph | Text | Text |
## 收费标准
<!-- - 保留logo的前提下可以免费安装使用不收取任何费用。授权修改微语及 Logo 1w -->
- 开源社区版,支持完全免费商用,无任何限制
<!-- - 服务器基本功能开源免费, [码云](https://gitee.com/270580156/weiyu.im),[github](https://github.com/Bytedesk/bytedesk) -->
<!-- - 服务器高级功能(技术栈 java+spring-boot3+jdk17数据统计、敏感词、会话转接、自动回复、满意度、质检等源码价格5w -->
<!-- - Web管理后台技术栈react+typescript+antd 源码价格5w -->
<!-- - 聊天Web/桌面客户端技术栈electron+react+typescript+antd支持[web](https://www.weiyuai.cn/agent)/[windows](https://www.weiyuai.cn/download/weiyu-windows.exe)/[macOS](https://www.weiyuai.cn/download/weiyu-mac.dmg)/[linux](https://www.weiyuai.cn/download/weiyu-linux.AppImage) 源码价格5w -->
<!-- - 手机客户端技术栈flutter支持[android](https://www.weiyuai.cn/download/weiyu-android.apk)/[ios](https://apps.apple.com/cn/app/%E5%BE%AE%E8%AF%AD/id6470106586) 源码价格5w -->
<!-- - Web访客端技术栈react+typescript 源码价格2w -->
- 如有定制需求,请[联系微信](/img/wechat.png),发送您的需求,评估开发周期/定价
## 其他
<!-- - 在保留原有商标 logo 等信息前提下,支持免费商用。如需移除,需要获得授权 -->
<!-- - 仅支持企业内部员工自用,销售、二次销售或者部署 SaaS 方式销售需要获得授权 -->
<!-- - 代理合作:您负责销售,我方负责售后,维护等,五五分成 -->
<!-- - 此软件可能存在 bug 或不完善的地方,如造成损失,需自行负责 -->
- 严禁用于含有木马、病毒、色情、赌博、诈骗等违法违规业务
<!-- - <img src="/img/wechat.png" width="150"></img> -->
<!-- - 定制按 2500 人/天 计算 -->

View File

@@ -1 +0,0 @@
Tell me a {adjective} joke about {topic}

View File

@@ -1,7 +0,0 @@
Use the following pieces of context to answer the question at the end.
If you don't know the answer, just say that you don't know, don't try to make up an answer.
{context}
Question: {question}
Helpful Answer:

View File

@@ -1,4 +0,0 @@
You are a helpful AI assistant.
You are an AI assistant that helps people find information.
Your name is {name}
You should reply to the user's request with your name and also in the style of a {voice}.

View File

@@ -1,7 +0,0 @@
You're assisting with questions about products in a bicycle catalog.
Use the information from the DOCUMENTS section to provide accurate answers.
If the answer involves referring to the price or the dimension of the bicycle, include the bicycle name in the response.
If unsure, simply state that you don't know.
DOCUMENTS:
{documents}

File diff suppressed because one or more lines are too long

View File

@@ -1,752 +0,0 @@
The [curling](Curling_at_the_Winter_Olympics "wikilink") competitions of
the [2022 Winter Olympics](2022_Winter_Olympics "wikilink") were held at
the [Beijing National Aquatics
Centre](Beijing_National_Aquatics_Centre "wikilink"), one of the
[Olympic Green](Olympic_Green "wikilink") venues. Curling competitions
were scheduled for every day of the games, from February 2 to February
20.\[1\] This was the eighth time that [curling](curling "wikilink") was
part of the Olympic program.
In each of the men's, women's, and [mixed
doubles](mixed_doubles_curling "wikilink") competitions, 10 nations
competed. The mixed doubles competition was expanded for its second
appearance in the Olympics.\[2\] A total of 120 quota spots (60 per sex)
were distributed to the sport of curling, an increase of four from the
[2018 Winter Olympics](2018_Winter_Olympics "wikilink").\[3\] A total of
3 events were contested, one for men, one for women, and one mixed.\[4\]
## Qualification
Qualification to the Men's and Women's curling tournaments at the Winter
Olympics was determined through two methods (in addition to the host
nation). Nations qualified teams by placing in the top six at the 2021
[World Curling Championships](World_Curling_Championships "wikilink").
Teams could also qualify through Olympic qualification events which were
held in 2021. Six nations qualified via World Championship qualification
placement, while three nations qualified through qualification events.
In men's and women's play, a host will be selected for the Olympic
Qualification Event (OQE). They would be joined by the teams which
competed at the 2021 World Championships but did not qualify for the
Olympics, and two qualifiers from the Pre-Olympic Qualification Event
(Pre-OQE). The Pre-OQE was open to all member associations.\[5\]
For the mixed doubles competition in 2022, the tournament field was
expanded from eight competitor nations to ten.\[6\] The top seven ranked
teams at the [2021 World Mixed Doubles Curling
Championship](2021_World_Mixed_Doubles_Curling_Championship "wikilink")
qualified, along with two teams from the Olympic Qualification Event
(OQE) Mixed Doubles. This OQE was open to a nominated host and the
fifteen nations with the highest qualification points not already
qualified to the Olympics. As the host nation, China qualified teams
automatically, thus making a total of ten teams per event in the curling
tournaments.\[7\]
- Summary
<table>
<thead>
<tr class="header">
<th><p>Nations</p></th>
<th><p><a href="#Men" title="wikilink">Men</a></p></th>
<th><p><a href="#Women" title="wikilink">Women</a></p></th>
<th><p><a href="#Mixed_doubles" title="wikilink">Mixed doubles</a></p></th>
<th><p>Athletes</p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>2</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>12</strong></p></td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>12</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>2</strong></p></td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>10</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>10</strong></p></td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>6</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>5</strong></p></td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>6</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>10</strong></p></td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>5</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>11</strong></p></td>
</tr>
<tr class="odd">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>12</strong></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td><p><strong>11</strong></p></td>
</tr>
<tr class="odd">
<td><p>Total: 14 NOCs</p></td>
<td><p>10</p></td>
<td><p>10</p></td>
<td><p>10</p></td>
<td><p>114</p></td>
</tr>
</tbody>
</table>
## Competition schedule
![The [Beijing National Aquatics
Centre](Beijing_National_Aquatics_Centre "wikilink") served as the venue
of the curling competitions.](Water_Cube_Ice_Cube_Beijing_2.jpg
"The Beijing National Aquatics Centre served as the venue of the curling competitions.")
Curling competitions started two days before the [Opening
Ceremony](2022_Winter_Olympics_opening_ceremony "wikilink") and finished
on the last day of the games, meaning the sport was the only one to have
had a competition every day of the games. The following was the
competition schedule for the curling competitions:
| | | | | | | | |
| :-: | ----------- | :-: | ---------- | :-: | ------------------ | :-: | ----- |
| RR | Round robin | SF | Semifinals | B | 3rd place play-off | F | Final |
<table>
<thead>
<tr class="header">
<th></th>
<th><p>Wed 2</p></th>
<th><p>Thu 3</p></th>
<th><p>Fri 4</p></th>
<th><p>Sat 5</p></th>
<th><p>Sun 6</p></th>
<th><p>Mon 7</p></th>
<th><p>Tue 8</p></th>
<th><p>Wed 9</p></th>
<th><p>Thu 10</p></th>
<th><p>Fri 11</p></th>
<th><p>Sat 12</p></th>
<th><p>Sun 13</p></th>
<th><p>Mon 14</p></th>
<th><p>Tue 15</p></th>
<th><p>Wed 16</p></th>
<th><p>Thu 17</p></th>
<th><p>Fri 18</p></th>
<th><p>Sat 19</p></th>
<th><p>Sun 20</p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p><a href="Curling_at_the_2022_Winter_Olympics__Men&#39;s_tournament" title="wikilink">Men's tournament</a></p></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>SF</p></td>
<td><p>B</p></td>
<td><p>F</p></td>
</tr>
<tr class="even">
<td><p><a href="Curling_at_the_2022_Winter_Olympics__Women&#39;s_tournament" title="wikilink">Women's tournament</a></p></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>SF</p></td>
<td><p>B</p></td>
<td><p>F</p></td>
</tr>
<tr class="odd">
<td><p><a href="Curling_at_the_2022_Winter_Olympics__Mixed_doubles_tournament" title="wikilink">Mixed doubles</a></p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>RR</p></td>
<td><p>SF</p></td>
<td><p>B</p></td>
<td><p>F</p></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
## Medal summary
### Medal table
### Medalists
|- |Men
|
[Niklas Edin](Niklas_Edin "wikilink")
[Oskar Eriksson](Oskar_Eriksson "wikilink")
[Rasmus Wranå](Rasmus_Wranå "wikilink")
[Christoffer Sundgren](Christoffer_Sundgren "wikilink")
[Daniel Magnusson](Daniel_Magnusson_\(curler\) "wikilink") |
[Bruce Mouat](Bruce_Mouat "wikilink")
[Grant Hardie](Grant_Hardie "wikilink")
[Bobby Lammie](Bobby_Lammie "wikilink")
[Hammy McMillan Jr.](Hammy_McMillan_Jr. "wikilink")
[Ross Whyte](Ross_Whyte "wikilink") |
[Brad Gushue](Brad_Gushue "wikilink")
[Mark Nichols](Mark_Nichols_\(curler\) "wikilink")
[Brett Gallant](Brett_Gallant "wikilink")
[Geoff Walker](Geoff_Walker_\(curler\) "wikilink")
[Marc Kennedy](Marc_Kennedy "wikilink") |- |Women
|
[Eve Muirhead](Eve_Muirhead "wikilink")
[Vicky Wright](Vicky_Wright "wikilink")
[Jennifer Dodds](Jennifer_Dodds "wikilink")
[Hailey Duff](Hailey_Duff "wikilink")
[Mili Smith](Mili_Smith "wikilink") |
[Satsuki Fujisawa](Satsuki_Fujisawa "wikilink")
[Chinami Yoshida](Chinami_Yoshida "wikilink")
[Yumi Suzuki](Yumi_Suzuki "wikilink")
[Yurika Yoshida](Yurika_Yoshida "wikilink")
[Kotomi Ishizaki](Kotomi_Ishizaki "wikilink") |
[Anna Hasselborg](Anna_Hasselborg "wikilink")
[Sara McManus](Sara_McManus "wikilink")
[Agnes Knochenhauer](Agnes_Knochenhauer "wikilink")
[Sofia Mabergs](Sofia_Mabergs "wikilink")
[Johanna Heldin](Johanna_Heldin "wikilink") |- |Mixed doubles
|
[Stefania Constantini](Stefania_Constantini "wikilink")
[Amos Mosaner](Amos_Mosaner "wikilink") |
[Kristin Skaslien](Kristin_Skaslien "wikilink")
[Magnus Nedregotten](Magnus_Nedregotten "wikilink") |
[Almida de Val](Almida_de_Val "wikilink")
[Oskar Eriksson](Oskar_Eriksson "wikilink") |}
## Teams
### Men
<table>
<thead>
<tr class="header">
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p><strong>Skip:</strong> <a href="Brad_Gushue" title="wikilink">Brad Gushue</a><br />
<strong>Third:</strong> <a href="Mark_Nichols_(curler)" title="wikilink">Mark Nichols</a><br />
<strong>Second:</strong> <a href="Brett_Gallant" title="wikilink">Brett Gallant</a><br />
<strong>Lead:</strong> <a href="Geoff_Walker_(curler)" title="wikilink">Geoff Walker</a><br />
<strong>Alternate:</strong> <em><a href="Marc_Kennedy" title="wikilink">Marc Kennedy</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Ma_Xiuyue" title="wikilink">Ma Xiuyue</a><br />
<strong>Third:</strong> <a href="Zou_Qiang" title="wikilink">Zou Qiang</a><br />
<strong>Second:</strong> <a href="Wang_Zhiyu" title="wikilink">Wang Zhiyu</a><br />
<strong>Lead:</strong> <a href="Xu_Jingtao" title="wikilink">Xu Jingtao</a><br />
<strong>Alternate:</strong> <em><a href="Jiang_Dongxu" title="wikilink">Jiang Dongxu</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Mikkel_Krause" title="wikilink">Mikkel Krause</a><br />
<strong>Third:</strong> <a href="Mads_Nørgård" title="wikilink">Mads Nørgård</a><br />
<strong>Second:</strong> <a href="Henrik_Holtermann" title="wikilink">Henrik Holtermann</a><br />
<strong>Lead:</strong> <a href="Kasper_Wiksten" title="wikilink">Kasper Wiksten</a><br />
<strong>Alternate:</strong> <em><a href="Tobias_Thune" title="wikilink">Tobias Thune</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Bruce_Mouat" title="wikilink">Bruce Mouat</a><br />
<strong>Third:</strong> <a href="Grant_Hardie" title="wikilink">Grant Hardie</a><br />
<strong>Second:</strong> <a href="Bobby_Lammie" title="wikilink">Bobby Lammie</a><br />
<strong>Lead:</strong> <a href="Hammy_McMillan_Jr." title="wikilink">Hammy McMillan Jr.</a><br />
<strong>Alternate:</strong> <em><a href="Ross_Whyte" title="wikilink">Ross Whyte</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Joël_Retornaz" title="wikilink">Joël Retornaz</a><br />
<strong>Third:</strong> <a href="Amos_Mosaner" title="wikilink">Amos Mosaner</a><br />
<strong>Second:</strong> <a href="Sebastiano_Arman" title="wikilink">Sebastiano Arman</a><br />
<strong>Lead:</strong> <a href="Simone_Gonin" title="wikilink">Simone Gonin</a><br />
<strong>Alternate:</strong> <em><a href="Mattia_Giovanella" title="wikilink">Mattia Giovanella</a></em></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td><p><strong>Skip:</strong> <a href="Steffen_Walstad" title="wikilink">Steffen Walstad</a><br />
<strong>Third:</strong> <a href="Torger_Nergård" title="wikilink">Torger Nergård</a><br />
<strong>Second:</strong> <a href="Markus_Høiberg" title="wikilink">Markus Høiberg</a><br />
<strong>Lead:</strong> <a href="Magnus_Vågberg" title="wikilink">Magnus Vågberg</a><br />
<strong>Alternate:</strong> <em><a href="Magnus_Nedregotten" title="wikilink">Magnus Nedregotten</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Sergey_Glukhov" title="wikilink">Sergey Glukhov</a><br />
<strong>Third:</strong> <a href="Evgeny_Klimov_(curler)" title="wikilink">Evgeny Klimov</a><br />
<strong>Second:</strong> <a href="Dmitry_Mironov" title="wikilink">Dmitry Mironov</a><br />
<strong>Lead:</strong> <a href="Anton_Kalalb" title="wikilink">Anton Kalalb</a><br />
<strong>Alternate:</strong> <em><a href="Daniil_Goriachev" title="wikilink">Daniil Goriachev</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Niklas_Edin" title="wikilink">Niklas Edin</a><br />
<strong>Third:</strong> <a href="Oskar_Eriksson" title="wikilink">Oskar Eriksson</a><br />
<strong>Second:</strong> <a href="Rasmus_Wranå" title="wikilink">Rasmus Wranå</a><br />
<strong>Lead:</strong> <a href="Christoffer_Sundgren" title="wikilink">Christoffer Sundgren</a><br />
<strong>Alternate:</strong> <em></em></p></td>
<td><p><strong>Fourth:</strong> <a href="Benoît_Schwarz" title="wikilink">Benoît Schwarz</a><br />
<strong>Third:</strong> <a href="Sven_Michel_(curler)" title="wikilink">Sven Michel</a><br />
<strong>Skip:</strong> <a href="Peter_de_Cruz" title="wikilink">Peter de Cruz</a><br />
<strong>Lead:</strong> <a href="Valentin_Tanner" title="wikilink">Valentin Tanner</a><br />
<strong>Alternate:</strong> <em><a href="Pablo_Lachat" title="wikilink">Pablo Lachat</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="John_Shuster" title="wikilink">John Shuster</a><br />
<strong>Third:</strong> <a href="Chris_Plys" title="wikilink">Chris Plys</a><br />
<strong>Second:</strong> <a href="Matt_Hamilton_(curler)" title="wikilink">Matt Hamilton</a><br />
<strong>Lead:</strong> <a href="John_Landsteiner" title="wikilink">John Landsteiner</a><br />
<strong>Alternate:</strong> <em><a href="Colin_Hufman" title="wikilink">Colin Hufman</a></em></p></td>
</tr>
</tbody>
</table>
### Women
<table>
<thead>
<tr class="header">
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p><strong>Skip:</strong> <a href="Jennifer_Jones_(curler)" title="wikilink">Jennifer Jones</a><br />
<strong>Third:</strong> <a href="Kaitlyn_Lawes" title="wikilink">Kaitlyn Lawes</a><br />
<strong>Second:</strong> <a href="Jocelyn_Peterman" title="wikilink">Jocelyn Peterman</a><br />
<strong>Lead:</strong> <a href="Dawn_McEwen" title="wikilink">Dawn McEwen</a><br />
<strong>Alternate:</strong> <em><a href="Lisa_Weagle" title="wikilink">Lisa Weagle</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Han_Yu_(curler)" title="wikilink">Han Yu</a><br />
<strong>Third:</strong> <a href="Wang_Rui_(curler)" title="wikilink">Wang Rui</a><br />
<strong>Second:</strong> <a href="Dong_Ziqi" title="wikilink">Dong Ziqi</a><br />
<strong>Lead:</strong> <a href="Zhang_Lijun_(curler)" title="wikilink">Zhang Lijun</a><br />
<strong>Alternate:</strong> <em><a href="Jiang_Xindi" title="wikilink">Jiang Xindi</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Madeleine_Dupont" title="wikilink">Madeleine Dupont</a><br />
<strong>Third:</strong> <a href="Mathilde_Halse" title="wikilink">Mathilde Halse</a><br />
<strong>Second:</strong> <a href="Denise_Dupont" title="wikilink">Denise Dupont</a><br />
<strong>Lead:</strong> <a href="My_Larsen" title="wikilink">My Larsen</a><br />
<strong>Alternate:</strong> <em><a href="Jasmin_Lander" title="wikilink">Jasmin Lander</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Eve_Muirhead" title="wikilink">Eve Muirhead</a><br />
<strong>Third:</strong> <a href="Vicky_Wright" title="wikilink">Vicky Wright</a><br />
<strong>Second:</strong> <a href="Jennifer_Dodds" title="wikilink">Jennifer Dodds</a><br />
<strong>Lead:</strong> <a href="Hailey_Duff" title="wikilink">Hailey Duff</a><br />
<strong>Alternate:</strong> <em><a href="Mili_Smith" title="wikilink">Mili Smith</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Satsuki_Fujisawa" title="wikilink">Satsuki Fujisawa</a><br />
<strong>Third:</strong> <a href="Chinami_Yoshida" title="wikilink">Chinami Yoshida</a><br />
<strong>Second:</strong> <a href="Yumi_Suzuki" title="wikilink">Yumi Suzuki</a><br />
<strong>Lead:</strong> <a href="Yurika_Yoshida" title="wikilink">Yurika Yoshida</a><br />
<strong>Alternate:</strong> <em><a href="Kotomi_Ishizaki" title="wikilink">Kotomi Ishizaki</a></em></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td><p><strong>Skip:</strong> <a href="Alina_Kovaleva" title="wikilink">Alina Kovaleva</a><br />
<strong>Third:</strong> <a href="Yulia_Portunova" title="wikilink">Yulia Portunova</a><br />
<strong>Second:</strong> <a href="Galina_Arsenkina" title="wikilink">Galina Arsenkina</a><br />
<strong>Lead:</strong> <a href="Ekaterina_Kuzmina" title="wikilink">Ekaterina Kuzmina</a><br />
<strong>Alternate:</strong> <em><a href="Maria_Komarova" title="wikilink">Maria Komarova</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Kim_Eun-jung_(curler)" title="wikilink">Kim Eun-jung</a><br />
<strong>Third:</strong> <a href="Kim_Kyeong-ae_(curler)" title="wikilink">Kim Kyeong-ae</a><br />
<strong>Second:</strong> <a href="Kim_Cho-hi" title="wikilink">Kim Cho-hi</a><br />
<strong>Lead:</strong> <a href="Kim_Seon-yeong_(curler)" title="wikilink">Kim Seon-yeong</a><br />
<strong>Alternate:</strong> <em><a href="Kim_Yeong-mi" title="wikilink">Kim Yeong-mi</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Anna_Hasselborg" title="wikilink">Anna Hasselborg</a><br />
<strong>Third:</strong> <a href="Sara_McManus" title="wikilink">Sara McManus</a><br />
<strong>Second:</strong> <a href="Agnes_Knochenhauer" title="wikilink">Agnes Knochenhauer</a><br />
<strong>Lead:</strong> <a href="Sofia_Mabergs" title="wikilink">Sofia Mabergs</a><br />
<strong>Alternate:</strong> <em><a href="Johanna_Heldin" title="wikilink">Johanna Heldin</a></em></p></td>
<td><p><strong>Fourth:</strong> <a href="Alina_Pätz" title="wikilink">Alina Pätz</a><br />
<strong>Skip:</strong> <a href="Silvana_Tirinzoni" title="wikilink">Silvana Tirinzoni</a><br />
<strong>Second:</strong> <a href="Esther_Neuenschwander" title="wikilink">Esther Neuenschwander</a><br />
<strong>Lead:</strong> <a href="Melanie_Barbezat" title="wikilink">Melanie Barbezat</a><br />
<strong>Alternate:</strong> <em><a href="Carole_Howald" title="wikilink">Carole Howald</a></em></p></td>
<td><p><strong>Skip:</strong> <a href="Tabitha_Peterson" title="wikilink">Tabitha Peterson</a><br />
<strong>Third:</strong> <a href="Nina_Roth" title="wikilink">Nina Roth</a><br />
<strong>Second:</strong> <a href="Becca_Hamilton" title="wikilink">Becca Hamilton</a><br />
<strong>Lead:</strong> <a href="Tara_Peterson" title="wikilink">Tara Peterson</a><br />
<strong>Alternate:</strong> <em><a href="Aileen_Geving" title="wikilink">Aileen Geving</a></em></p></td>
</tr>
</tbody>
</table>
### Mixed doubles
<table>
<thead>
<tr class="header">
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p><strong>Female:</strong> <a href="Tahli_Gill" title="wikilink">Tahli Gill</a><br />
<strong>Male:</strong> <a href="Dean_Hewitt" title="wikilink">Dean Hewitt</a></p></td>
<td><p><strong>Female:</strong> <a href="Rachel_Homan" title="wikilink">Rachel Homan</a><br />
<strong>Male:</strong> <a href="John_Morris_(curler)" title="wikilink">John Morris</a></p></td>
<td><p><strong>Female:</strong> <a href="Fan_Suyuan" title="wikilink">Fan Suyuan</a><br />
<strong>Male:</strong> <a href="Ling_Zhi" title="wikilink">Ling Zhi</a></p></td>
<td><p><strong>Female:</strong> <a href="Zuzana_Paulová" title="wikilink">Zuzana Paulová</a><br />
<strong>Male:</strong> <a href="Tomáš_Paul" title="wikilink">Tomáš Paul</a></p></td>
<td><p><strong>Female:</strong> <a href="Jennifer_Dodds" title="wikilink">Jennifer Dodds</a><br />
<strong>Male:</strong> <a href="Bruce_Mouat" title="wikilink">Bruce Mouat</a></p></td>
</tr>
<tr class="even">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td><p><strong>Female:</strong> <a href="Stefania_Constantini" title="wikilink">Stefania Constantini</a><br />
<strong>Male:</strong> <a href="Amos_Mosaner" title="wikilink">Amos Mosaner</a></p></td>
<td><p><strong>Female:</strong> <a href="Kristin_Skaslien" title="wikilink">Kristin Skaslien</a><br />
<strong>Male:</strong> <a href="Magnus_Nedregotten" title="wikilink">Magnus Nedregotten</a></p></td>
<td><p><strong>Female:</strong> <a href="Almida_de_Val" title="wikilink">Almida de Val</a><br />
<strong>Male:</strong> <a href="Oskar_Eriksson" title="wikilink">Oskar Eriksson</a></p></td>
<td><p><strong>Female:</strong> <a href="Jenny_Perret" title="wikilink">Jenny Perret</a><br />
<strong>Male:</strong> <a href="Martin_Rios" title="wikilink">Martin Rios</a></p></td>
<td><p><strong>Female:</strong> <a href="Vicky_Persinger" title="wikilink">Vicky Persinger</a><br />
<strong>Male:</strong> <a href="Chris_Plys" title="wikilink">Chris Plys</a></p></td>
</tr>
</tbody>
</table>
## Results summary
### Men's tournament
#### Round robin
- Standings
{{\#lst:Curling at the 2022 Winter Olympics Men's
tournament|Standings}}
- Results
{{\#lst:Curling at the 2022 Winter Olympics Men's tournament|Results}}
#### Playoffs
##### Semifinals
*Thursday, 17 February, 20:05* {{\#lst:Curling at the 2022 Winter
Olympics Men's tournament|SF1}} {{\#lst:Curling at the 2022 Winter
Olympics Men's tournament|SF2}}
##### Bronze medal game
*Friday, 18 February, 14:05* {{\#lst:Curling at the 2022 Winter Olympics
Men's tournament|BM}}
##### Gold medal game
*Saturday, 19 February, 14:50*\[8\] {{\#lst:Curling at the 2022 Winter
Olympics Men's tournament|GM}}
### Women's tournament
#### Round robin
- Standings
{{\#lst:Curling at the 2022 Winter Olympics Women's
tournament|Standings}}
- Results
{{\#lst:Curling at the 2022 Winter Olympics Women's
tournament|Results}}
#### Playoffs
##### Semifinals
*Friday, 18 February, 20:05* {{\#lst:Curling at the 2022 Winter Olympics
Women's tournament|SF1}} {{\#lst:Curling at the 2022 Winter Olympics
Women's tournament|SF2}}
##### Bronze medal game
*Saturday, 19 February, 20:05* {{\#lst:Curling at the 2022 Winter
Olympics Women's tournament|BM}}
##### Gold medal game
*Sunday, 20 February, 9:05* {{\#lst:Curling at the 2022 Winter Olympics
Women's tournament|GM}}
### Mixed doubles tournament
#### Round robin
- Standings
{{\#lst:Curling at the 2022 Winter Olympics Mixed doubles
tournament|Standings}}
- Results
{{\#lst:Curling at the 2022 Winter Olympics Mixed doubles
tournament|Results}}
#### Playoffs
##### Semifinals
*Monday, 7 February, 20:05* {{\#lst:Curling at the 2022 Winter Olympics
Mixed doubles tournament|SF1}}
<table>
<thead>
<tr class="header">
<th><p>Player percentages</p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td></td>
</tr>
<tr class="even">
<td><p><a href="Stefania_Constantini" title="wikilink">Stefania Constantini</a></p></td>
</tr>
<tr class="odd">
<td><p><a href="Amos_Mosaner" title="wikilink">Amos Mosaner</a></p></td>
</tr>
<tr class="even">
<td><p><strong>Total</strong></p></td>
</tr>
</tbody>
</table>
{{\#lst:Curling at the 2022 Winter Olympics Mixed doubles
tournament|SF2}}
<table>
<thead>
<tr class="header">
<th><p>Player percentages</p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td></td>
</tr>
<tr class="even">
<td><p><a href="Kristin_Skaslien" title="wikilink">Kristin Skaslien</a></p></td>
</tr>
<tr class="odd">
<td><p><a href="Magnus_Nedregotten" title="wikilink">Magnus Nedregotten</a></p></td>
</tr>
<tr class="even">
<td><p><strong>Total</strong></p></td>
</tr>
</tbody>
</table>
##### Bronze medal game
*Tuesday, 8 February, 14:05* {{\#lst:Curling at the 2022 Winter Olympics
Mixed doubles tournament|BM}}
<table>
<thead>
<tr class="header">
<th><p>Player percentages</p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td></td>
</tr>
<tr class="even">
<td><p><a href="Almida_de_Val" title="wikilink">Almida de Val</a></p></td>
</tr>
<tr class="odd">
<td><p><a href="Oskar_Eriksson" title="wikilink">Oskar Eriksson</a></p></td>
</tr>
<tr class="even">
<td><p><strong>Total</strong></p></td>
</tr>
</tbody>
</table>
##### Gold medal game
*Tuesday, 8 February, 20:05* {{\#lst:Curling at the 2022 Winter Olympics
Mixed doubles tournament|GM}}
<table>
<thead>
<tr class="header">
<th><p>Player percentages</p></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td></td>
</tr>
<tr class="even">
<td><p><a href="Stefania_Constantini" title="wikilink">Stefania Constantini</a></p></td>
</tr>
<tr class="odd">
<td><p><a href="Amos_Mosaner" title="wikilink">Amos Mosaner</a></p></td>
</tr>
<tr class="even">
<td><p><strong>Total</strong></p></td>
</tr>
</tbody>
</table>
## Participating nations
A total of 114 athletes from 14 nations (including the IOC's designation
of ROC) were scheduled to participate (the numbers of athletes are shown
in parentheses). Some curlers competed in both the 4-person and mixed
doubles tournament, therefore, the numbers included on this list are the
total athletes sent by each NOC to the Olympics, not how many athletes
they qualified. Both Australia and the Czech Republic made their Olympic
sport debuts.\[9\]
## References
## External links
- [Official Results Book
Curling](https://library.olympics.com/default/digitalCollection/DigitalCollectionAttachmentDownloadHandler.ashx?parentDocumentId=1568639&documentId=1568653)
[ ](Category:Curling_at_the_2022_Winter_Olympics "wikilink")
[Category:2022 Winter Olympics
events](Category:2022_Winter_Olympics_events "wikilink") [Winter
Olympics](Category:2022_in_curling "wikilink") [2022 Winter
Olympics](Category:International_curling_competitions_hosted_by_China "wikilink")
1.
2.
3.
4.
5. [Rule changes
outlined](https://s3-eu-west-1.amazonaws.com/media.worldcurling.org/media.worldcurling.org/wcf_worldcurling/2019/09/06193637/Resolutions-put-to-the-Annual-General-Assembly-2019.pdf)
6.
7.
8.
9.

View File

@@ -1,4 +0,0 @@
# 商品导购助手
- 商品推荐
- 订单退货

View File

@@ -1,12 +0,0 @@
spring.application.name=ai
# 启用Actuator端点
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoints.enabled-by-default=true
# 启用Spring AI的观察功能
spring.ai.observation.enabled=true
spring.ai.retry.observation.enabled=true
# Prometheus相关配置可选
management.metrics.export.prometheus.enabled=true

View File

@@ -1,21 +0,0 @@
spring:
ai:
dashscope:
chat:
enabled: true # 控制是否启用阿里云百炼相关功能
vectorstore:
weaviate:
enabled: false # 禁用 Weaviate
redis:
enabled: true # 启用 Redis
default-model: bge-m3:latest
zhipuai:
chat:
enabled: true # 控制是否启用智谱AI相关功能
# 其他配置...
# AI提供商配置
bytedesk:
ai:
provider: volcengine # 可选: baidu, deepseek, gitee, siliconFlow, tencent, volcengine

View File

@@ -1,182 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AI智能助手 - 微语</title>
<meta name="description" content="微语AI智能助手提供多模型智能对话及自动化服务">
<link href="/assets/vendor/bootstrap5/css/bootstrap.min.css" rel="stylesheet">
<style>
.feature-icon {
font-size: 2.5rem;
color: #0d6efd;
margin-bottom: 1rem;
}
.feature-box {
padding: 2rem;
border-radius: 10px;
background: #f8f9fa;
transition: all 0.3s ease;
}
.feature-box:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="#">微语AI Agent</a>
</div>
</nav>
<div class="container my-5">
<div class="row text-center mb-5">
<div class="col">
<h1 class="display-4 mb-3">智能AI Agent系统</h1>
<p class="lead">整合多种大语言模型提供智能对话、自动化工作流、知识库管理等全方位AI解决方案</p>
<div class="mt-4">
<a href="/contact" class="btn btn-primary btn-lg me-3">免费试用</a>
<a href="/docs/zh-CN" class="btn btn-outline-primary btn-lg">查看文档</a>
</div>
</div>
</div>
<!-- AI 核心优势 -->
<div class="row mb-5">
<div class="col-12 text-center mb-4">
<h2>AI 驱动的智能服务</h2>
<p class="lead text-muted">结合大语言模型,打造智能化服务体验</p>
</div>
<div class="col-md-4">
<div class="feature-box h-100">
<div class="feature-icon">🤖</div>
<h3>多模型协同</h3>
<p>整合OpenAI、智谱AI、文心一言等主流大语言模型实现多模型协同提供最优解决方案。</p>
<ul class="list-unstyled">
<li><i class="bi bi-check-circle"></i> 模型智能调度</li>
<li><i class="bi bi-check-circle"></i> 成本最优选择</li>
<li><i class="bi bi-check-circle"></i> 性能实时监控</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="feature-box h-100">
<div class="feature-icon">📊</div>
<h3>智能数据分析</h3>
<p>AI驱动的数据分析系统自动识别用户意图生成服务洞察助力企业优化服务流程。</p>
<ul class="list-unstyled">
<li><i class="bi bi-check-circle"></i> 实时情感分析</li>
<li><i class="bi bi-check-circle"></i> 智能质检评分</li>
<li><i class="bi bi-check-circle"></i> 预测性分析</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="feature-box h-100">
<div class="feature-icon">🎯</div>
<h3>智能体系统</h3>
<p>基于大语言模型的智能体系统,实现角色定制、知识库对接、多智能体协作等高级功能。</p>
<ul class="list-unstyled">
<li><i class="bi bi-check-circle"></i> 智能角色定制</li>
<li><i class="bi bi-check-circle"></i> 知识库联动</li>
<li><i class="bi bi-check-circle"></i> 多智能体协作</li>
</ul>
</div>
</div>
</div>
<!-- 客户价值 -->
<div class="row mb-5">
<div class="col-12 text-center mb-4">
<h2>为什么选择 微语 AI Agent</h2>
<p class="lead text-muted">为企业创造实实在在的价值</p>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">💰</div>
<h4>降低成本</h4>
<p>AI自动化处理80%常见咨询,显著降低人工成本</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">⚡</div>
<h4>提升效率</h4>
<p>智能对话和工作流自动化提升效率达300%</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">📈</div>
<h4>增加收入</h4>
<p>智能营销和交叉销售提升转化率30%</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">😊</div>
<h4>提升满意度</h4>
<p>个性化服务提升客户满意度至95%</p>
</div>
</div>
</div>
<!-- 客户案例 -->
<div class="row mb-5">
<div class="col-12 text-center mb-4">
<h2>成功案例</h2>
<p class="lead text-muted">值得信赖的企业级AI解决方案</p>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">某大型电商平台</h5>
<p class="card-text">通过部署微语AI Agent系统客服效率提升300%客户满意度提升40%人工成本降低60%。</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">某金融机构</h5>
<p class="card-text">AI驱动的智能服务系统帮助客户服务成本降低50%业务转化率提升35%服务响应时间缩短80%。</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">某教育机构</h5>
<p class="card-text">智能AI系统助力招生咨询效率提升200%客户转化率提升45%人工成本降低70%。</p>
</div>
</div>
</div>
</div>
<!-- 行动召唤 -->
<div class="row text-center mb-5">
<div class="col-12">
<h2 class="mb-4">开启AI智能服务新时代</h2>
<p class="lead mb-4">立即体验 微语 AI Agent让AI为您的企业创造价值</p>
<div class="d-flex justify-content-center gap-3">
<a href="/contact" class="btn btn-primary btn-lg">免费试用</a>
<a href="/docs/zh-CN" class="btn btn-outline-secondary btn-lg">查看文档</a>
</div>
</div>
</div>
</div>
<footer class="bg-light py-4 mt-5">
<div class="container text-center">
<p class="mb-0">© 2025 微语. All rights reserved.</p>
<p class="text-muted">北京微语天下科技有限公司</p>
</div>
</footer>
<script src="/assets/vendor/jquery-3.7.1.min.js"></script>
<script src="/assets/vendor/bootstrap5/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e63a53cfb9c4d291ebe3c2b0edacb7622bbc480326beaa5a0456e412f52f066a
size 62547

View File

@@ -1,2 +0,0 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

View File

@@ -1,17 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-12-02 13:21:01
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-12-02 13:24:03
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# TODO
- [X] finished
- [ ] todo

308
modules/forum/bin/mvnw vendored
View File

@@ -1,308 +0,0 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

View File

@@ -1,205 +0,0 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

View File

@@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bytedesk</groupId>
<artifactId>modules</artifactId>
<version>${revision}</version>
</parent>
<artifactId>bytedesk-module-forum</artifactId>
<version>${revision}</version>
<name>bytedesk-module-forum</name>
<description>https://ai.bytedesk.com</description>
<properties>
</properties>
<dependencies>
<!-- ///////////////////////////////////////////////////////////////////////////// -->
<dependency>
<groupId>com.bytedesk</groupId>
<artifactId>bytedesk-module-core</artifactId>
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<!-- ///////////////////////////////////////////////////////////////////////////// -->
</dependencies>
<build>
<plugins>
<!-- <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin> -->
</plugins>
</build>
</project>

View File

@@ -1,14 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-09-11 10:22:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-12-02 11:35:28
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# forum

View File

@@ -1,182 +0,0 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2024-09-11 10:22:00
* @LastEditors: jack ning github@bytedesk.com
* @LastEditTime: 2025-02-26 22:56:37
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
-->
# 用户社区/论坛
## 1. 系统概述
ByteDesk用户社区是一个面向开发者和用户的交流平台旨在提供优质的技术讨论、问答和知识分享环境。参考[腾讯云-开发者社区](https://cloud.tencent.com/developer)实现。
## 2. 核心功能模块
### 2.1 用户系统
- 用户注册与登录
- 邮箱注册
- 手机号注册
- 第三方账号登录GitHub、微信等
- 用户个人中心
- 个人资料管理
- 头像设置
- 积分系统
- 收藏管理
- 发帖历史
- 回复历史
### 2.2 内容管理
- 板块分类
- 技术交流
- 产品反馈
- 使用教程
- 最佳实践
- 问答社区
- 官方公告
- 帖子功能
- 发布帖子支持Markdown
- 富文本编辑器
- 代码高亮
- 图片上传
- 附件管理
- 互动功能
- 点赞
- 收藏
- 分享
- 举报
- 评论与回复
### 2.3 社区运营
- 积分体系
- 发帖奖励
- 回复奖励
- 被采纳奖励
- 点赞获得积分
- 等级制度
- 用户等级
- 专家认证
- 官方认证
- 内容管理
- 内容审核
- 垃圾信息过滤
- 敏感词过滤
- 用户举报处理
### 2.4 搜索系统
- 全文检索
- 帖子搜索
- 评论搜索
- 用户搜索
- 高级筛选
- 时间范围
- 板块筛选
- 标签筛选
- 热度排序
### 2.5 通知系统
- 站内消息
- 回复提醒
- 点赞提醒
- 系统通知
- 邮件通知
- 重要消息邮件提醒
- 周报订阅
- 消息订阅
- 关注用户动态
- 话题订阅
## 3. 技术特性
### 3.1 性能优化
- 页面缓存
- 数据库优化
- CDN加速
- 图片压缩
### 3.2 安全特性
- XSS防护
- CSRF防护
- SQL注入防护
- 敏感信息加密
- 访问频率限制
### 3.3 运维监控
- 访问统计
- 性能监控
- 错误日志
- 用户行为分析
## 4. 界面设计
### 4.1 PC端
- 响应式布局
- 深色模式支持
- 自适应屏幕
### 4.2 移动端
- 移动端适配
- APP版本
- 小程序版本
## 5. 扩展功能
### 5.1 社区活动
- 技术沙龙
- 在线直播
- 技术大赛
- 有奖问答
### 5.2 知识库
- 官方文档
- 常见问题
- 最佳实践
- 案例分享
### 5.3 社区生态
- 开发者认证
- 技术专家
- 贡献榜单
- 荣誉体系
## 6. 后续规划
### 6.1 近期计划
- 基础功能实现
- 用户系统搭建
- 内容发布功能
- 基础互动功能
### 6.2 中期计划
- 完善运营体系
- 引入积分机制
- 优化搜索系统
- 移动端适配
### 6.3 长期计划
- 社区生态建设
- 知识库体系
- 活动运营
- 商业化探索

View File

@@ -1 +0,0 @@
spring.application.name=baidu

View File

@@ -1,34 +0,0 @@
.post-content {
line-height: 1.6;
font-size: 1.1rem;
}
.comment {
border-bottom: 1px solid #eee;
padding-bottom: 1rem;
}
.comment:last-child {
border-bottom: none;
}
.pagination {
margin-bottom: 0;
}
.list-group-item a {
color: #333;
text-decoration: none;
}
.list-group-item a:hover {
color: #007bff;
}
.card {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.navbar {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

View File

@@ -1,71 +0,0 @@
<#import "layout/base.ftl" as base>
<@base.base title="${category.name} - ByteDesk Forum">
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/forum">首页</a></li>
<li class="breadcrumb-item active">${category.name}</li>
</ol>
</nav>
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>${category.name} - 帖子列表</span>
<a href="/forum/posts/create?categoryId=${category.id}" class="btn btn-primary btn-sm">发布帖子</a>
</div>
<div class="list-group list-group-flush">
<#list posts.content as post>
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">
<a href="/forum/posts/${post.id}" class="text-decoration-none">${post.title}</a>
</h5>
<small>${post.createdAt?string('yyyy-MM-dd HH:mm')}</small>
</div>
<p class="mb-1 text-truncate">${post.content}</p>
<div class="d-flex justify-content-between align-items-center">
<small>
<span class="me-2">
<i class="bi bi-eye"></i> ${post.viewCount}
</span>
<span class="me-2">
<i class="bi bi-chat"></i> ${post.commentCount}
</span>
<span>
<i class="bi bi-heart"></i> ${post.likeCount}
</span>
</small>
<small>作者: ${post.userId}</small>
</div>
</div>
</#list>
</div>
</div>
<!-- 分页 -->
<nav class="mt-4">
<ul class="pagination justify-content-center">
<#if posts.hasPrevious()>
<li class="page-item">
<a class="page-link" href="?page=${posts.number - 1}">上一页</a>
</li>
</#if>
<#list 0..posts.totalPages-1 as i>
<li class="page-item ${(i == posts.number)?string('active', '')}">
<a class="page-link" href="?page=${i}">${i + 1}</a>
</li>
</#list>
<#if posts.hasNext()>
<li class="page-item">
<a class="page-link" href="?page=${posts.number + 1}">下一页</a>
</li>
</#if>
</ul>
</nav>
</div>
</div>
</@base.base>

View File

@@ -1,82 +0,0 @@
<#import "layout/base.ftl" as base>
<@base.base title="ByteDesk Forum - 首页">
<div class="row">
<!-- 左侧分类列表 -->
<div class="col-md-3">
<div class="card">
<div class="card-header">
分类
</div>
<div class="list-group list-group-flush">
<#list categories as category>
<a href="/forum/category/${category.id}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
${category.name}
<span class="badge bg-primary rounded-pill">${category.postCount}</span>
</a>
</#list>
</div>
</div>
</div>
<!-- 右侧帖子列表 -->
<div class="col-md-9">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>最新帖子</span>
<a href="/forum/posts/create" class="btn btn-primary btn-sm">发布帖子</a>
</div>
<div class="list-group list-group-flush">
<#list posts.content as post>
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">
<a href="/forum/posts/${post.id}" class="text-decoration-none">${post.title}</a>
</h5>
<small>${post.createdAt?string('yyyy-MM-dd HH:mm')}</small>
</div>
<p class="mb-1 text-truncate">${post.content}</p>
<div class="d-flex justify-content-between align-items-center">
<small>
<span class="me-2">
<i class="bi bi-eye"></i> ${post.viewCount}
</span>
<span class="me-2">
<i class="bi bi-chat"></i> ${post.commentCount}
</span>
<span>
<i class="bi bi-heart"></i> ${post.likeCount}
</span>
</small>
<small>作者: ${post.userId}</small>
</div>
</div>
</#list>
</div>
</div>
<!-- 分页 -->
<nav class="mt-4">
<ul class="pagination justify-content-center">
<#if posts.hasPrevious()>
<li class="page-item">
<a class="page-link" href="?page=${posts.number - 1}">上一页</a>
</li>
</#if>
<#list 0..posts.totalPages-1 as i>
<li class="page-item ${(i == posts.number)?string('active', '')}">
<a class="page-link" href="?page=${i}">${i + 1}</a>
</li>
</#list>
<#if posts.hasNext()>
<li class="page-item">
<a class="page-link" href="?page=${posts.number + 1}">下一页</a>
</li>
</#if>
</ul>
</nav>
</div>
</div>
</@base.base>

View File

@@ -1,209 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>微语 社区论坛 - AI驱动的智能社区平台</title>
<meta name="description" content="微语社区论坛是一个基于AI的智能社区平台为企业提供安全可靠的知识分享与交流解决方案">
<link href="/assets/vendor/bootstrap5/css/bootstrap.min.css" rel="stylesheet">
<#-- <link href="/css/ticket/index.css" rel="stylesheet"> -->
<style>
.feature-icon {
font-size: 2.5rem;
color: #0d6efd;
margin-bottom: 1rem;
}
.feature-box {
padding: 2rem;
border-radius: 10px;
background: #f8f9fa;
transition: all 0.3s ease;
}
.feature-box:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.card {
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="#">微语社区论坛</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#技术交流">技术交流</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#问答社区">问答社区</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#最佳实践">最佳实践</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#官方公告">官方公告</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container my-5">
<!-- 顶部介绍区域 -->
<div class="row text-center mb-5">
<div class="col">
<h1 class="display-4 mb-3">AI驱动的智能社区平台</h1>
<p class="lead">基于大语言模型的智能社区系统,重新定义知识分享与交流体验</p>
<div class="mt-4">
<a href="/contact" class="btn btn-primary btn-lg me-3">免费试用</a>
<a href="/docs/zh-CN" class="btn btn-outline-primary btn-lg">查看文档</a>
</div>
</div>
</div>
<!-- AI 核心优势 -->
<div class="row mb-5">
<div class="col-12 text-center mb-4">
<h2>AI 驱动的智能社区</h2>
<p class="lead text-muted">结合大语言模型,打造智能化社区体验</p>
</div>
<div class="col-md-4">
<div class="feature-box h-100">
<div class="feature-icon">🤖</div>
<h3>智能内容推荐</h3>
<p>基于大语言模型的智能推荐系统,为用户提供个性化内容推荐。</p>
<ul class="list-unstyled">
<li><i class="bi bi-check-circle"></i> 个性化推荐</li>
<li><i class="bi bi-check-circle"></i> 兴趣匹配</li>
<li><i class="bi bi-check-circle"></i> 热点发现</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="feature-box h-100">
<div class="feature-icon">📊</div>
<h3>智能内容分析</h3>
<p>AI驱动的社区分析系统提供内容质量评估和社区洞察。</p>
<ul class="list-unstyled">
<li><i class="bi bi-check-circle"></i> 质量评估</li>
<li><i class="bi bi-check-circle"></i> 情感分析</li>
<li><i class="bi bi-check-circle"></i> 趋势预测</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="feature-box h-100">
<div class="feature-icon">🎯</div>
<h3>智能社区管理</h3>
<p>基于AI的智能管理系统自动维护社区秩序提升用户体验。</p>
<ul class="list-unstyled">
<li><i class="bi bi-check-circle"></i> 内容审核</li>
<li><i class="bi bi-check-circle"></i> 用户画像</li>
<li><i class="bi bi-check-circle"></i> 行为分析</li>
</ul>
</div>
</div>
</div>
<!-- 客户价值 -->
<div class="row mb-5">
<div class="col-12 text-center mb-4">
<h2>为什么选择 微语 社区论坛?</h2>
<p class="lead text-muted">为企业创造实实在在的价值</p>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">💰</div>
<h4>降低成本</h4>
<p>AI管理降低运营成本50%</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">⚡</div>
<h4>提升活跃度</h4>
<p>智能推荐提升用户活跃度200%</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">📈</div>
<h4>内容质量</h4>
<p>智能分析提升内容质量40%</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="feature-icon">😊</div>
<h4>提升满意度</h4>
<p>优质体验提升用户满意度至95%</p>
</div>
</div>
</div>
<!-- 成功案例 -->
<div class="row mb-5">
<div class="col-12 text-center mb-4">
<h2>成功案例</h2>
<p class="lead text-muted">值得信赖的企业级解决方案</p>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">某大型科技社区</h5>
<p class="card-text">通过部署微语社区论坛用户活跃度提升200%内容质量提升40%。</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">某教育机构</h5>
<p class="card-text">AI驱动的智能社区系统帮助师生互动效率提升150%学习效果提升35%。</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">某企业社区</h5>
<p class="card-text">智能社区平台助力知识分享效率提升45%员工满意度提升50%。</p>
</div>
</div>
</div>
</div>
<!-- 行动召唤 -->
<div class="row text-center mb-5">
<div class="col-12">
<h2 class="mb-4">开启智能社区新时代</h2>
<p class="lead mb-4">立即体验 微语 社区论坛让AI为您的企业创造价值</p>
<div class="d-flex justify-content-center gap-3">
<a href="/contact" class="btn btn-primary btn-lg">免费试用</a>
<a href="/docs/zh-CN" class="btn btn-outline-secondary btn-lg">查看文档</a>
</div>
</div>
</div>
</div>
<footer class="bg-light py-4 mt-5">
<div class="container text-center">
<p class="mb-0">© 2025 微语. All rights reserved.</p>
<p class="text-muted">北京微语天下科技有限公司</p>
</div>
</footer>
<script src="/assets/vendor/jquery-3.7.1.min.js"></script>
<script src="/assets/vendor/bootstrap5/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -1,80 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${title!'ByteDesk Forum'}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/forum/style.css" rel="stylesheet">
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/forum">ByteDesk Forum</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/forum">首页</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/forum/categories">分类</a>
</li>
</ul>
<div class="d-flex align-items-center">
<form class="d-flex me-3" action="/forum/search" method="GET">
<input class="form-control me-2" type="search" name="keyword" placeholder="搜索帖子...">
<button class="btn btn-outline-light" type="submit">搜索</button>
</form>
<#if currentUser??>
<div class="dropdown">
<button class="btn btn-outline-light dropdown-toggle" type="button" data-bs-toggle="dropdown">
${currentUser.username}
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="/forum/user/posts">我的帖子</a></li>
<li><a class="dropdown-item" href="/forum/user/comments">我的评论</a></li>
<li><hr class="dropdown-divider"></li>
<li>
<form action="/logout" method="POST" class="dropdown-item">
<button type="submit" class="btn btn-link p-0">退出登录</button>
</form>
</li>
</ul>
</div>
<#else>
<a href="/login" class="btn btn-outline-light">登录</a>
<a href="/register" class="btn btn-light ms-2">注册</a>
</#if>
</div>
</div>
</div>
</nav>
<!-- 主要内容 -->
<main class="container my-4">
<#nested>
</main>
<!-- 页脚 -->
<footer class="bg-dark text-light py-4 mt-5">
<div class="container">
<div class="row">
<div class="col-md-6">
<h5>ByteDesk Forum</h5>
<p>一个开源的社区论坛系统</p>
</div>
<div class="col-md-6 text-end">
<p>&copy; 2024 ByteDesk. All rights reserved.</p>
</div>
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="/js/forum/main.js"></script>
</body>
</html>

View File

@@ -1,77 +0,0 @@
<#import "layout/base.ftl" as base>
<@base.base title="${post??'编辑帖子':'发布新帖子'} - ByteDesk Forum">
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/forum">首页</a></li>
<li class="breadcrumb-item active">${post??'发布新帖子':'编辑帖子'}</li>
</ol>
</nav>
<div class="card">
<div class="card-header">
<h5 class="mb-0">${post??'发布新帖子':'编辑帖子'}</h5>
</div>
<div class="card-body">
<form id="postForm" method="POST" action="/api/v1/posts${post??'/'+post.id:''}">
<div class="mb-3">
<label for="title" class="form-label">标题</label>
<input type="text" class="form-control" id="title" name="title"
value="${(post.title)!''}" required>
</div>
<div class="mb-3">
<label for="categoryId" class="form-label">分类</label>
<select class="form-select" id="categoryId" name="categoryId" required>
<option value="">选择分类</option>
<#list categories as category>
<option value="${category.id}"
${((post.categoryId?? && post.categoryId == category.id) ||
(selectedCategory?? && selectedCategory.id == category.id))?string('selected', '')}>
${category.name}
</option>
</#list>
</select>
</div>
<div class="mb-3">
<label for="content" class="form-label">内容</label>
<textarea class="form-control" id="content" name="content"
rows="10" required>${(post.content)!''}</textarea>
</div>
<input type="hidden" name="_method" value="${post??'PUT':'POST'}">
<div class="text-end">
<a href="javascript:history.back()" class="btn btn-secondary">取消</a>
<button type="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
document.getElementById('postForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const method = formData.get('_method');
formData.delete('_method');
fetch(this.action, {
method: method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams(formData)
}).then(response => {
if (response.ok) {
window.location.href = '/forum';
}
});
});
</script>
</@base.base>

View File

@@ -1,137 +0,0 @@
<#import "layout/base.ftl" as base>
<@base.base title="${post.title} - ByteDesk Forum">
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/forum">首页</a></li>
<li class="breadcrumb-item"><a href="/forum/category/${post.categoryId}">分类</a></li>
<li class="breadcrumb-item active">${post.title}</li>
</ol>
</nav>
<!-- 帖子内容 -->
<div class="card mb-4">
<div class="card-header">
<h4 class="mb-0">${post.title}</h4>
<small class="text-muted">
作者: ${post.userId} |
发布时间: ${post.createdAt?string('yyyy-MM-dd HH:mm:ss')} |
浏览: ${post.viewCount} |
评论: ${post.commentCount} |
点赞: ${post.likeCount}
</small>
</div>
<div class="card-body">
<div class="post-content">
${post.content}
</div>
<div class="text-end mt-3">
<button class="btn btn-outline-primary btn-sm" onclick="likePost(${post.id})">
<i class="bi bi-heart"></i> 点赞
</button>
</div>
</div>
</div>
<!-- 评论区 -->
<div class="card">
<div class="card-header">
评论区
</div>
<div class="card-body">
<!-- 发表评论 -->
<form id="commentForm" class="mb-4">
<div class="mb-3">
<textarea class="form-control" id="commentContent" rows="3" placeholder="写下你的评论..."></textarea>
</div>
<button type="submit" class="btn btn-primary">发表评论</button>
</form>
<!-- 评论列表 -->
<div class="comments-list">
<#list comments.content as comment>
<div class="comment mb-3">
<div class="d-flex justify-content-between">
<div>
<strong>${comment.userId}</strong>
<small class="text-muted ms-2">${comment.createdAt?string('yyyy-MM-dd HH:mm')}</small>
</div>
<button class="btn btn-link btn-sm" onclick="likeComment(${comment.id})">
<i class="bi bi-heart"></i> ${comment.likeCount}
</button>
</div>
<div class="mt-2">
${comment.content}
</div>
</div>
</#list>
</div>
<!-- 评论分页 -->
<nav class="mt-4">
<ul class="pagination justify-content-center">
<#if comments.hasPrevious()>
<li class="page-item">
<a class="page-link" href="?page=${comments.number - 1}#comments">上一页</a>
</li>
</#if>
<#list 0..comments.totalPages-1 as i>
<li class="page-item ${(i == comments.number)?string('active', '')}">
<a class="page-link" href="?page=${i}#comments">${i + 1}</a>
</li>
</#list>
<#if comments.hasNext()>
<li class="page-item">
<a class="page-link" href="?page=${comments.number + 1}#comments">下一页</a>
</li>
</#if>
</ul>
</nav>
</div>
</div>
</div>
</div>
<script>
function likePost(postId) {
fetch(`/api/v1/posts/${postId}/like`, {
method: 'POST'
}).then(response => {
if (response.ok) {
location.reload();
}
});
}
function likeComment(commentId) {
fetch(`/api/v1/comments/${commentId}/like`, {
method: 'POST'
}).then(response => {
if (response.ok) {
location.reload();
}
});
}
document.getElementById('commentForm').addEventListener('submit', function(e) {
e.preventDefault();
const content = document.getElementById('commentContent').value;
fetch('/api/v1/comments', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `content=${encodeURIComponent(content)}&postId=${post.id}&userId=${currentUserId}`
}).then(response => {
if (response.ok) {
location.reload();
}
});
});
</script>
</@base.base>

View File

@@ -1,78 +0,0 @@
<#import "layout/base.ftl" as base>
<@base.base title="搜索结果 - ByteDesk Forum">
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/forum">首页</a></li>
<li class="breadcrumb-item active">搜索结果</li>
</ol>
</nav>
<div class="card">
<div class="card-header">
搜索结果: "${keyword}"
</div>
<div class="list-group list-group-flush">
<#if posts.totalElements == 0>
<div class="list-group-item text-center text-muted">
没有找到相关内容
</div>
<#else>
<#list posts.content as post>
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">
<a href="/forum/posts/${post.id}" class="text-decoration-none">${post.title}</a>
</h5>
<small>${post.createdAt?string('yyyy-MM-dd HH:mm')}</small>
</div>
<p class="mb-1 text-truncate">${post.content}</p>
<div class="d-flex justify-content-between align-items-center">
<small>
<span class="me-2">
<i class="bi bi-eye"></i> ${post.viewCount}
</span>
<span class="me-2">
<i class="bi bi-chat"></i> ${post.commentCount}
</span>
<span>
<i class="bi bi-heart"></i> ${post.likeCount}
</span>
</small>
<small>作者: ${post.userId}</small>
</div>
</div>
</#list>
</#if>
</div>
</div>
<!-- 分页 -->
<#if posts.totalElements gt 0>
<nav class="mt-4">
<ul class="pagination justify-content-center">
<#if posts.hasPrevious()>
<li class="page-item">
<a class="page-link" href="?keyword=${keyword}&page=${posts.number - 1}">上一页</a>
</li>
</#if>
<#list 0..posts.totalPages-1 as i>
<li class="page-item ${(i == posts.number)?string('active', '')}">
<a class="page-link" href="?keyword=${keyword}&page=${i}">${i + 1}</a>
</li>
</#list>
<#if posts.hasNext()>
<li class="page-item">
<a class="page-link" href="?keyword=${keyword}&page=${posts.number + 1}">下一页</a>
</li>
</#if>
</ul>
</nav>
</#if>
</div>
</div>
</@base.base>

View File

@@ -1,81 +0,0 @@
<#import "layout/base.ftl" as base>
<@base.base title="我的帖子 - ByteDesk Forum">
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/forum">首页</a></li>
<li class="breadcrumb-item active">我的帖子</li>
</ol>
</nav>
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>我的帖子</span>
<a href="/forum/posts/create" class="btn btn-primary btn-sm">发布帖子</a>
</div>
<div class="list-group list-group-flush">
<#if posts.totalElements == 0>
<div class="list-group-item text-center text-muted">
还没有发布过帖子
</div>
<#else>
<#list posts.content as post>
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">
<a href="/forum/posts/${post.id}" class="text-decoration-none">${post.title}</a>
</h5>
<div>
<small class="text-muted me-2">${post.createdAt?string('yyyy-MM-dd HH:mm')}</small>
<a href="/forum/posts/${post.id}/edit" class="btn btn-outline-primary btn-sm">编辑</a>
</div>
</div>
<p class="mb-1 text-truncate">${post.content}</p>
<div class="d-flex justify-content-between align-items-center">
<small>
<span class="me-2">
<i class="bi bi-eye"></i> ${post.viewCount}
</span>
<span class="me-2">
<i class="bi bi-chat"></i> ${post.commentCount}
</span>
<span>
<i class="bi bi-heart"></i> ${post.likeCount}
</span>
</small>
<small>状态: ${post.status}</small>
</div>
</div>
</#list>
</#if>
</div>
</div>
<#if posts.totalElements gt 0>
<nav class="mt-4">
<ul class="pagination justify-content-center">
<#if posts.hasPrevious()>
<li class="page-item">
<a class="page-link" href="?page=${posts.number - 1}">上一页</a>
</li>
</#if>
<#list 0..posts.totalPages-1 as i>
<li class="page-item ${(i == posts.number)?string('active', '')}">
<a class="page-link" href="?page=${i}">${i + 1}</a>
</li>
</#list>
<#if posts.hasNext()>
<li class="page-item">
<a class="page-link" href="?page=${posts.number + 1}">下一页</a>
</li>
</#if>
</ul>
</nav>
</#if>
</div>
</div>
</@base.base>

View File

@@ -1,131 +0,0 @@
<#import "../layout/base.ftl" as base>
<@base.base title="个人中心 - ByteDesk Forum">
<div class="row">
<!-- 左侧导航 -->
<div class="col-md-3">
<div class="card">
<div class="card-header">
个人中心
</div>
<div class="list-group list-group-flush">
<a href="/forum/user/profile" class="list-group-item list-group-item-action active">
基本信息
</a>
<a href="/forum/user/posts" class="list-group-item list-group-item-action">
我的帖子
</a>
<a href="/forum/user/comments" class="list-group-item list-group-item-action">
我的评论
</a>
<a href="/forum/user/likes" class="list-group-item list-group-item-action">
我的点赞
</a>
<a href="/forum/user/settings" class="list-group-item list-group-item-action">
账号设置
</a>
</div>
</div>
</div>
<!-- 右侧内容 -->
<div class="col-md-9">
<div class="card">
<div class="card-header">
基本信息
</div>
<div class="card-body">
<form id="profileForm" class="needs-validation" novalidate>
<div class="row mb-3">
<label class="col-sm-2 col-form-label">用户名</label>
<div class="col-sm-10">
<input type="text" class="form-control" value="${currentUser.username}" readonly>
</div>
</div>
<div class="row mb-3">
<label for="nickname" class="col-sm-2 col-form-label">昵称</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="nickname" name="nickname"
value="${currentUser.nickname!''}" required>
</div>
</div>
<div class="row mb-3">
<label for="email" class="col-sm-2 col-form-label">邮箱</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email" name="email"
value="${currentUser.email!''}" required>
</div>
</div>
<div class="row mb-3">
<label for="bio" class="col-sm-2 col-form-label">个人简介</label>
<div class="col-sm-10">
<textarea class="form-control" id="bio" name="bio"
rows="3">${currentUser.bio!''}</textarea>
</div>
</div>
<div class="row mb-3">
<label class="col-sm-2 col-form-label">注册时间</label>
<div class="col-sm-10">
<input type="text" class="form-control"
value="${currentUser.createdAt?string('yyyy-MM-dd HH:mm:ss')}" readonly>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-2">
<button type="submit" class="btn btn-primary">保存修改</button>
</div>
</div>
</form>
</div>
</div>
<!-- 统计信息 -->
<div class="card mt-4">
<div class="card-header">
统计信息
</div>
<div class="card-body">
<div class="row text-center">
<div class="col-md-4">
<h4>${userStats.postCount}</h4>
<p class="text-muted">发帖数</p>
</div>
<div class="col-md-4">
<h4>${userStats.commentCount}</h4>
<p class="text-muted">评论数</p>
</div>
<div class="col-md-4">
<h4>${userStats.likeCount}</h4>
<p class="text-muted">获赞数</p>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.getElementById('profileForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch('/api/v1/users/profile', {
method: 'PUT',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams(formData)
}).then(response => {
if (response.ok) {
alert('保存成功');
location.reload();
}
});
});
</script>
</@base.base>