Skip to content

Commit a0da81b

Browse files
committed
feat: mcp chat generate picture
1 parent 269f16a commit a0da81b

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ DOCKER_IMAGE_BACKEND=backend
2828
DOCKER_IMAGE_FRONTEND=frontend
2929

3030
MCP_IMAGE_PATH=/opt/sqlbot/images
31+
MCP_IMAGE_HOST=http://localhost:3000
32+
SERVER_IMAGE_HOST=https://sqlbot.fit2cloud.cn/images/

backend/apps/chat/task/llm.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import logging
2+
import traceback
23
import warnings
34
from typing import Any, List, Union, Dict
45

56
import numpy as np
67
import orjson
78
import pandas as pd
9+
import requests
810
from langchain_community.utilities import SQLDatabase
911
from langchain_core.language_models import BaseLLM
1012
from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AIMessage, AIMessageChunk
@@ -22,6 +24,7 @@
2224
from apps.db.db import exec_sql
2325
from apps.system.crud.user import get_user_info
2426
from apps.system.models.system_model import AiModelDetail
27+
from common.core.config import settings
2528
from common.core.deps import SessionDep, CurrentUser
2629

2730
warnings.filterwarnings("ignore")
@@ -68,8 +71,9 @@ def __init__(self, session: SessionDep, current_user: CurrentUser, chat_question
6871

6972
history_records: List[ChatRecord] = list(
7073
map(lambda x: ChatRecord(**x.model_dump()), filter(lambda r: True if r.first_chat != True else False,
71-
list_records(session=self.session, current_user=current_user,
72-
chart_id=chat_question.chat_id))))
74+
list_records(session=self.session,
75+
current_user=current_user,
76+
chart_id=chat_question.chat_id))))
7377
# get schema
7478
if ds:
7579
chat_question.db_schema = get_table_schema(session=self.session, ds=ds)
@@ -639,12 +643,49 @@ def run_task(llm_service: LLMService, session: SessionDep, in_chat: bool = True)
639643
else:
640644
# todo generate picture
641645
if chart['type'] != 'table':
642-
yield '# todo generate chart picture'
643-
644-
yield f'![{chart["type"]}](https://sqlbot.fit2cloud.cn/images/111.png)'
646+
yield '# generated chart picture'
647+
image_url = request_picture(llm_service.record.chat_id, llm_service.record.id, chart, result)
648+
print(image_url)
649+
yield f'![{chart["type"]}]({image_url})'
645650
except Exception as e:
651+
traceback.print_exc()
646652
llm_service.save_error(message=str(e))
647653
if in_chat:
648654
yield orjson.dumps({'content': str(e), 'type': 'error'}).decode() + '\n\n'
649655
else:
650656
yield f'> ❌ **ERROR**\n\n> \n\n> {str(e)}。'
657+
658+
659+
def request_picture(chat_id: int, record_id: int, chart: dict, data: dict):
660+
file_name = f'c_{chat_id}_r_{record_id}'
661+
662+
columns = chart.get('columns') if chart.get('columns') else []
663+
x = None
664+
y = None
665+
series = None
666+
if chart.get('axis'):
667+
x = chart.get('axis').get('x')
668+
y = chart.get('axis').get('y')
669+
series = chart.get('axis').get('series')
670+
671+
axis = []
672+
for v in columns:
673+
axis.append({'name': v.get('name'), 'value': v.get('value')})
674+
if x:
675+
axis.append({'name': x.get('name'), 'value': x.get('value'), 'type': 'x'})
676+
if y:
677+
axis.append({'name': y.get('name'), 'value': y.get('value'), 'type': 'y'})
678+
if series:
679+
axis.append({'name': series.get('name'), 'value': series.get('value'), 'type': 'series'})
680+
681+
request_obj = {
682+
"path": (settings.MCP_IMAGE_PATH if settings.MCP_IMAGE_PATH[-1] == '/' else (
683+
settings.MCP_IMAGE_PATH + '/')) + file_name,
684+
"type": chart['type'],
685+
"data": orjson.dumps(data.get('data') if data.get('data') else []).decode(),
686+
"axis": orjson.dumps(axis).decode(),
687+
}
688+
689+
requests.post(url=settings.MCP_IMAGE_HOST, json=request_obj)
690+
691+
return f'{(settings.SERVER_IMAGE_HOST if settings.SERVER_IMAGE_HOST[-1] == "/" else (settings.SERVER_IMAGE_HOST + "/"))}{file_name}.png'

backend/common/core/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def SQLALCHEMY_DATABASE_URI(self) -> PostgresDsn:
8080
EMAILS_FROM_EMAIL: EmailStr | None = None
8181
EMAILS_FROM_NAME: EmailStr | None = None
8282
MCP_IMAGE_PATH: str
83+
MCP_IMAGE_HOST: str
84+
SERVER_IMAGE_HOST: str
8385

8486
@model_validator(mode="after")
8587
def _set_default_emails_from(self) -> Self:

0 commit comments

Comments
 (0)