import json import time import re from traceback import print_exc from appPublic.dictObject import DictObject from appPublic.httpclient import * from appPublic.jsonConfig import getConfig from appPublic.log import info, debug, warning, error, exception, critical def search(request, env): params_kw = env.get(params_kw) prompt = params_kw.prompt f = params_kw.search_func def get_json_text(json_str): pattern = r'json(.*?)```' match = re.search(pattern, json_str, re.DOTALL) if match: return match.group(1).strip() else: return json_str def clear_dict(dic): d = { k:v for k,v in dic.items() if v not in [ 'undefined', '' ] } ret = {} for k ,v in d.items(): if isinstance(v, dict): v = clear_dict(v) if v != {}: ret.update({k:v}) else: ret.update({k:v}) return ret async def _llmchat(prompt): hc = HttpClient() config = getConfig() model = config.definitions.search_model url = config.definitions.search_url syscontent = config.definitions.search_syscontent headers = { "Content-Type":"application/json" } messages = [ { "role":"system", "content":syscontent }, { "role":"user", "content":prompt } ] body = { "model":model, "stream":False, "messages":messages } data = json.dumps(body) t1 = time.time() resp = await hc.request(url, 'POST', headers=headers, data=data, response_type=RESPONSE_JSON) t2 = time.time() resp = DictObject(resp) info(f'{resp.message.content=}, cost={t2 - t1}') text = resp.message.content jtxt = get_json_text(text) if jtxt is None: return None j = DictObject(**json.loads(jtxt)) j.time_cost = t2 - t1 j = clear_dict(j) info(f'return data={j}========') return j async def llmchat2json(prompt): """ 用大语言模型将用户输入转化为查询条件的json对象, 需要在项目的config.json文件中的definitions属性中 定义以下变量 "search_model":"qwen2:7b", "search_url":"http://localhost:11434/api/chat", "search_syscontent":"将用户输入转换成算力和云服务器查询的json数据json格式为{ \"requestType\": \"resourceQuery\", \"queryParameters\": { \"resourceType\": \"undefined\", \"region\": \"undefined\", \"gpuModel\": \"undefined\", \"gpuCount\": 0, \"cpuModel\": \"undefined\", \"cpuCount\": \"undefined\", \"memorySizeGB\": \"undefined\", \"storageType\": \"undefined\", \"storageCapacityGB\": \"undefined\",\"bandwidthMbps\": \"undefined\",\"priceRange\": { \"min\": \"undefined\", \"max\": \"undefined\"}, \"availabilityZone\": \"undefined\" }}, 保持数据中原有语言,只需返回json数据内容 ,输入中没有的属性省略" 其中:search_model定义了用于转化查询的大模型名字 search_url是提供大模型对话服务的url, 我们使用本地部署的开源大模型,所以不用定义apikey search_syscontent是一段给大模型的约束文本,要求大模型按要求回复信息 输入参数:prompt 用户输入的查询条件 返回:查询条件的json, 如果出错,返回None """ try: x = await _llmchat(prompt) return x except Exception as e: exception(f'{e=}') return None if __name__ == '__main__': import sys if len(sys.argv) < 2: print(f'Usage:\n{sys.argv[0]} search_text') sys.exit(1) prompt= sys.argv[1] config = getConfig('.') loop = asyncio.get_event_loop().run_until_complete(llmchat(prompt)) print('here')