feat: 添加好友功能并集成 LiteLLM 代理服务
- 新增好友搜索、添加、好友列表功能 - 集成 LiteLLM 代理服务及多模型定价配置 - 更新 iOS CocoaPods 配置 - 更新 .gitignore 和环境变量配置
This commit is contained in:
+66
-12
@@ -5,12 +5,13 @@ ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
SESSION_NAME="${SESSION_NAME:-social-dev}"
|
||||
COMPOSE_FILE="$ROOT_DIR/infra/docker/docker-compose.yml"
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
LITELLM_RUNTIME_CONFIG="$ROOT_DIR/.tmp/litellm-proxy-config.yaml"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " start Start web + worker processes in tmux"
|
||||
echo " start Start LiteLLM + web + worker processes in tmux"
|
||||
echo " stop Stop tmux session and clean orphaned processes"
|
||||
echo " restart Stop then start all app processes"
|
||||
exit 1
|
||||
@@ -86,9 +87,37 @@ kill_pids_gracefully() {
|
||||
kill -KILL "${alive[@]}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
kill_matching_processes() {
|
||||
local label="$1"
|
||||
local pattern="$2"
|
||||
local pids
|
||||
|
||||
pids="$(pgrep -f "$pattern" || true)"
|
||||
if [ -z "$pids" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
kill_pids_gracefully "$label" $pids
|
||||
}
|
||||
|
||||
kill_listening_processes() {
|
||||
local label="$1"
|
||||
local port="$2"
|
||||
local pids
|
||||
|
||||
pids="$(collect_listening_pids "$port" || true)"
|
||||
if [ -z "$pids" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
kill_pids_gracefully "$label" $pids
|
||||
}
|
||||
|
||||
start() {
|
||||
echo "=== App Up ==="
|
||||
echo "This script starts web + worker processes in tmux."
|
||||
echo "This script starts LiteLLM + web + worker processes in tmux."
|
||||
echo "NOTE: Bootstrap (migrate + init-data) must be run separately."
|
||||
echo ""
|
||||
|
||||
@@ -110,8 +139,9 @@ start() {
|
||||
load_env_if_exists
|
||||
|
||||
UVICORN_LOG_LEVEL="${SOCIAL_RUNTIME__LOG_LEVEL:-info}"
|
||||
UVICORN_LOG_LEVEL="${UVICORN_LOG_LEVEL,,}"
|
||||
UVICORN_LOG_LEVEL="$(echo "$UVICORN_LOG_LEVEL" | tr '[:upper:]' '[:lower:]')"
|
||||
WEB_PORT="${SOCIAL_WEB__PORT:-5775}"
|
||||
LITELLM_PORT="${SOCIAL_LITELLM__PORT:-3875}"
|
||||
|
||||
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
|
||||
echo "Error: tmux session '$SESSION_NAME' already exists." >&2
|
||||
@@ -125,7 +155,24 @@ start() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting web + worker processes in tmux session '$SESSION_NAME'..."
|
||||
if is_port_in_use "$LITELLM_PORT"; then
|
||||
echo "Error: litellm port ${LITELLM_PORT} is already in use." >&2
|
||||
echo "Hint: run '$0 stop' or change SOCIAL_LITELLM__PORT in .env" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${SOCIAL_LLM__PROVIDER_KEYS__DASHSCOPE:-}" ]; then
|
||||
echo "Warning: SOCIAL_LLM__PROVIDER_KEYS__DASHSCOPE is empty; qwen calls may fail." >&2
|
||||
fi
|
||||
if [ -z "${SOCIAL_LLM__PROVIDER_KEYS__DEEPSEEK:-}" ]; then
|
||||
echo "Warning: SOCIAL_LLM__PROVIDER_KEYS__DEEPSEEK is empty; deepseek calls may fail." >&2
|
||||
fi
|
||||
|
||||
echo "Starting LiteLLM + web + worker processes in tmux session '$SESSION_NAME'..."
|
||||
|
||||
PYTHONPATH=backend/src uv run python backend/scripts/build_litellm_proxy_config.py --output "$LITELLM_RUNTIME_CONFIG"
|
||||
|
||||
LITELLM_CMD="cd '$ROOT_DIR' && DASHSCOPE_API_KEY='${SOCIAL_LLM__PROVIDER_KEYS__DASHSCOPE:-}' DEEPSEEK_API_KEY='${SOCIAL_LLM__PROVIDER_KEYS__DEEPSEEK:-}' ARK_API_KEY='${SOCIAL_LLM__PROVIDER_KEYS__ARK:-}' uv run litellm --config '$LITELLM_RUNTIME_CONFIG' --port ${LITELLM_PORT}"
|
||||
|
||||
WEB_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src SOCIAL_RUNTIME__SERVICE_NAME=web uv run uvicorn app:app --host \
|
||||
${SOCIAL_WEB__HOST:-0.0.0.0} --port ${WEB_PORT} --workers \
|
||||
@@ -135,7 +182,8 @@ ${SOCIAL_WEB__WORKERS:-2} --log-level ${UVICORN_LOG_LEVEL}"
|
||||
WORKER_DEFAULT_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src SOCIAL_RUNTIME__SERVICE_NAME=worker-default uv run taskiq worker core.taskiq.app:default_broker core.agent.infrastructure.queue.tasks --workers ${SOCIAL_WORKER__GROUPS__DEFAULT__CONCURRENCY:-2}"
|
||||
WORKER_BULK_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src SOCIAL_RUNTIME__SERVICE_NAME=worker-bulk uv run taskiq worker core.taskiq.app:bulk_broker core.agent.infrastructure.queue.tasks --workers ${SOCIAL_WORKER__GROUPS__BULK__CONCURRENCY:-1}"
|
||||
|
||||
tmux new-session -d -s "$SESSION_NAME" -n web "bash -lc \"$WEB_CMD; echo '[web] exited'; exec bash\""
|
||||
tmux new-session -d -s "$SESSION_NAME" -n litellm "bash -lc \"$LITELLM_CMD; echo '[litellm] exited'; exec bash\""
|
||||
tmux new-window -t "$SESSION_NAME" -n web "bash -lc \"$WEB_CMD; echo '[web] exited'; exec bash\""
|
||||
tmux new-window -t "$SESSION_NAME" -n worker-critical "bash -lc \"$WORKER_CRITICAL_CMD; echo '[worker-critical] exited'; exec bash\""
|
||||
tmux new-window -t "$SESSION_NAME" -n worker-default "bash -lc \"$WORKER_DEFAULT_CMD; echo '[worker-default] exited'; exec bash\""
|
||||
tmux new-window -t "$SESSION_NAME" -n worker-bulk "bash -lc \"$WORKER_BULK_CMD; echo '[worker-bulk] exited'; exec bash\""
|
||||
@@ -143,6 +191,7 @@ ${SOCIAL_WEB__WORKERS:-2} --log-level ${UVICORN_LOG_LEVEL}"
|
||||
echo ""
|
||||
echo "=== App Started ==="
|
||||
echo "Log files will be created in logs/ directory:"
|
||||
echo " - litellm.log, litellm.error.log"
|
||||
echo " - web.log, web.error.log"
|
||||
echo " - worker-critical.log, worker-critical.error.log"
|
||||
echo " - worker-default.log, worker-default.error.log"
|
||||
@@ -156,6 +205,7 @@ stop() {
|
||||
echo "=== App Down ==="
|
||||
load_env_if_exists
|
||||
WEB_PORT="${SOCIAL_WEB__PORT:-5775}"
|
||||
LITELLM_PORT="${SOCIAL_LITELLM__PORT:-3875}"
|
||||
|
||||
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
|
||||
echo "Stopping tmux session '$SESSION_NAME'..."
|
||||
@@ -166,14 +216,12 @@ stop() {
|
||||
|
||||
echo "Checking for orphaned processes..."
|
||||
|
||||
mapfile -t uvicorn_pids < <(pgrep -f "uv run uvicorn app:app" || true)
|
||||
kill_pids_gracefully "uvicorn" "${uvicorn_pids[@]}"
|
||||
kill_matching_processes "uvicorn" "uv run uvicorn app:app"
|
||||
kill_matching_processes "litellm" "uv run litellm --config"
|
||||
kill_matching_processes "taskiq workers" "uv run taskiq worker core.taskiq.app:"
|
||||
|
||||
mapfile -t taskiq_pids < <(pgrep -f "uv run taskiq worker core.taskiq.app:" || true)
|
||||
kill_pids_gracefully "taskiq workers" "${taskiq_pids[@]}"
|
||||
|
||||
mapfile -t port_pids < <(collect_listening_pids "$WEB_PORT" || true)
|
||||
kill_pids_gracefully "port ${WEB_PORT} listeners" "${port_pids[@]}"
|
||||
kill_listening_processes "port ${WEB_PORT} listeners" "$WEB_PORT"
|
||||
kill_listening_processes "port ${LITELLM_PORT} listeners" "$LITELLM_PORT"
|
||||
|
||||
if is_port_in_use "$WEB_PORT"; then
|
||||
echo "Warning: port ${WEB_PORT} is still in use after cleanup." >&2
|
||||
@@ -181,6 +229,12 @@ stop() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if is_port_in_use "$LITELLM_PORT"; then
|
||||
echo "Warning: port ${LITELLM_PORT} is still in use after cleanup." >&2
|
||||
echo "Hint: check process with 'lsof -iTCP:${LITELLM_PORT} -sTCP:LISTEN'" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Session stopped and cleaned up."
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user