Compare commits
7 Commits
651eecf50f
...
dev_graph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
655a3cd41f | ||
|
|
e767a9ecaa | ||
|
|
721ea07652 | ||
|
|
a2309606bf | ||
|
|
35da349712 | ||
|
|
4e4941d5d4 | ||
|
|
b98faab961 |
@@ -3,7 +3,7 @@ WORKDIR /app
|
||||
COPY . /app
|
||||
ENV TZ=Asia/Shanghai \
|
||||
LANG=C.UTF-8
|
||||
RUN rm -rf logs .git .idea .venv && apt-get update && apt-get install -y vim curl openssl libssl-dev && pip install -r requirement.txt -i https://mirrors.aliyun.com/pypi/simple/
|
||||
RUN rm -rf logs .git .idea .venv && apt-get update && apt-get install -y vim curl openssl libssl-dev sqlite3 && pip install -r requirement.txt -i https://mirrors.aliyun.com/pypi/simple/
|
||||
RUN mkdir -p /app/logs && touch /app/logs/sqlbot.log && rm -rf *.whl
|
||||
EXPOSE 8084
|
||||
CMD ["python","main_service.py"]
|
||||
|
||||
@@ -12,9 +12,9 @@ from decouple import config
|
||||
from template.template import get_base_template
|
||||
from util.utils import extract_nested_json, check_and_get_sql, get_chart_type_from_sql_answer
|
||||
from datetime import datetime
|
||||
from util import train_ddl,utils
|
||||
|
||||
from util import train_ddl, utils
|
||||
|
||||
from util.pre_question_answer import merged_dict
|
||||
|
||||
gen_history_llm = ChatOpenAI(
|
||||
model=config('CHAT_MODEL_NAME', default=''),
|
||||
@@ -37,6 +37,8 @@ gen_sql_llm = ChatOpenAI(
|
||||
'''
|
||||
用于生成sql,生成图表的agent,上下文
|
||||
'''
|
||||
|
||||
|
||||
class SqlAgentState(TypedDict):
|
||||
user_question: str
|
||||
rewritten_user_question: Optional[str]
|
||||
@@ -52,9 +54,13 @@ class SqlAgentState(TypedDict):
|
||||
|
||||
sql_retry_count: int
|
||||
chart_retry_count: int
|
||||
|
||||
|
||||
'''
|
||||
基于上下文,历史消息,重写用户问题
|
||||
'''
|
||||
|
||||
|
||||
def _rewrite_user_question(state: SqlAgentState) -> dict:
|
||||
logger.info(f"user:{state.get('user_id', '1')} ---------------进入 _rewrite_user_question 节点---------------")
|
||||
user_question = state['user_question']
|
||||
@@ -76,6 +82,17 @@ def _gen_sql(state: SqlAgentState) -> dict:
|
||||
logger.info(f"user:{state.get('user_id', '1')} ---------------进入 _gen_sql 节点---------------")
|
||||
question = state.get('rewritten_user_question', state['user_question'])
|
||||
service = vn
|
||||
|
||||
# 预制问题-答案,后期如模型效果好,可以考虑删除
|
||||
if state.get('user_question', '') in merged_dict.keys():
|
||||
logger.info(f"预制问题-答案-】-{state.get('user_question', '')}-hit")
|
||||
r = merged_dict[state.get('user_question', '')]
|
||||
r['success'] = True
|
||||
return {'gen_sql_result': r, "sql_retry_count": 0, "gen_sql_error": ""}
|
||||
if state.get('rewritten_user_question', '') in merged_dict.keys():
|
||||
r = merged_dict[state.get('rewritten_user_question', '')]
|
||||
r['success'] = True
|
||||
return {'gen_sql_result': r, "sql_retry_count": 0, "gen_sql_error": ""}
|
||||
question_sql_list = service.get_similar_question_sql(question)
|
||||
if question_sql_list and len(question_sql_list) > 3:
|
||||
question_sql_list = question_sql_list[:3]
|
||||
@@ -97,7 +114,7 @@ def _gen_sql(state: SqlAgentState) -> dict:
|
||||
logger.info(f"gensql result: {result}")
|
||||
result = orjson.loads(result)
|
||||
retry = state.get("sql_retry_count", 0) + 1
|
||||
return {'gen_sql_result': result, "sql_retry_count": retry,"gen_sql_error":""}
|
||||
return {'gen_sql_result': result, "sql_retry_count": retry, "gen_sql_error": ""}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@@ -122,7 +139,8 @@ def _gen_chart(state: SqlAgentState) -> dict:
|
||||
[{'role': 'system', 'content': sys_char_temp}, {'role': 'user', 'content': user_char_temp}]).text()
|
||||
rr = utils.remove_think_tags(rr)
|
||||
retry = state.get("chart_retry_count", 0) + 1
|
||||
return {"chart_retry_count": retry, 'gen_chart_result': orjson.loads(extract_nested_json(rr)),"gen_chart_error":""}
|
||||
return {"chart_retry_count": retry, 'gen_chart_result': orjson.loads(extract_nested_json(rr)),
|
||||
"gen_chart_error": ""}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
@@ -183,4 +201,4 @@ memory = MemorySaver()
|
||||
sql_chart_agent = workflow.compile(checkpointer=memory)
|
||||
# png_data=sql_chart_agent .get_graph().draw_mermaid_png()
|
||||
# with open("D://graph.png", "wb") as f:
|
||||
# f.write(png_data)
|
||||
# f.write(png_data)
|
||||
|
||||
@@ -320,8 +320,8 @@ def update_question_feed_back():
|
||||
update_user_feedBack(id, '', user_feedback)
|
||||
return jsonify({"type": "success"})
|
||||
except Exception as e:
|
||||
logger.error(f"查询预制问题失败 failed:{e}")
|
||||
return jsonify({"type": "error", "error": f'查询预制问题失败:{str(e)}'})
|
||||
logger.error(f"保存问题反馈失败 failed:{e}")
|
||||
return jsonify({"type": "error", "error": f'保存问题反馈失败:{str(e)}'})
|
||||
|
||||
|
||||
@app.flask_app.route("/yj_sqlbot/api/v0/gen_graph_question", methods=["GET"])
|
||||
@@ -383,8 +383,9 @@ def gen_graph_question():
|
||||
return jsonify(data)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
logger.error(f"查询预制问题失败 failed:{e}")
|
||||
return jsonify({"type": "error", "error": f'查询预制问题失败:{str(e)}'})
|
||||
logger.error(f"sql及图表生成环节异常 failed:{str(e)}")
|
||||
update_conversation(id=id, answer={'type_error': 'error', 'error':f'sql及图表生成环节异常:{str(e)}' })
|
||||
return jsonify({"type": "error", "error": f'sql及图表生成环节异常:{str(e)}'})
|
||||
|
||||
|
||||
@app.flask_app.route("/yj_sqlbot/api/v0/run_sql_3", methods=["GET"])
|
||||
@@ -438,9 +439,9 @@ def run_sql_3():
|
||||
summary = rr.get('summary', '')
|
||||
run_sql_error = rr.get('run_sql_error', '')
|
||||
logger.debug(f"data type is {type(data)} data is {data} summary is {summary}")
|
||||
if data and not run_sql_error:
|
||||
if not run_sql_error:
|
||||
update_conversation(id=id, answer={'data': data,'summary':summary})
|
||||
elif run_sql_error:
|
||||
else:
|
||||
update_conversation(id=id, answer={'type_error':'error','error':"sql执行失败"})
|
||||
logger.info(f"run_Sql finish run_sql_error => {run_sql_error}")
|
||||
return jsonify(
|
||||
@@ -452,7 +453,8 @@ def run_sql_3():
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"run sql failed:{e}")
|
||||
return jsonify({"type": "sql_error", "error": str(e)})
|
||||
update_conversation(id=id, answer={'type_error': 'error', 'error': f'run sql环节异常 {str(e)}'})
|
||||
return jsonify({"type": "sql_error", "error":f'run sql环节异常 {str(e)}'})
|
||||
|
||||
|
||||
@app.flask_app.route("/yj_sqlbot/api/v0/get_history", methods=["GET"])
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
import pandas as pd
|
||||
from db_util.db_main import Conversation, SqliteSqlalchemy
|
||||
import logging
|
||||
from util.utils import custom_json_serializer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -72,11 +72,27 @@ def update_conversation(id: str, sql=None, question=None, chart_cfg=None, meta=N
|
||||
meta = json.dumps(meta, ensure_ascii=False)
|
||||
update_data['meta'] = meta
|
||||
if answer is not None:
|
||||
if isinstance(answer, dict):
|
||||
logger.info("answer dict")
|
||||
answer_df = pd.DataFrame(answer)
|
||||
answer = answer_df.to_json(orient='records', date_format='iso', force_ascii=False)
|
||||
# answer = json.dumps(answer, ensure_ascii=False)
|
||||
if isinstance(answer, (dict, list)):
|
||||
# 直接使用JSON序列化,避免DataFrame转换
|
||||
try:
|
||||
logger.info("json序列化")
|
||||
answer = json.dumps(answer, ensure_ascii=False, default=custom_json_serializer)
|
||||
logger.info(f"answer JSON: {answer}")
|
||||
except Exception as e:
|
||||
logger.error(f"JSON序列化失败,字符串化: {e}")
|
||||
answer = str(answer)
|
||||
else:
|
||||
logger.info("其他类型直接转换为字符串")
|
||||
answer = str(answer)
|
||||
# if isinstance(answer, dict):
|
||||
# logger.info("answer dict")
|
||||
# answer_df = pd.DataFrame(answer)
|
||||
# # answer_df = answer_df[0]
|
||||
# answer = answer_df.to_json(orient='records', date_format='iso', force_ascii=False)
|
||||
# answer = answer.rstrip(']')
|
||||
# answer = answer.lstrip('[')
|
||||
# logger.info(f"answer {answer}")
|
||||
# # answer = json.dumps(answer, ensure_ascii=False)
|
||||
update_data['answer'] = answer
|
||||
if update_data:
|
||||
result = session.query(Conversation).filter(Conversation.id == id).update(update_data)
|
||||
|
||||
@@ -492,8 +492,8 @@ class CustomQdrant_VectorStore(Qdrant_VectorStore):
|
||||
request_body = {
|
||||
"model": self.embedding_model_name,
|
||||
"encoding_format": "float",
|
||||
# "input": [data],
|
||||
"sentences":[data]
|
||||
"input": [data],
|
||||
#"sentences":[data]
|
||||
}
|
||||
#硅基流动的beg3
|
||||
# request_body = {
|
||||
@@ -510,27 +510,23 @@ class CustomQdrant_VectorStore(Qdrant_VectorStore):
|
||||
# logger.info(f"request_body:{request_body}")
|
||||
request_body.update(kwargs)
|
||||
#AI中台的beg3
|
||||
response = requests.post(
|
||||
url=f"{self.embedding_api_base}",
|
||||
json=request_body,
|
||||
headers={"Authorization": f"Bearer {self.embedding_api_key}", 'Content-Type': 'application/json'},
|
||||
)
|
||||
|
||||
#硅基流动的
|
||||
# response = requests.post(
|
||||
# url=f"{self.embedding_api_base}/v1/embeddings",
|
||||
# json=request_body,
|
||||
# headers={"Authorization": f"Bearer {self.embedding_api_key}", 'Content-Type': 'application/json'},
|
||||
# )
|
||||
response = requests.post(
|
||||
url=f"{self.embedding_api_base}/v1/embeddings",
|
||||
json=request_body,
|
||||
headers={"Authorization": f"Bearer {self.embedding_api_key}", 'Content-Type': 'application/json'},
|
||||
)
|
||||
if response.status_code != 200:
|
||||
raise RuntimeError(
|
||||
f"Failed to create the embeddings, detail: {_get_error_string(response)}"
|
||||
)
|
||||
result = response.json()
|
||||
# logger.info("embedding result:{0}".format(result))
|
||||
embeddings = result['embeddings']
|
||||
# embeddings = result['data'][0]['embedding']
|
||||
return embeddings[0]
|
||||
# return embeddings
|
||||
#embeddings = result['embeddings']
|
||||
embeddings = result['data'][0]['embedding']
|
||||
#return embeddings[0]
|
||||
return embeddings
|
||||
|
||||
class CustomVanna(CustomQdrant_VectorStore, OpenAICompatibleLLM):
|
||||
def __init__(self, llm_config=None, vector_store_config=None):
|
||||
|
||||
@@ -75,7 +75,6 @@ template:
|
||||
</rule>
|
||||
<rule>
|
||||
<rule-title>术语标准化规则</rule-title>
|
||||
|
||||
<rule-detail>
|
||||
数信中心和数信部都是部门,而非单位
|
||||
</rule-detail>
|
||||
@@ -86,7 +85,15 @@ template:
|
||||
internal_dept和internal_unit的字段值是内部部门和内部单位编号,而非名称,涉及内部单位或部门时需要在部门表中递归查询
|
||||
例如:"internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START WITH ("name" || "shortname") LIKE '%数信中心%' AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%' CONNECT BY PRIOR "id" = "parentid")
|
||||
</rule-detail>
|
||||
|
||||
<rule-detail>
|
||||
时间范围参考
|
||||
上午 (Morning): 06:00:00 - 11:59:59
|
||||
中午 (Noon): 12:00:00 - 13:59:59
|
||||
下午 (Afternoon): 14:00:00 - 17:59:59
|
||||
傍晚 (Evening): 18:00:00 - 19:59:59
|
||||
晚上 (Night): 20:00:00 - 23:59:59
|
||||
深夜 (Late Night): 00:00:00 - 05:59:59
|
||||
</rule-detail>
|
||||
</rule>
|
||||
<rule>
|
||||
<rule-title>聚合与计算</rule-title>
|
||||
@@ -565,6 +572,7 @@ template:
|
||||
|---|---|---|
|
||||
| 数信部 | 数字信息部 | 如果匹配,则替换 |
|
||||
| 安质部 | 安全质量部 | 如果匹配,则替换 |
|
||||
| 南网 | 南方电网 | 如果匹配,则替换 |
|
||||
|
||||
|
||||
# 输出格式要求
|
||||
|
||||
224
util/pre_question_answer.py
Normal file
224
util/pre_question_answer.py
Normal file
@@ -0,0 +1,224 @@
|
||||
q_a = {
|
||||
"数信部上周有哪些人加班": {'sql': '''
|
||||
SELECT DISTINCT p."id" AS "id",
|
||||
p."code" AS "工号",
|
||||
p."name" AS "姓名",
|
||||
p."work_unit" AS "工作单位",
|
||||
CASE WHEN ps."status" = '1008' THEN '加班' ELSE '其他' END AS "状态"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
JOIN "YJOA_APPSERVICE_DB"."t_yj_person_status" ps
|
||||
ON p."code" = ps."person_id"
|
||||
JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" || "shortname" LIKE '%数字信息部%') AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
AND p."dr" = 0
|
||||
AND ps."status" = '1008'
|
||||
AND ps."date_value" >= TRUNC(SYSDATE) - (TO_CHAR(SYSDATE
|
||||
, 'd') - 1 + 7)
|
||||
AND ps."date_value" <= TRUNC(SYSDATE) - (TO_CHAR(SYSDATE
|
||||
, 'd') - 1) LIMIT 1000
|
||||
''', 'chart-type': 'table'}
|
||||
,
|
||||
"数信部上周有哪些人迟到": {'sql':'''
|
||||
SELECT p."id" AS "id",
|
||||
p."code" AS "工号",
|
||||
p."name" AS "姓名",
|
||||
p."work_unit" AS "工作单位",
|
||||
CASE
|
||||
WHEN ps."status" = '1006' THEN '迟到早退'
|
||||
WHEN ps."status" = '1009' THEN '迟到'
|
||||
WHEN ps."status" = '6002' THEN 'am迟到pm在岗'
|
||||
WHEN ps."status" = '6004' THEN 'am迟到pm缺勤'
|
||||
ELSE ps."status" END AS "状态"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
INNER JOIN "YJOA_APPSERVICE_DB"."t_yj_person_status" ps
|
||||
ON p."code" = ps."person_id"
|
||||
WHERE ps."status" IN ('1006', '1009', '6002', '6004')
|
||||
AND ps."date_value" >= TRUNC(SYSDATE) - (TO_CHAR(SYSDATE, 'd') - 1 + 7)
|
||||
AND ps."date_value" <= TRUNC(SYSDATE) - (TO_CHAR(SYSDATE, 'd') - 1)
|
||||
AND p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" || "shortname" LIKE '%数字信息部%' AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%')
|
||||
CONNECT BY PRIOR "id" = "parentid") AND p."dr" = 0 AND ps."dr" = 0 LIMIT 1000
|
||||
''','chart-type': 'table'},
|
||||
"数信部本周有哪些人旷工": {'sql':'''
|
||||
SELECT p."id" AS "id",
|
||||
p."code" AS "工号",
|
||||
p."name" AS "姓名",
|
||||
p."work_unit" AS "工作单位",
|
||||
CASE WHEN ps."status" = '1005' THEN '旷工' ELSE ps."status" END AS "状态"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_yj_person_status" ps
|
||||
INNER JOIN "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
ON p."code" = ps."person_id"
|
||||
WHERE ps."status" = '1005'
|
||||
AND ps."date_value" >= TRUNC(SYSDATE) - (TO_CHAR(SYSDATE, 'd') - 1)
|
||||
AND ps."date_value" <= TRUNC(SYSDATE) - (TO_CHAR(SYSDATE, 'd') - 1) + 7
|
||||
AND ps."dr" = 0
|
||||
AND p."dr" = 0
|
||||
AND p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" || "shortname" LIKE '%数字信息部%' OR "name" || "shortname" LIKE '%数信中心%') AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
ORDER BY ps."date_value" DESC LIMIT 1000
|
||||
''','chart-type': 'table'},
|
||||
'数信部员工连续在藏天数查询': {'sql':'''
|
||||
SELECT pt."year" AS "年份",
|
||||
p."code" AS "人员编号",
|
||||
pt."continuous_in_tibet_days" AS "连续在藏天数",
|
||||
p."name" AS "姓名",
|
||||
o."name" AS "部门"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
INNER JOIN "YJOA_APPSERVICE_DB"."t_yj_person_in_tibat" pt
|
||||
ON p."code" = pt."person_id"
|
||||
INNER JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE p."dr" = 0
|
||||
AND pt."dr" = 0
|
||||
AND p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" || "shortname" LIKE '%数字信息部%' AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%')
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
ORDER BY pt."year" DESC, pt."continuous_in_tibet_days" DESC LIMIT 1000
|
||||
''','chart-type': 'table'}
|
||||
,
|
||||
'数信中心员工累计在藏天数前20名': {'sql':'''
|
||||
SELECT p."code" AS "人员编号",
|
||||
p."name" AS "姓名",
|
||||
o."name" AS "部门",
|
||||
SUM(pt."count_in_tibat") AS "累计在藏天数"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
INNER JOIN "YJOA_APPSERVICE_DB"."t_yj_person_in_tibat" pt
|
||||
ON p."code" = pt."person_id"
|
||||
INNER JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE p."dr" = 0
|
||||
AND pt."dr" = 0
|
||||
AND p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" || "shortname" LIKE '%数信中心%' AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%')
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
GROUP BY p."code", p."name", o."name"
|
||||
ORDER BY SUM (pt."count_in_tibat") DESC LIMIT 20
|
||||
''','chart-type': 'bar'},
|
||||
'数信部员工昨日打卡记录查询':{'sql': '''
|
||||
SELECT a."person_name" AS "person_name",
|
||||
p."code" AS "employee_code",
|
||||
a."attendance_time" AS "attendance_time",
|
||||
a."attendance_address" AS "attendance_address",
|
||||
CASE
|
||||
WHEN a."status" = 1 THEN '在岗'
|
||||
WHEN a."status" = 2 THEN '出差'
|
||||
WHEN a."status" = 3
|
||||
THEN '休假' END AS "status_desc",
|
||||
CASE
|
||||
WHEN a."enter_or_exit" = 1 THEN '进'
|
||||
WHEN a."enter_or_exit" = 2
|
||||
THEN '出' END AS "entry_exit",
|
||||
o."name" AS "department_name"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_yj_person_attendance" a
|
||||
JOIN "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
ON a."person_id" = p."code"
|
||||
JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE a."dr" = 0
|
||||
AND p."dr" = 0
|
||||
AND a."attendance_time" >= TRUNC(SYSDATE - 1)
|
||||
AND a."attendance_time" < TRUNC(SYSDATE)
|
||||
AND o."id" IN (SELECT o2."id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" o2
|
||||
START WITH (o2."name" LIKE '%数字信息部%'
|
||||
OR o2."shortname" LIKE '%数字信息部%')
|
||||
AND o2."dr" = 0
|
||||
AND o2."enable" = 1
|
||||
AND o2."code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR o2."id" = o2."parentid")
|
||||
ORDER BY a."attendance_time" DESC LIMIT 1000
|
||||
''','chart-type': 'table'},
|
||||
'数信中心员工昨日考勤查询':{'sql': '''
|
||||
SELECT p."code" AS "工号",
|
||||
p."name" AS "姓名",
|
||||
o."name" AS "部门名称",
|
||||
ps."date_value" AS "日期",
|
||||
CASE
|
||||
WHEN ps."status" = '1001' THEN '在岗'
|
||||
WHEN ps."status" = '1002' THEN '出差'
|
||||
WHEN ps."status" = '1003' THEN '休假,请假'
|
||||
WHEN ps."status" = '1005' THEN '旷工'
|
||||
WHEN ps."status" = '1006' THEN '迟到,早退'
|
||||
WHEN ps."status" = '1007' THEN '休息日'
|
||||
WHEN ps."status" = '1008' THEN '加班'
|
||||
WHEN ps."status" = '1009' THEN '迟到'
|
||||
WHEN ps."status" = '4001' THEN 'am在岗pm缺勤'
|
||||
WHEN ps."status" = '4002' THEN 'am缺勤pm在岗'
|
||||
WHEN ps."status" = '6001' THEN 'am在岗pm早退'
|
||||
WHEN ps."status" = '6002' THEN 'am迟到pm在岗'
|
||||
WHEN ps."status" = '6004' THEN 'am迟到pm缺勤'
|
||||
WHEN ps."status" = '4006' THEN 'am缺勤pm早退'
|
||||
ELSE ps."status" END AS "人员状态"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_yj_person_status" ps
|
||||
JOIN "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
ON ps."person_id" = p."code"
|
||||
JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE o."id" IN (SELECT id FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" LIKE '%数信中心%' OR "shortname" LIKE '%数信中心%') AND "enable" = 1 AND "dr" = 0 AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
AND ps."date_value" = TO_CHAR(SYSDATE - 1
|
||||
, 'YYYY-MM-DD')
|
||||
AND ps."dr" = 0
|
||||
AND p."dr" = 0
|
||||
ORDER BY ps."date_value" DESC LIMIT 1000
|
||||
''','chart-type': 'table'},
|
||||
'外部单位人数最多的前五家是哪几个': {'sql':'''
|
||||
SELECT o.name AS "外部单位名称", COUNT(p.id) AS "员工人数"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
INNER JOIN "YJOA_APPSERVICE_DB"."t_pr3rl2oj_outsourcing_org_new" o
|
||||
ON p.external_unit = o.id
|
||||
WHERE p.dr = 0
|
||||
GROUP BY o.name
|
||||
ORDER BY COUNT(p.id) DESC LIMIT 5
|
||||
''','chart-type': 'column'},
|
||||
'数信部员工10月在林芝工作天数排行': {'sql':'''
|
||||
SELECT p."code" AS "工号",
|
||||
p."name" AS "姓名",
|
||||
COUNT(DISTINCT TO_CHAR(a."attendance_time", 'yyyy-MM-dd')) AS "在林芝工作天数"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
LEFT JOIN "YJOA_APPSERVICE_DB"."t_yj_person_attendance" a
|
||||
ON p."code" = a."person_id"
|
||||
LEFT JOIN "YJOA_APPSERVICE_DB"."t_yj_person_ac_area" ac
|
||||
ON a."access_control_point" = ac."ac_point"
|
||||
WHERE p."dr" = 0
|
||||
AND a."dr" = 0
|
||||
AND ac."region" = 5
|
||||
AND
|
||||
p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" LIKE '%数字信息部%' OR "shortname" LIKE '%数字信息部%') AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
AND TO_CHAR(a."attendance_time"
|
||||
, 'yyyy-MM') = '2025-10'
|
||||
GROUP BY p."code", p."name"
|
||||
ORDER BY "在林芝工作天数" DESC LIMIT 1000
|
||||
''','chart-type': 'bar'},
|
||||
'数信中心截止目前满足休假条件的员工有哪些': {'sql':'''
|
||||
SELECT pt."year" AS "年份",
|
||||
p."code" AS "人员编号",
|
||||
pt."continuous_in_tibet_days" AS "连续在藏天数",
|
||||
p."name" AS "姓名",
|
||||
o."name" AS "部门"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
INNER JOIN "YJOA_APPSERVICE_DB"."t_yj_person_in_tibat" pt
|
||||
ON p."code" = pt."person_id"
|
||||
INNER JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE p."dr" = 0
|
||||
AND pt."dr" = 0
|
||||
AND pt."continuous_in_tibet_days" >= 22
|
||||
AND p."internal_dept" IN
|
||||
(SELECT id FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" LIKE '%数信中心%' OR "shortname" LIKE '%数信中心%') AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
ORDER BY pt."continuous_in_tibet_days" DESC
|
||||
''','chart-type': 'table'}
|
||||
|
||||
}
|
||||
q_a_extent = {
|
||||
"数字信息部上周有哪些人加班": q_a['数信部上周有哪些人加班'],
|
||||
"数字信息部上周有哪些人迟到": q_a['数信部上周有哪些人迟到'],
|
||||
"数字信息部本周有哪些人旷工": q_a['数信部本周有哪些人旷工'],
|
||||
"数字信息部员工连续在藏天数查询": q_a['数信部员工连续在藏天数查询'],
|
||||
"数字信息部员工昨日打卡记录查询": q_a['数信部员工昨日打卡记录查询'],
|
||||
"数字信息部10月在林芝工作天数排行": q_a['数信部员工10月在林芝工作天数排行'],
|
||||
}
|
||||
|
||||
merged_dict = q_a | q_a_extent
|
||||
@@ -26,7 +26,7 @@ org_and_attend_q_a = [
|
||||
}, {
|
||||
"question": "xx中心10月有哪些人迟到",
|
||||
"answer": '''
|
||||
SELECT p."id" AS "id",
|
||||
SELECT
|
||||
p."code" AS "code",
|
||||
p."name" AS "name",
|
||||
CASE WHEN ps."status" = '1006' THEN '迟到/早退' ELSE ps."status" END AS "status"
|
||||
@@ -48,7 +48,7 @@ org_and_attend_q_a = [
|
||||
{
|
||||
"question": "xx中心10月有哪些人出差",
|
||||
"answer": '''
|
||||
SELECT p."id" AS "id",
|
||||
SELECT
|
||||
p."code" AS "code",
|
||||
p."name" AS "name",
|
||||
CASE WHEN ps."status" = '1002' THEN '出差' ELSE ps."status" END AS "status"
|
||||
@@ -70,7 +70,7 @@ org_and_attend_q_a = [
|
||||
{
|
||||
"question": "xx中心10月有哪些人旷工",
|
||||
"answer": '''
|
||||
SELECT p."id" AS "id",
|
||||
SELECT
|
||||
p."code" AS "code",
|
||||
p."name" AS "name",
|
||||
CASE WHEN ps."status" = '1002' THEN '旷工' ELSE ps."status" END AS "status"
|
||||
@@ -92,7 +92,7 @@ org_and_attend_q_a = [
|
||||
{
|
||||
"question": "xx中心10月有哪些人请假",
|
||||
"answer": '''
|
||||
SELECT p."id" AS "id",
|
||||
SELECT
|
||||
p."code" AS "code",
|
||||
p."name" AS "name",
|
||||
CASE WHEN ps."status" = '1003' THEN '请假' ELSE ps."status" END AS "status"
|
||||
@@ -120,7 +120,7 @@ org_and_attend_q_a = [
|
||||
COUNT(ps.id) AS "late_count"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p.internal_dept = o.id
|
||||
JOIN "YJOA_APPSERVICE_DB"."t_yj_person_status" ps ON p.id = ps.person_id
|
||||
JOIN "YJOA_APPSERVICE_DB"."t_yj_person_status" ps ON p.code = ps.person_id
|
||||
WHERE p.dr = 0
|
||||
AND ps.dr = 0
|
||||
AND ps.status in ('1006','1009','6002','6004')
|
||||
@@ -243,7 +243,7 @@ org_and_attend_q_a = [
|
||||
{
|
||||
"question": "xx中心10月有哪些人加班",
|
||||
"answer": '''
|
||||
SELECT p."id" AS "id",
|
||||
SELECT
|
||||
p."code" AS "code",
|
||||
p."name" AS "name",
|
||||
CASE WHEN ps."status" = '1008' THEN '加班' ELSE ps."status" END AS "status"
|
||||
@@ -262,24 +262,18 @@ org_and_attend_q_a = [
|
||||
"tags": ["员工", "部门", "考勤", "加班"],
|
||||
"category": "考勤管理"
|
||||
},{
|
||||
'question':'xx部有哪些员工',
|
||||
'question':'xx部有哪些正式员工',
|
||||
'answer':'''
|
||||
SELECT p."id" AS "id",
|
||||
SELECT
|
||||
p."code" AS "工号",
|
||||
p."name" AS "姓名",
|
||||
o."name" AS "单位",
|
||||
CASE WHEN p."gender" = '1' THEN '男' WHEN p."gender" = '2' THEN '女' END AS "性别",
|
||||
CASE
|
||||
WHEN p."person_status" = '1' THEN '草稿'
|
||||
WHEN p."person_status" = '2' THEN '审批中'
|
||||
WHEN p."person_status" = '3' THEN '制卡中'
|
||||
WHEN p."person_status" = '4' THEN '已入库'
|
||||
WHEN p."person_status" = '5' THEN '停用' END AS "人员状态"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON p."internal_dept" = o."id"
|
||||
WHERE p."internal_dept" IN (SELECT "id" FROM "IUAP_APDOC_BASEDOC"."org_orgs" START
|
||||
WITH ("name" || "shortname") LIKE '%xx部%' AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid") AND p."dr" = 0
|
||||
CONNECT BY PRIOR "id" = "parentid") AND p."dr" = 0 and p."person_type"='YG'
|
||||
ORDER BY p."code" ASC LIMIT 1000
|
||||
''',
|
||||
"tags": ["员工", "部门",],
|
||||
|
||||
@@ -224,6 +224,35 @@ question_and_answer = [
|
||||
"tags": ["员工", "学历", "部门", "人数统计"],
|
||||
"category": "学历分布统计"
|
||||
},
|
||||
{
|
||||
"question": "XX部门员工学历或学位排行",
|
||||
"answer": """
|
||||
SELECT p."code" AS "员工编号",p."name" AS "姓名", o."name" AS "部门",
|
||||
CASE WHEN p."highest_degree"='1' THEN '学士学位'
|
||||
WHEN p."highest_degree"='2' THEN '硕士学位'
|
||||
WHEN p."highest_degree"='3' THEN '博士学位'
|
||||
ELSE '其他' END AS "学位",
|
||||
p."graduate_school" AS "毕业院校"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p
|
||||
INNER JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o ON o."id"=p."internal_dept"
|
||||
WHERE p."internal_dept" IN (
|
||||
SELECT "id"
|
||||
FROM "IUAP_APDOC_BASEDOC"."org_orgs"
|
||||
START WITH ("name" || "shortname" LIKE '%数信中心%' AND "dr" = 0 AND "enable" = 1 AND "code" LIKE '%CYJ%')
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
AND p.dr=0
|
||||
AND o.dr=0
|
||||
AND p."person_type" = 'YG'
|
||||
ORDER BY
|
||||
CASE WHEN p."highest_degree" = '1' THEN 1
|
||||
WHEN p."highest_degree" = '2' THEN 2
|
||||
WHEN p."highest_degree" = '3' THEN 3
|
||||
ELSE 0
|
||||
END DESC LIMIT 1000
|
||||
""",
|
||||
"tags": ["员工", "学历", "部门", "人数统计"],
|
||||
"category": "学历分布统计"
|
||||
},
|
||||
{
|
||||
"question": "XX部门博士多少人",
|
||||
"answer": '''
|
||||
@@ -807,7 +836,34 @@ question_and_answer = [
|
||||
"category": "工作地考勤统计分析"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
"question": "本月XX中心各处室下迟到人次统计",
|
||||
"answer": '''
|
||||
SELECT o1."name" AS "处室名称", COUNT(DISTINCT ps."person_id") AS "迟到人数"
|
||||
FROM "YJOA_APPSERVICE_DB"."t_yj_person_status" ps
|
||||
JOIN "YJOA_APPSERVICE_DB"."t_pr3rl2oj_yj_person_database" p ON ps."person_id" = p."code"
|
||||
JOIN "IUAP_APDOC_BASEDOC"."org_orgs" o1 ON p."internal_dept" = o1."id"
|
||||
WHERE ps."status" IN ('1006','1009','6002','6004')
|
||||
AND ps."date_value" LIKE '2025-11%'
|
||||
AND ps."dr" = 0
|
||||
AND p."dr" = 0
|
||||
AND o1."dr" = 0
|
||||
AND o1."enable" = 1
|
||||
AND o1."code" LIKE '%CYJ%'
|
||||
AND p."internal_dept"IN (
|
||||
SELECT id
|
||||
FROM "IUAP_APDOC_BASEDOC"."org_orgs"
|
||||
START WITH ("name" LIKE '%数信中心%' OR "shortname" LIKE '%数信中心%')
|
||||
AND "dr" = 0
|
||||
AND "enable" = 1
|
||||
AND "code" LIKE '%CYJ%'
|
||||
CONNECT BY PRIOR "id" = "parentid")
|
||||
GROUP BY o1."name"
|
||||
ORDER BY "迟到人数" DESC LIMIT 1000
|
||||
''',
|
||||
"tags": ["员工", "部门", "考勤", "迟到","统计"],
|
||||
"category": "各部门迟到统计分析"
|
||||
},
|
||||
{
|
||||
"question": "张三9月在林芝上班期间,有多少天早退了?",
|
||||
"answer": '''
|
||||
|
||||
@@ -2,6 +2,10 @@ import logging
|
||||
from typing import Optional
|
||||
import re
|
||||
from orjson import orjson
|
||||
import pandas as pd
|
||||
from pandas import Timestamp
|
||||
from datetime import datetime, date
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
keywords = {
|
||||
# "gender":{"1":"男","2":"女"},
|
||||
@@ -107,3 +111,17 @@ def deal_result(data: list) -> list:
|
||||
raise Exception(f"sql执行结果处理失败:{str(e)}")
|
||||
|
||||
|
||||
def custom_json_serializer(obj):
|
||||
"""自定义JSON序列化器"""
|
||||
if isinstance(obj, (Timestamp, pd.Timestamp)):
|
||||
logger.info("format Timestamp")
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, (datetime, date)):
|
||||
logger.info("format datetime")
|
||||
return obj.isoformat()
|
||||
elif pd.isna(obj):
|
||||
logger.info("format NaN")
|
||||
return None
|
||||
else:
|
||||
logger.error(f"unknown type {type(obj)}")
|
||||
return str(obj)
|
||||
Reference in New Issue
Block a user