Эх сурвалжийг харах

Merge branch 'lbq' of wushan/ai_learning into master

lbq 1 долоо хоног өмнө
parent
commit
3427bc8ec5

+ 35 - 0
Dockerfile

@@ -0,0 +1,35 @@
+# 使用官方 Python 3.11 作为基础镜像
+FROM python:3.11  
+ # 定义构建参数,用户名称为 app
+ARG USER=app 
+# 定义构建参数,应用目录为 /app
+ARG APP_DIR=/app  
+# 设置环境变量 APP_DIR
+ENV APP_DIR=${APP_DIR}  
+
+# 创建用户组和用户,并设置家目录
+RUN groupadd -g 61000 ${USER} \
+  && useradd -g 61000 -u 61000 -ms /bin/bash -d ${APP_DIR} ${USER}
+
+  # 设置工作目录为 /app
+WORKDIR ${APP_DIR}  
+
+# 复制 fastapi 目录下的所有代码到镜像中
+COPY ./fastapi_demo ./fastapi_demo   
+# 安装 fastapi 目录下的依赖  使用国内源更快拉依赖
+RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r ./fastapi_demo/requirements.txt  
+
+# 复制启动脚本到镜像中
+COPY ./entrypoint.sh ./entrypoint.sh  
+ # 修改 /app 目录及其内容的所有者为 app 用户
+RUN chown -R ${USER}:${USER} ${APP_DIR} 
+
+# 切换到非 root 用户,提升安全性
+USER ${USER}
+# 设置容器启动时执行的脚本
+ENTRYPOINT ["/app/entrypoint.sh"]  
+
+# 默认传递给 entrypoint.sh 的参数(可选)
+# 在entrypoint脚本中如果传入参数为chill会进入空转状态,如果有写别的命令则会覆盖这条
+
+CMD ["chill"]  

+ 16 - 0
compose.yaml

@@ -0,0 +1,16 @@
+services:
+  api:
+    build:
+      context: .
+      dockerfile: Dockerfile
+    image: ${IMAGE_NAME:-agent-api}:${IMAGE_TAG:-latest}
+    command: uvicorn fastapi_demo.main:app --host 0.0.0.0 --port 8000 --reload
+    restart: unless-stopped
+    volumes:
+      - .:/app
+    ports:
+      - 8000:8000
+    environment:
+      - BAILIAN_API_KEY:${BAILIAN_API_KEY}
+      - BAILIAN_API_BASE_URL:${BAILIAN_API_BASE_URL}
+      - PRINT_ENV_ON_LOAD:"true"

+ 25 - 0
entrypoint.sh

@@ -0,0 +1,25 @@
+#!/bin/bash 
+############################################################################
+# Container Entrypoint script
+############################################################################
+if [[ "$PRINT_ENV_ON_LOAD" = true || "$PRINT_ENV_ON_LOAD" = True ]]; then
+  echo "=================================================="
+  printenv
+  echo "=================================================="
+fi
+
+############################################################################
+# Start App
+############################################################################
+
+case "$1" in
+  chill)
+    ;;
+  *)
+    echo "Running: $@"
+    exec "$@"
+    ;;
+esac
+
+echo ">>> Hello World!"
+while true; do sleep 18000; done

+ 0 - 0
fastapi_demo/__init__.py


+ 43 - 0
fastapi_demo/main.py

@@ -0,0 +1,43 @@
+   # main.py
+from fastapi import FastAPI, Request
+from agno.storage.sqlite import SqliteStorage
+from sse_starlette.sse import EventSourceResponse
+from agno.agent import Agent
+from agno.models.openai import OpenAILike
+from dotenv import load_dotenv
+import os
+app = FastAPI()
+load_dotenv()
+# 读取环境变量
+model = OpenAILike(
+    id="qwen3-32b",
+    api_key=os.getenv("BAILIAN_API_KEY"),
+    base_url=os.getenv("BAILIAN_API_BASE_URL"),
+  #  request_params={"extra_body": {"enable_thinking": False}},#如果不使用流式输出记得加这句话不然会报错
+)
+   # 初始化 Agent
+agent = Agent(
+       model=model,
+       instructions=(
+        "你是一个信息收集助手,需要和用户多轮对话,收集用户的姓名、年龄和感兴趣的行业。"
+        "请严格按照顺序提问:先问姓名,再问年龄,再问行业。"
+        "每次只问一个问题,问完问题需要加一个?。"
+        "用户如果输入无关内容,请提醒用户先完成信息收集,不要回答无关问题。"
+        "用户如果拒绝回答(如‘不告诉你’),请礼貌提醒必须填写。"
+        "收集完毕后请总结结果。"
+       ),
+       storage=SqliteStorage(table_name="agent_sessions", db_file="D:/pythonai/ai_learning/agno_cache/data.db"),
+       add_history_to_messages=True,#是否自动把历史对话消息(chat history)添加到每次发送给大模型的 prompt 里。
+       num_history_runs=20,#这里设置为 20,表示每次和模型对话时,会把最近的 20 轮(你和 Agent 的来回)历史消息一并发给模型
+
+   )
+
+@app.get("/stream")
+async def stream(request: Request, prompt: str,session_id:str):
+       async def event_generator():
+           for chunk in agent.run(prompt, stream=True,session_id=session_id):
+               if await request.is_disconnected():
+                   break
+               if hasattr(chunk, "content") and chunk.content:
+                   yield {"data": chunk.content}
+       return EventSourceResponse(event_generator())

BIN
fastapi_demo/requirements.txt


+ 22 - 0
卢炳圻/fastapi/sse_client.py

@@ -0,0 +1,22 @@
+import requests
+import sseclient
+
+def stream_agent_response(prompt, session_id):
+    url = f"http://127.0.0.1:8000/stream?prompt={prompt}&session_id={session_id}"
+    # response = requests.get(url, stream=True)
+    client = sseclient.SSEClient(url) 
+    print("AI输出:", end="", flush=True)
+    for event in client:
+        print(event.data, end="", flush=True)
+        if "?" in event.data:
+            break
+
+if __name__ == "__main__":
+    # 示例:多轮对话
+    session_id = "user123"
+    while True:
+        user_input = input("你: ")
+        if user_input.strip().lower() in ["exit", "quit"]:
+            break
+        stream_agent_response(user_input, session_id)
+        print()  # 换行