使用Postman访问siliconflow大模型接口

一 获取密钥

注册硅基流动:https://www.siliconflow.cn/

登录控制台后,在左侧的API 密钥菜单中新建API密钥。

该API密钥可用作请求的token,下文会用到。

二 挑选模型并查看文档

在模型广场挑选自己喜欢的模型,不同的模型价格不同。

从上图中可以看到deepseek 的7B模型为免费。点击该模型,右侧会有弹窗:

在这里可以复制模型名,并查看API文档。

API文档是通用文档,并非针对该模型。这里给出的是一个对话请求文档,重点在右上角:

curl --request POST \
  --url https://api.siliconflow.cn/v1/chat/completions \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "Qwen/QwQ-32B",
  "messages": [
    {
      "role": "user",
      "content": "What opportunities and challenges will the Chinese large model industry face in 2025?"
    }
  ]
}'

从这里可知:

  • 请求类型为POST。

  • 请求url为:https://api.siliconflow.cn/v1/chat/completions

  • header上要附加两个字段:

    • Authorization: Bearer <token>(<token>即为上文中创建的API密钥)

    • Content-Type: application/json

  • body中传入json参数:

    {
      "model": "模型名",
      "messages": [
        {
          "role": "user",
          "content": "提示词"
        }
      ]
    }

    三 使用Postman请求

    打开Postman,创建一个post请求,按如上格式拼接请求内容并发送,即可看到大模型的返回:

    INFO: 127.0.0.1:58952 - "POST /query HTTP/1.1" 422 Unprocessable Entity 代码: from fastapi import FastAPI, HTTPException, BackgroundTasks from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from pydantic import BaseModel, Field from typing import List, Dict, Any, Optional import asyncio import logging import os import time # 添加time模块导入 import uuid # 添加uuid模块导入 from dotenv import load_dotenv import uvicorn from contextlib import asynccontextmanager # 在导入其他模块之前先加载环境变量 load_dotenv() # 导入RAG系统 from rag_main import RAGSystem, RAGConfig # 导入TTS服务 from text_to_speech import tts_service # 添加TTS服务导入 # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # 全局RAG系统实例 rag_system: Optional[RAGSystem] = None # Pydantic模型定义 class ImageData(BaseModel): """图片数据模型""" name: str = Field(..., description="图片文件名") data: str = Field(..., description="图片base64数据") class QueryRequest(BaseModel): """查询请求模型""" question: str = Field(..., description="用户问题", min_length=1, max_length=1000) include_history: bool = Field(True, description="是否包含对话历史") images: List[ImageData] = Field(default=[], description="上传的图片列表") user_id: Optional[str] = Field(None, description="用户ID") conversation_history: List[Dict[str, Any]] = Field(default=[], description="对话历史") class BatchQueryRequest(BaseModel): """批量查询请求模型""" questions: List[str] = Field(..., description="问题列表", min_items=1, max_items=10) class QueryResponse(BaseModel): """查询响应模型""" success: bool question: Optional[str] = None answer: Optional[str] = None sources: List[Dict[str, Any]] = [] context_used: Optional[int] = None retrieval_results: Optional[int] = None timing: Optional[Dict[str, float]] = None model_info: Optional[Dict[str, Any]] = None error: Optional[str] = None images: Optional[list] = [] # 新增此行,支持图片多模态返回 class SystemStatus(BaseModel): """系统状态模型""" initialized: bool chat_history_length: int files_exist: Dict[str, bool] config: Dict[str, Any] class ConfigUpdateRequest(BaseModel): """配置更新请求模型""" chunk_size: Optional[int] = Field(None, ge=100, le=2048) chunk_overlap: Optional[int] = Field(None, ge=0, le=500) retrieval_top_k: Optional[int] = Field(None, ge=1, le=50) final_top_k: Optional[int] = Field(None, ge=1, le=20) temperature: Optional[float] = Field(None, ge=0.0, le=2.0) max_tokens: Optional[int] = Field(None, ge=100, le=4096) enable_reranking: Optional[bool] = None enable_safety_check: Optional[bool] = None # 应用生命周期管理 @asynccontextmanager async def lifespan(app: FastAPI): """应用启动和关闭时的生命周期管理""" # 启动时初始化RAG系统 global rag_system try: logger.info("🚀 正在初始化RAG系统...") # 环境变量已经在模块级别加载了,这里不需要再次加载 # load_dotenv() # 删除这行 # 获取API密钥 siliconflow_api_key = os.getenv("SILICONFLOW_API_KEY") volcengine_api_key = os.getenv("VOLCENGINE_API_KEY") if not siliconflow_api_key: raise ValueError("未找到SILICONFLOW_API_KEY环境变量") if not volcengine_api_key: raise ValueError("未找到VOLCENGINE_API_KEY环境变量") # 创建配置 config = RAGConfig( api_key=siliconflow_api_key, volcengine_api_key=volcengine_api_key, document_path="招股说明书1.pdf", output_dir="./", chunk_size=384, chunk_overlap=48, retrieval_top_k=20, final_top_k=8, enable_safety_check=False ) # 初始化RAG系统 rag_system = RAGSystem(config) if not await rag_system.initialize(): raise RuntimeError("RAG系统初始化失败") # 处理文档 if not await rag_system.process_document(): raise RuntimeError("文档处理失败") logger.info("✅ RAG系统初始化成功") except Exception as e: logger.error(f"❌ RAG系统初始化失败: {e}") rag_system = None raise yield # 关闭时清理资源 logger.info("🔄 正在关闭RAG系统...") rag_system = None # 创建FastAPI应用 app = FastAPI( title="RAG智能问答API", description="基于检索增强生成(RAG)的智能问答系统API", version="1.0.0", lifespan=lifespan ) # 添加CORS中间件 app.add_middleware( CORSMiddleware, allow_origins=["*"], # 生产环境中应该限制具体域名 allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 辅助函数 def check_system_ready(): """检查系统是否就绪""" if rag_system is None or not rag_system.is_initialized: raise HTTPException( status_code=503, detail="RAG系统未初始化或不可用,请稍后重试" ) # API路由定义 @app.get("/", summary="根路径", description="API根路径,返回欢迎信息") async def root(): """根路径""" return { "message": "欢迎使用RAG智能问答API", "version": "1.0.0", "docs": "/docs", "status": "/status" } @app.get("/health", summary="健康检查", description="检查API服务健康状态") async def health_check(): """健康检查""" return { "status": "healthy", "rag_system_ready": rag_system is not None and rag_system.is_initialized } @app.get("/status", response_model=SystemStatus, summary="系统状态", description="获取RAG系统详细状态") async def get_system_status(): """获取系统状态""" check_system_ready() status = rag_system.get_system_status() return SystemStatus(**status) # 在现有的Pydantic模型定义后添加 class ImageDescriptionRequest(BaseModel): """图片描述请求模型""" images: List[ImageData] = Field(..., description="要描述的图片列表", min_items=1) detailed: bool = Field(True, description="是否生成详细描述") class ImageDescriptionResponse(BaseModel): """图片描述响应模型""" success: bool descriptions: List[Dict[str, str]] = [] total_images: int processing_time: Optional[float] = None error: Optional[str] = None # 在现有的API端点后添加新的图片描述端点 @app.post("/describe_image", response_model=ImageDescriptionResponse, summary="图片描述", description="上传图片并获取AI生成的详细描述") async def describe_images(request: ImageDescriptionRequest): """图片描述接口 - 专门用于处理用户上传的图片""" import time start_time = time.time() try: from image_captioning import describe_image import base64 descriptions = [] for img in request.images: try: # 提取base64数据 if img.data.startswith('data:image/'): base64_data = img.data.split(',')[1] else: base64_data = img.data # 获取图片格式 img_format = img.name.split('.')[-1].lower() if '.' in img.name else 'png' # 生成图片描述 description = describe_image(base64_data, img_format) descriptions.append({ "image_name": img.name, "description": description, "status": "success" }) logger.info(f"✓ 成功描述图片: {img.name}") except Exception as e: logger.error(f"处理图片 {img.name} 失败: {e}") descriptions.append({ "image_name": img.name, "description": f"无法生成描述: {str(e)}", "status": "error" }) processing_time = time.time() - start_time return ImageDescriptionResponse( success=True, descriptions=descriptions, total_images=len(request.images), processing_time=processing_time ) except Exception as e: logger.error(f"图片描述处理异常: {e}") return ImageDescriptionResponse( success=False, descriptions=[], total_images=len(request.images), error=str(e) ) # 修改现有的query_rag函数,增强图片处理逻辑 @app.post("/query", response_model=QueryResponse, summary="智能问答", description="提交问题并获取AI回答") async def query_rag(request: QueryRequest): """智能问答接口""" check_system_ready() try: # 处理图片描述 image_descriptions = [] if request.images: from image_captioning import describe_image import base64 for img in request.images: try: # 添加日志以检查 img.data 和 img.name 的值 logger.info(f"处理图片: 名称={img.name}, 数据前100字符={img.data[:100]}") # 提取base64数据 if img.data.startswith('data:image/'): base64_data = img.data.split(',')[1] else: base64_data = img.data # 获取图片格式 img_format = img.name.split('.')[-1].lower() if '.' in img.name else 'png' # 生成图片描述 description = describe_image(base64_data, img_format) image_descriptions.append(f"图片 {img.name}: {description}") logger.info(f"✓ 成功处理图片: {img.name}") except Exception as e: logger.error(f"处理图片 {img.name} 失败: {e}") image_descriptions.append(f"图片 {img.name}: 无法生成描述") # 判断是否为纯图片查询(没有文字问题或问题很简单) is_image_only_query = ( request.images and (not request.question.strip() or request.question.strip().lower() in ['这是什么', '描述一下', '看看这个', '这个图片', '图片内容']) ) if is_image_only_query and image_descriptions: # 纯图片查询,直接返回图片描述 answer = "根据您上传的图片,我看到:\n\n" + "\n\n".join(image_descriptions) # 在 query_rag 方法中,构建 images 列表 images = [] for idx, img in enumerate(request.images): images.append({ "url": f"/images/{img.name}", "description": image_descriptions[idx] if idx < len(image_descriptions) else "" }) # 在 QueryResponse 返回时加入 images 字段 return QueryResponse( success=True, question=request.question, answer=answer, sources=[], images=images, context_used=0, retrieval_results=0, timing={"total_time": 0.1}, model_info={"type": "image_description_only"} ) # 构建完整问题(包含图片描述) full_question = request.question if image_descriptions: full_question += "\n\n上传的图片信息:\n" + "\n".join(image_descriptions) # 调用RAG系统 result = await rag_system.query( user_question=full_question, include_history=request.include_history ) # 保存图片描述到对话历史 if image_descriptions: result['image_descriptions'] = image_descriptions return QueryResponse(**result) except Exception as e: logger.error(f"查询处理异常: {e}") raise HTTPException( status_code=500, detail=f"查询处理失败: {str(e)}" ) @app.post("/batch_query", response_model=List[QueryResponse], summary="批量问答", description="批量提交问题并获取AI回答") async def batch_query_rag(request: BatchQueryRequest): """批量查询接口""" check_system_ready() try: results = await rag_system.batch_query(request.questions) return [QueryResponse(**result) for result in results] except Exception as e: logger.error(f"批量查询处理异常: {e}") raise HTTPException( status_code=500, detail=f"批量查询处理失败: {str(e)}" ) @app.post("/clear_history", summary="清空历史", description="清空对话历史记录") async def clear_chat_history(): """清空对话历史""" check_system_ready() try: rag_system.clear_history() return {"success": True, "message": "对话历史已清空"} except Exception as e: logger.error(f"清空历史异常: {e}") raise HTTPException( status_code=500, detail=f"清空历史失败: {str(e)}" ) @app.post("/reprocess_document", summary="重新处理文档", description="强制重新处理文档") async def reprocess_document(background_tasks: BackgroundTasks): """重新处理文档""" check_system_ready() async def process_task(): try: await rag_system.process_document(force_reprocess=True) logger.info("文档重新处理完成") except Exception as e: logger.error(f"文档重新处理失败: {e}") background_tasks.add_task(process_task) return {"success": True, "message": "文档重新处理任务已启动,请稍后查看状态"} @app.get("/config", summary="获取配置", description="获取当前系统配置") async def get_config(): """获取当前配置""" check_system_ready() config = rag_system.config return { "embedding_model": config.embedding_model, "chunk_size": config.chunk_size, "chunk_overlap": config.chunk_overlap, "retrieval_top_k": config.retrieval_top_k, "final_top_k": config.final_top_k, "generation_model": config.generation_model, "temperature": config.temperature, "max_tokens": config.max_tokens, "enable_reranking": config.enable_reranking, "enable_safety_check": config.enable_safety_check } @app.put("/config", summary="更新配置", description="更新系统配置参数") async def update_config(request: ConfigUpdateRequest): """更新配置""" check_system_ready() try: config = rag_system.config updated_fields = [] # 更新配置字段 if request.chunk_size is not None: config.chunk_size = request.chunk_size updated_fields.append("chunk_size") if request.chunk_overlap is not None: config.chunk_overlap = request.chunk_overlap updated_fields.append("chunk_overlap") if request.retrieval_top_k is not None: config.retrieval_top_k = request.retrieval_top_k updated_fields.append("retrieval_top_k") if request.final_top_k is not None: config.final_top_k = request.final_top_k updated_fields.append("final_top_k") if request.temperature is not None: config.temperature = request.temperature updated_fields.append("temperature") if request.max_tokens is not None: config.max_tokens = request.max_tokens updated_fields.append("max_tokens") if request.enable_reranking is not None: config.enable_reranking = request.enable_reranking updated_fields.append("enable_reranking") if request.enable_safety_check is not None: config.enable_safety_check = request.enable_safety_check updated_fields.append("enable_safety_check") return { "success": True, "message": f"配置已更新: {', '.join(updated_fields)}", "updated_fields": updated_fields } except Exception as e: logger.error(f"配置更新异常: {e}") raise HTTPException( status_code=500, detail=f"配置更新失败: {str(e)}" ) # 错误处理 @app.exception_handler(Exception) async def global_exception_handler(request, exc): """全局异常处理""" logger.error(f"未处理的异常: {exc}") if isinstance(exc, HTTPException): return JSONResponse(status_code=exc.status_code, content={ "success": False, "error": exc.detail }) return { "success": False, "error": "服务器内部错误", "detail": str(exc) } # 主函数 import os if __name__ == "__main__": # 开发环境启用重载,生产环境禁用 reload_mode = os.getenv("UVICORN_RELOAD", "true").lower() == "true" uvicorn.run( "rag_api:app", host="0.0.0.0", port=8000, reload=reload_mode, log_level="info" ) from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles # 添加静态文件服务 app.mount("/images", StaticFiles(directory="images"), name="images") @app.get("/image/{image_name}") async def get_image(image_name: str): """获取图片文件""" image_path = os.path.join("images", image_name) if os.path.exists(image_path): return FileResponse(image_path) else: raise HTTPException(status_code=404, detail="图片未找到") from speech_to_text import process_speech_to_text from fastapi import UploadFile, File # 添加语音转文字接口 @app.post("/speech-to-text") async def speech_to_text(audio_file: UploadFile = File(...)): """语音转文字接口""" try: # 验证文件类型 if not audio_file.content_type.startswith('audio/'): raise HTTPException(status_code=400, detail="请上传音频文件") # 处理语音转文字 result = await process_speech_to_text(audio_file) return JSONResponse(content=result) except Exception as e: logger.error(f"语音转文字API错误: {e}") raise HTTPException(status_code=500, detail=str(e)) @app.post("/voice-query") async def voice_query(audio_file: UploadFile = File(...)): """语音查询接口:语音转文字 + RAG查询""" try: # 1. 语音转文字 speech_result = await process_speech_to_text(audio_file) if not speech_result["success"]: return JSONResponse(content=speech_result) transcribed_text = speech_result["transcribed_text"] # 添加调试日志 logger.info(f"原始转录结果: {speech_result['transcribed_text']}") logger.info(f"转录文本类型: {type(transcribed_text)}") # 如果转录结果是列表格式,需要提取文本 if isinstance(transcribed_text, list) and len(transcribed_text) > 0: if isinstance(transcribed_text[0], dict) and 'text' in transcribed_text[0]: transcribed_text = transcribed_text[0]['text'] elif isinstance(transcribed_text[0], str): transcribed_text = transcribed_text[0] logger.info(f"处理后的查询文本: {transcribed_text}") # 2. 使用转录文本进行RAG查询 if hasattr(rag_system, 'query_with_images'): query_result = await rag_system.query_with_images(transcribed_text) else: query_result = await rag_system.query(transcribed_text) # 3. 返回完整结果 return JSONResponse(content={ "success": True, "transcribed_text": transcribed_text, "audio_file_path": speech_result["audio_file_path"], "answer": query_result["answer"], "sources": query_result["sources"], "images": query_result.get("images", []), "processing_time": query_result.get("timing", {}).get("total_time", 0) }) except Exception as e: logger.error(f"语音查询API错误: {e}") @app.post("/query-with-tts") async def query_with_tts(request: QueryRequest): """ 智能问答并返回TTS音频 """ check_system_ready() try: start_time = time.time() # 执行RAG查询 result = await rag_system.query( user_question=request.question, include_history=request.include_history ) if not result.get('success', False): raise HTTPException(status_code=500, detail=result.get('error', '查询失败')) answer_text = result.get('answer', '') # 尝试生成TTS音频(增强错误处理) try: # 检查方法是否存在 if hasattr(tts_service, 'text_to_speech'): audio_data = tts_service.text_to_speech(answer_text) elif hasattr(tts_service, 'text_to_speech_stream'): # 使用流式方法作为备选 audio_stream = tts_service.text_to_speech_stream(answer_text) if audio_stream: # 处理流式数据 audio_data = b''.join(audio_stream) else: audio_data = None else: logger.error("No available TTS method found") audio_data = None except Exception as e: logger.error(f"TTS service error: {str(e)}") audio_data = None if audio_data: # 创建临时文件保存音频 audio_filename = f"audio_{uuid.uuid4().hex}.wav" audio_path = os.path.join("audio_files", audio_filename) # 确保audio_files目录存在 os.makedirs("audio_files", exist_ok=True) # 保存音频文件 if tts_service.save_audio_to_file(audio_data, audio_path): result['audio_file'] = audio_filename result['audio_url'] = f"/audio/{audio_filename}" logger.info(f"✓ TTS音频生成成功: {audio_filename}") else: logger.warning("音频文件保存失败") result['tts_error'] = "音频文件保存失败" else: logger.warning("TTS转换失败") result['tts_error'] = "TTS转换失败" processing_time = time.time() - start_time result['processing_time'] = processing_time return QueryResponse(**result) except HTTPException: raise except Exception as e: logger.error(f"Query with TTS error: {str(e)}") raise HTTPException(status_code=500, detail=f"查询失败: {str(e)}") # 添加音频文件服务端点 @app.get("/audio/{audio_filename}") async def get_audio(audio_filename: str): """ 获取生成的音频文件 """ audio_path = os.path.join("audio_files", audio_filename) if not os.path.exists(audio_path): raise HTTPException(status_code=404, detail="音频文件不存在") return FileResponse( audio_path, media_type="audio/wav", filename=audio_filename ) # 添加TTS独立端点 @app.post("/text-to-speech") async def text_to_speech_endpoint(text: str, voice: str = "Cherry"): """ 独立的文字转语音端点 """ try: audio_data = tts_service.text_to_speech_stream(text, voice) if not audio_data: raise HTTPException(status_code=500, detail="TTS转换失败") # 创建临时文件 audio_filename = f"tts_{uuid.uuid4().hex}.wav" audio_path = os.path.join("audio_files", audio_filename) # 确保目录存在 os.makedirs("audio_files", exist_ok=True) # 保存音频文件 if tts_service.save_audio_to_file(audio_data, audio_path): return { "success": True, "audio_file": audio_filename, "audio_url": f"/audio/{audio_filename}" } else: raise HTTPException(status_code=500, detail="音频文件保存失败") except Exception as e: logger.error(f"TTS endpoint error: {str(e)}") raise HTTPException(status_code=500, detail=f"TTS转换失败: {str(e)}") def build_multimodal_answer(answer_text, images): multimodal_part = "" for idx, img in enumerate(images, 1): multimodal_part += f"如图{idx}所示:{img['description']}\n【图片{idx}:{img['url']}, {img['description']}】\n" return answer_text + "\n" + multimodal_part if images else answer_text 检查代码错误
    08-22
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值