chat2db调用ollama实现数据库的操纵。

打印 上一主题 下一主题

主题 1636|帖子 1636|积分 4910

只试了mysql的调用。

其它的我也不用,原来想充钱算了。最后一看单位是美刀。就放弃了这分心。于是折腾了一下。
本地运行chat2db 及chat2db ui

https://gitee.com/ooooinfo/Chat2DB
clone 后运行起来 chat2db的java端,我现在搞不清这一个项目是有没有链接到数据库里去。
在idea项目中运行


前端在:chat2db-client中。我的环境是 node 20 ,yarn , 留意大概需要 yarn add electron
直接运行:yarn start

安装ollama 以及模型 qwen2.5 这里我也不懂。不知装那一个好。

https://ollama.com/

在powershell下运行:ollama run qwen2.5 或 ollama pull qwen2.5
最终你要包管ollama启运。
仿一下openai的接口 调用ollama 提供给chat2db:

chat2db中如许设置,所以需要我本身写一个app.py 去做一下代理请求ollama,不是我不想写自定义,重要是总不乐成。不如直接仿openai .

app.py的部分代码。

我用的conda 创建的3.9的环境:
requirements.txt
  1. fastapi==0.104.1
  2. uvicorn==0.24.0
  3. httpx==0.25.1
  4. tenacity==8.2.3
  5. backoff
