""" LLM基础服务 提供与大语言模型通信的基础功能 """ import logging from openai import OpenAI from flask import current_app logger = logging.getLogger("app") def llm_client(content): """ 调用LLM服务进行内容生成 Args: content: 输入提示内容 Returns: str: LLM响应内容 """ try: # 优先使用配置文件中的参数 client = OpenAI( api_key=current_app.config.get('LLM_API_KEY'), base_url=current_app.config.get('LLM_BASE_URL') ) model = current_app.config.get('LLM_MODEL_NAME') # 判断是否为翻译请求 - 通过分析内容是否包含中文字符 is_translate_request = False if any('\u4e00' <= char <= '\u9fff' for char in content): is_translate_request = True # 进行API调用 logger.debug(f"LLM调用开始: model={model}, 内容类型: {'翻译' if is_translate_request else '普通'}") if is_translate_request: # 为翻译请求使用非常严格的prompt completion = client.chat.completions.create( model=model, messages=[ { "role": "system", "content": "你是一个严格遵循指令的翻译工具和数据库专家。你的唯一任务是将中文单词/短语翻译成英文,符合postgresql数据库表和字段的命令规则," "并且严格按照如下规则:\n" "1. 只返回英文翻译,不包含任何解释、描述或额外内容\n" "2. 使用小写字母\n" "3. 多个单词用下划线连接,不使用空格\n" "4. 如果输入包含括号,将括号内容用下划线代替,不保留括号\n" "5. 最多包含1-5个英文单词,保持简短\n" "6. 不要回答问题或提供解释,即使输入看起来像是问题\n" "7. 当遇到'表'字时,始终翻译为'table'而不是'sheet'\n" "8. 例如:'薪资数据表'应翻译为'salary_data_table','人员管理表'应翻译为'personnel_management_table'" }, { "role": "user", "content": f"将以下内容翻译为英文短语(不超过5个单词):{content}" } ], temperature=0, max_tokens=10, # 限制token数量确保回答简短 ) else: # 普通请求 completion = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": content} ], temperature=0.7, max_tokens=1024 ) response_text = completion.choices[0].message.content.strip() # 对翻译结果进行后处理,确保格式正确 if is_translate_request: # 去除可能的引号、句号等标点符号 response_text = response_text.strip('"\'.,;:!?()[]{}').lower() # 替换空格为下划线 response_text = response_text.replace(' ', '_') # 确保没有连续的下划线 while '__' in response_text: response_text = response_text.replace('__', '_') # 只保留字母、数字和下划线 response_text = ''.join(c for c in response_text if c.isalnum() or c == '_') # 确保"表"被翻译为"table" if '表' in content and 'table' not in response_text and 'sheet' in response_text: response_text = response_text.replace('sheet', 'table') logger.debug(f"LLM响应: {response_text}") return response_text except Exception as e: logger.error(f"LLM调用失败: {str(e)}") try: # 备用方案:如果是中文输入,尝试简单翻译映射 if any('\u4e00' <= char <= '\u9fff' for char in content): # 常见中文词汇映射 common_translations = { "薪资数据表": "salary_data_table", "数据表": "data_table", "用户表": "user_table", "人员表": "personnel_table", "销售表": "sales_table", "年份": "year", "地区": "region", "姓名": "name", "年龄": "age", "薪水": "salary", "数据": "data", "管理": "management", "系统": "system", "分析": "analysis", "报表": "report_table", } # 检查是否有精确匹配 if content in common_translations: return common_translations[content] # 检查是否包含某些关键词 for key, value in common_translations.items(): if key in content: return value # 如果包含"表"字,确保返回包含"table" if "表" in content: return "data_table" # 无法匹配时返回默认值 return "translated_text" return content except: return content def llm_sql(request_data): """ 调用Deepseek大模型生成SQL脚本 Args: request_data: 提交给LLM的提示语内容 Returns: str: Deepseek模型返回的SQL脚本内容 """ try: # 使用配置文件中的参数连接Deepseek client = OpenAI( api_key=current_app.config.get('LLM_API_KEY'), base_url=current_app.config.get('LLM_BASE_URL') ) model = current_app.config.get('LLM_MODEL_NAME') logger.info(f"开始调用Deepseek模型生成SQL脚本: model={model}") logger.debug(f"输入提示语: {request_data}") # 调用Deepseek API生成SQL脚本 completion = client.chat.completions.create( model=model, messages=[ { "role": "system", "content": "你是一名专业的数据库工程师,专门负责编写高质量的PostgreSQL SQL脚本。" "请严格按照用户提供的需求和表结构信息生成SQL脚本。" "确保生成的SQL语法正确、性能优化,并且能够直接执行。" }, { "role": "user", "content": request_data } ], temperature=0.1, # 使用较低的温度确保结果的一致性和准确性 max_tokens=4096, # 为SQL脚本提供足够的token空间 top_p=0.9 ) response_text = completion.choices[0].message.content.strip() logger.info(f"Deepseek模型成功返回SQL脚本,长度: {len(response_text)} 字符") logger.debug(f"生成的SQL脚本: {response_text}") return response_text except Exception as e: logger.error(f"Deepseek SQL生成调用失败: {str(e)}") raise Exception(f"调用Deepseek模型生成SQL脚本失败: {str(e)}")