复制代码
相关的app.py的代码:
  1. from fastapi import FastAPI, HTTPException, Request, Depends
  2. from fastapi.middleware.cors import CORSMiddleware
  3. from fastapi.responses import JSONResponse, StreamingResponse
  4. import httpx
  5. import uvicorn
  6. import traceback
  7. import sys
  8. import time
  9. import json
  10. import asyncio
  11. import re
  12. import backoff  # 确保已安装 backoff 库
  13. app = FastAPI(
  14.     title="Ollama API Adapter",
  15.     description="An adapter for Ollama API that mimics OpenAI API format",
  16.     version="1.0.0"
  17. )
  18. app.add_middleware(
  19.     CORSMiddleware,
  20.     allow_origins=["*"],
  21.     allow_credentials=True,
  22.     allow_methods=["*"],
  23.     allow_headers=["*"],
  24. )
  25. API_KEY = "sk-123456"
  26. OLLAMA_BASE_URL = "http://127.0.0.1:11434"
  27. DEFAULT_MODEL = "qwen2.5:latest"
  28. def verify_api_key(request: Request):
  29.     authorization: str = request.headers.get('authorization')
  30.     if not authorization:
  31.         raise HTTPException(status_code=401, detail="Authorization header is missing.")
  32.     token_type, _, token = authorization.partition(' ')
  33.     if token_type.lower() != 'bearer' or token != API_KEY:
  34.         raise HTTPException(status_code=401, detail="Unauthorized: API Key is invalid or missing.")
  35. @app.get("/v1", dependencies=[Depends(verify_api_key)])
  36. async def root():
  37.     """
  38.     Root endpoint that returns API information
  39.     """
  40.     return {
  41.         "version": "1.0.0",
  42.         "status": "ok",
  43.         "endpoints": [
  44.             "/v1/chat/completions",
  45.             "/v1/models",
  46.             "/health"
  47.         ]
  48.     }
  49. @app.get("/v1/models", dependencies=[Depends(verify_api_key)])
  50. async def list_models():
  51.     """
  52.     List available models
  53.     """
  54.     try:
  55.         async with httpx.AsyncClient(timeout=10.0) as client:
  56.             response = await client.get(f"{OLLAMA_BASE_URL}/api/tags")
  57.             if response.status_code == 200:
  58.                 models = response.json().get("models", [])
  59.                 return {
  60.                     "data": [
  61.                         {
  62.                             "id": model["name"],
  63.                             "object": "model",
  64.                             "created": 0,
  65.                             "owned_by": "ollama"
  66.                         }
  67.                         for model in models
  68.                     ]
  69.                 }
  70.             else:
  71.                 raise HTTPException(status_code=503, detail="Ollama service unavailable")
  72.     except Exception as e:
  73.         print(f"Error listing models: {str(e)}")
  74.         raise HTTPException(status_code=503, detail=str(e))
  75. @app.get("/health", dependencies=[Depends(verify_api_key)])
  76. async def health_check():
  77.     """
  78.     健康检查接口
  79.     """
  80.     try:
  81.         async with httpx.AsyncClient(timeout=5.0) as client:
  82.             response = await client.get(f"{OLLAMA_BASE_URL}/api/tags")
  83.             if response.status_code == 200:
  84.                 print("Ollama service is healthy.")
  85.                 return {"status": "healthy", "message": "服务运行正常"}
  86.             else:
  87.                 print("Ollama service is not healthy.")
  88.                 raise HTTPException(status_code=503, detail="Ollama 服务不可用")
  89.     except httpx.HTTPStatusError as exc:
  90.         print(f"HTTP error occurred: {exc.response.status_code}")
  91.         raise HTTPException(status_code=exc.response.status_code, detail=str(exc))
  92.     except httpx.RequestError as exc:
  93.         print(f"An error occurred while requesting {exc.request.url!r}.")
  94.         raise HTTPException(status_code=500, detail=str(exc))
  95. async def generate_sse_response(content):
  96.     # 提取 SQL 语句并添加换行
  97.     sql_match = re.search(r'```sql\n(.*?)\n```', content, re.DOTALL)
  98.     sql = sql_match.group(1).strip() if sql_match else content
  99.    
  100.     # 添加换行符
  101.     formatted_content = f"{sql}\n"
  102.    
  103.     # 构造 OpenAI API 格式的响应
  104.     response_data = {
  105.         "id": f"chatcmpl-{int(time.time())}",
  106.         "object": "chat.completion.chunk",
  107.         "created": int(time.time()),
  108.         "model": "gpt-3.5-turbo",
  109.         "choices": [{
  110.             "delta": {
  111.                 "content": formatted_content  # 使用带换行的内容
  112.             },
  113.             "finish_reason": None,
  114.             "index": 0
  115.         }]
  116.     }
  117.    
  118.     # 发送主要内容
  119.     yield f"data: {json.dumps(response_data, ensure_ascii=False)}\n\n"
  120.    
  121.     # 发送结束消息
  122.     finish_response = {
  123.         "id": f"chatcmpl-{int(time.time())}",
  124.         "object": "chat.completion.chunk",
  125.         "created": int(time.time()),
  126.         "model": "gpt-3.5-turbo",
  127.         "choices": [{
  128.             "delta": {},
  129.             "finish_reason": "stop",
  130.             "index": 0
  131.         }]
  132.     }
  133.    
  134.     yield f"data: {json.dumps(finish_response, ensure_ascii=False)}\n\n"
  135.     yield "data: [DONE]\n\n"
  136. # 重试策略装饰器
  137. @backoff.on_exception(backoff.expo, httpx.ReadTimeout, max_tries=5, max_time=300)
  138. async def send_request(ollama_request):
  139.     timeout_config = httpx.Timeout(10.0, read=120.0)  # 连接超10秒,读取超时120秒
  140.     async with httpx.AsyncClient(timeout=timeout_config) as client:
  141.         try:
  142.             response = await client.post(
  143.                 f"{OLLAMA_BASE_URL}/api/chat",
  144.                 json=ollama_request
  145.             )
  146.             print(f"Response received with status {response.status_code}")
  147.             return response
  148.         except httpx.RequestError as exc:
  149.             print(f"An error occurred while requesting {exc.request.url!r}.")
  150.             raise HTTPException(status_code=500, detail=str(exc))
  151. @app.post("/v1/chat/completions", dependencies=[Depends(verify_api_key)])
  152. @app.post("/chat/completions", dependencies=[Depends(verify_api_key)])
  153. @app.post("/", dependencies=[Depends(verify_api_key)])
  154. async def chat_completions(request: Request):
  155.     try:
  156.         body = await request.json()
  157.         messages = body.get("messages", [])
  158.         stream = body.get("stream", True)
  159.         print(f"Received request with body: {body}")  # 使用 print 打印请求体
  160.         ollama_request = {
  161.             "model": DEFAULT_MODEL,
  162.             "messages": messages,
  163.             "stream": False
  164.         }
  165.         
  166.         response = await send_request(ollama_request)
  167.         print(f"Received response: {response.text}")  # 使用 print 打印响应文本
  168.         
  169.         if response.status_code != 200:
  170.             print(f"Failed to get response from model, status code: {response.status_code}")
  171.             raise HTTPException(status_code=400, detail="Failed to get response from model")
  172.         
  173.         ollama_response = response.json()
  174.         content = ollama_response.get("message", {}).get("content", "")
  175.         
  176.         print(f"Processed content: {content}")  # 使用 print 打印处理后的内容
  177.         if not stream:
  178.             result = {
  179.                 "id": f"chatcmpl-{int(time.time())}",
  180.                 "object": "chat.completion",
  181.                 "created": int(time.time()),
  182.                 "model": DEFAULT_MODEL,
  183.                 "choices": [{
  184.                     "message": {
  185.                         "role": "database developer and expert",
  186.                         "content": content
  187.                     },
  188.                     "finish_reason": "stop",
  189.                     "index": 0
  190.                 }]
  191.             }
  192.             print(f"Returning non-stream response: {result}")  # 使用 print 打印非流响应
  193.             return result
  194.         
  195.         headers = {
  196.             "Content-Type": "text/event-stream",
  197.             "Cache-Control": "no-cache",
  198.             "Connection": "keep-alive"
  199.         }
  200.         
  201.         return StreamingResponse(
  202.             generate_sse_response(content),
  203.             media_type="text/event-stream",
  204.             headers=headers
  205.         )
  206.         
  207.     except json.JSONDecodeError as e:
  208.         print(f"JSON decoding error: {str(e)}")
  209.         return JSONResponse(status_code=400, content={"message": "Invalid JSON data"})
  210.     except Exception as e:
  211.         print(f"Error during chat completions: {str(e)}")
  212.         print(traceback.format_exc())  # 使用 print 打印堆栈跟踪
  213.         return JSONResponse(
  214.             status_code=500,
  215.             content={"message": "Internal server error"}
  216.         )
  217.    
  218. if __name__ == "__main__":
  219.     print("Starting server on 0.0.0.0:8080")
  220.     uvicorn.run(app, host="0.0.0.0", port=8080)
复制代码
上面代码装key及model都写死,所以你一下要先下载下来相关的模型 。
python app.py

再留意以下本置:

在chat2db做好链接,再输入你的提示词。见下面结果:

响应速率几秒钟,当时看本身电脑响应速率了。都不费钱了,就不要什么自行车了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用多少眼泪才能让你相信

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表