From 041e9f80ab12d03a1bdc29b97efce8ec3e21bc68 Mon Sep 17 00:00:00 2001 From: sudoskys Date: Fri, 27 Jan 2023 14:45:50 +0800 Subject: [PATCH 1/4] =?UTF-8?q?0.2.0=20=E4=BF=AE=E5=A4=8D=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=BA=93=EF=BC=8C=E4=BF=AE=E5=A4=8D=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 4 +- src/llm_kira/client/Optimizer.py | 65 ++++----- src/llm_kira/client/anchor.py | 120 ++++++++--------- src/llm_kira/client/llms/base.py | 7 +- src/llm_kira/client/llms/openai.py | 20 ++- src/llm_kira/client/types.py | 8 +- src/llm_kira/openai/api/network.py | 160 +++++++++------------- src/llm_kira/openai/api/network.py.curl | 168 ++++++++++++++++++++++++ 8 files changed, 350 insertions(+), 202 deletions(-) create mode 100644 src/llm_kira/openai/api/network.py.curl diff --git a/pyproject.toml b/pyproject.toml index 9689599..a09c6b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "llm_kira" -version = "0.1.9" +version = "0.2.0" description = "chatbot client for llm" authors = ["sudoskys "] maintainers = [ @@ -26,7 +26,7 @@ openai-async = "^0.0.2" numpy = "^1.24.1" tiktoken = "^0.1.2" scikit-learn = "^1.2.0" -pycurl = "^7.43.0.6" +# pycurl = "^7.43.0.6" [build-system] diff --git a/src/llm_kira/client/Optimizer.py b/src/llm_kira/client/Optimizer.py index cd99216..573ba1d 100644 --- a/src/llm_kira/client/Optimizer.py +++ b/src/llm_kira/client/Optimizer.py @@ -57,7 +57,7 @@ class MatrixPoint(Point): def __init__(self, tokenizer, prompt: str = "", - memory: List[Memory_Flow] = None, + memory: List[dict] = None, attention: int = 3, # start_token: int = 0, extra_token: int = 0, @@ -130,17 +130,17 @@ def forgetting_curve(x): # 主题检索 _key = Utils.tfidf_keywords(prompt, topK=5) - # print(_key) - for i in range(0, len(memory)): - score = 0 - full_score = len(_key) if len(_key) != 0 else 1 - ask, reply = MsgFlow.get_content(memory[i], sign=False) - for ir in _key: - if ir in f"{ask}{reply}": - score += 1 - _get = (score / full_score) * 100 - if _get: - memory[i]["content"]["weight"].append(_get) # 基准数据,置信为 0.5 百分比 + full_score = len(_key) + if full_score > 5: + for i in range(0, len(memory)): + score = 0 + ask, reply = MsgFlow.get_content(memory[i], sign=False) + for ir in _key: + if ir in f"{ask}{reply}": + score += 1 + _get = (score / full_score) * 100 + if _get != 0: + memory[i]["content"]["weight"].append(_get) # 基准数据,置信为 0.5 百分比 # 预处理 for i in range(0, len(memory) - attention): @@ -179,7 +179,7 @@ class SinglePoint(Point): def __init__(self, tokenizer, prompt: str = "", - memory: List[Memory_Flow] = None, + memory: List[dict] = None, attention: int = 3, # start_token: int = 0, extra_token: int = 0, @@ -205,7 +205,6 @@ def __init__(self, self.tokenizer = tokenizer def run(self) -> list: - # 单条消息的内容 {"ask": self._restart_sequence+prompt, "reply": self._start_sequence+REPLY[0]} memory = self.memory attention = self.attention @@ -214,6 +213,7 @@ def run(self) -> list: if self.memory is None: memory = [] _create_token = self.token_limit - self.extra_token + # 入口检查 if len(memory) - attention < 0: return convert_msgflow_to_list(memory) @@ -258,34 +258,27 @@ def forgetting_curve(x): _diff2 = Utils.cosion_sismilarity(pre=prompt, aft=reply) _diff = _diff1 if _diff1 > _diff2 else _diff2 score = _diff * 100 - score = score if score < 90 else 1 + score = score if score < 90 else 0 if score != 0: memory[i]["content"]["weight"].append(score) + if ask == reply: + memory[i]["content"]["ask"] = "" # 主题检索 _key = Utils.tfidf_keywords(prompt, topK=5) - # print(_key) - for i in range(0, len(memory)): - score = 0 - full_score = len(_key) if len(_key) != 0 else 1 - ask, reply = MsgFlow.get_content(memory[i], sign=False) - for ir in _key: - if ir in f"{ask}{reply}": - score += 1 - _get = (score / full_score) * 100 - _get = _get if _get < 95 else 50 - if _get != 0: - memory[i]["content"]["weight"].append(_get) # 基准数据,置信为 0.5 百分比 + full_score = len(_key) + if full_score > 5: + for i in range(0, len(memory)): + score = 0 + ask, reply = MsgFlow.get_content(memory[i], sign=False) + for ir in _key: + if ir in f"{ask}{reply}": + score += 1 + _get = (score / full_score) * 100 + _get = _get if _get < 95 else 50 + if _get != 0: + memory[i]["content"]["weight"].append(_get) # 基准数据,置信为 0.5 百分比 - # 预处理 - for i in range(0, len(memory) - attention): - ask, reply = MsgFlow.get_content(memory[i], sign=False) - if self.tokenizer(f"{ask}{reply}") > 240: - if Detect.get_text_language(sentence=f"{ask}{reply}") == "CN": - _sum = Utils.tfidf_summarization(sentence=f"{ask}{reply}", ratio=0.5) - if len(_sum) > 7: - memory[i]["content"]["ask"] = "info" - memory[i]["content"]["reply"] = _sum # 进行筛选,计算限制 _msg_flow = [] _msg_return = [] diff --git a/src/llm_kira/client/anchor.py b/src/llm_kira/client/anchor.py index a570008..89a70d4 100644 --- a/src/llm_kira/client/anchor.py +++ b/src/llm_kira/client/anchor.py @@ -13,7 +13,7 @@ from .enhance import Support from .llms.base import LlmBaseParam from .llms.openai import LlmBase -from .types import LlmReturn +from .types import LlmReturn, LLMException from ..utils.chat import Detect from ..utils.data import MsgFlow # 基于 Completion 上层 @@ -230,7 +230,7 @@ def __init__(self, self.optimizer = Optimizer.SinglePoint self.llm = llm_model if llm_model is None: - raise Exception("Whats your llm model?") + raise LLMException("Whats your llm model?") async def predict(self, prompt: PromptManager, @@ -242,114 +242,110 @@ async def predict(self, self.prompt = prompt if parse_reply: self.llm.parse_reply = parse_reply + + predict_tokens += self.llm.tokenizer(self.profile.restart_name) if predict_tokens > self.llm.get_token_limit(): - raise Exception("Why your predict token > set token limit?") - prompt: str = self.prompt.run(raw_list=False) + raise LLMException("Why your predict token > set token limit?") - # prompt 重整 + prompt_text: str = self.prompt.run(raw_list=False) + # prompt 前向注入 prompt_raw: list = self.prompt.run(raw_list=True) - prompt_raw_index = list(reversed(prompt_raw))[0] __extra_memory = [] - __content_list = [prompt_raw_index] for item in prompt_raw: index = round(len(item) / 3) if round(len(item) / 3) > 3 else 10 if ":" in item[:index]: __extra_memory.append(item) else: - __content_list.append(item) + self.memory_manger.save_context(ask=item, + reply=item, + no_head=True) if len(__extra_memory) == 2: self.memory_manger.save_context(ask=__extra_memory[0], reply=__extra_memory[1], no_head=True) __extra_memory.clear() - - prompt_index = ','.join(__content_list) - + # Prompt Info + prompt_lang: str = Detect.get_text_language(sentence=prompt_text) + prompt_iscode: bool = Detect.isCode(sentence=prompt_text) + prompt_preset = Preset(self.profile) # Template template: str = self.prompt.run_template() - - # Lang - prompt_lang: str = Detect.get_text_language(sentence=prompt) - prompt_iscode: bool = Detect.isCode(sentence=prompt) - prompt_preset = Preset(self.profile) - _template = [] - - # Role + # Preset LLM Head if template is None: + __template = [] + # Head + head = prompt_preset.head(prompt_iscode=prompt_iscode, + lang=prompt_lang) + __template.append(head) # Character character = prompt_preset.character(lang=prompt_lang) _role = prompt_preset.role(restart_name=self.profile.restart_name, character=",".join(character), prompt_iscode=prompt_iscode, lang=prompt_lang) - role = f"{self.profile.start_name}:{_role}.\n" - _template.append(role) - - # Head - if template is None: - head = prompt_preset.head(prompt_iscode=prompt_iscode, - lang=prompt_lang) - _template.append(head) - if template is None: - template = ''.join(_template) - # Restart - _prompt_s = [f"{prompt}"] - - # Memory + role = f"\n{_role}." + __template.append(role) + template = ''.join(__template) + # Memory Read _prompt_memory = self.memory_manger.read_memory(plain_text=False) + # Advance Template + _prompt_head = [] + _prompt_body = [] + _prompt_foot = [] + _prompt_foot.extend([f"{prompt_text}"]) # Enhance if isinstance(increase, str): _appendix = increase else: _appendix = await increase.run() - - # PROMPT - _prompt_list = [_appendix] - - # Extra - _extra_token = int( + _prompt_head.append(template) + _prompt_head.append(_appendix) + # Cut Size + _body_token = int( predict_tokens + - len(_prompt_memory) + - self.llm.tokenizer(self.profile.start_name) + - self.llm.tokenizer(template + "".join(_prompt_s)) + - self.llm.tokenizer(_appendix) + # len(_prompt_memory) + + self.llm.tokenizer(''.join(_prompt_head)) + + self.llm.tokenizer(''.join(_prompt_foot)) + + 1 # \n ) # Run Optimizer - _prompt_apple = self.optimizer( - prompt=prompt, + _prompt_optimized = self.optimizer( + prompt=prompt_text, memory=_prompt_memory, - extra_token=_extra_token, + extra_token=_body_token, token_limit=self.llm.get_token_limit(), tokenizer=self.llm.tokenizer, ).run() + _prompt_body.extend(_prompt_optimized) + + # Resize + _llm_result_limit = self.llm.get_token_limit() - predict_tokens + _prompt = self.llm.resize_context(head=_prompt_head, + body=_prompt_body, + foot=_prompt_foot, + token=_llm_result_limit) - # After - _prompt_list.extend(_prompt_apple) - _prompt_list.extend(_prompt_s) # Clean - _prompt_list = [item for item in _prompt_list if item] - # Stick - _prompt = '\n'.join(_prompt_list) + f"\n{self.profile.restart_name}:" + _prompt_body = [item for item in _prompt_body if item] + + # Stick Them + _prompt = _prompt + f"\n{self.profile.restart_name}:" if not prompt_iscode: _prompt = _prompt.replace("\n\n", "\n") - # Resize - _limit = self.llm.get_token_limit() - _extra_token - _prompt = self.llm.resize_context(_prompt, _limit) - _prompt = template + _prompt - _prompt = self.llm.resize_context(_prompt, self.llm.get_token_limit() - predict_tokens) + # TOD # logger.warning(_prompt) - # GET + + # Get llm_result = await self.llm.run(prompt=_prompt, predict_tokens=predict_tokens, llm_param=llm_param) llm_result: LlmReturn - - # 解析结果返回结果 - self.memory_manger.save_context(ask=prompt_index, + # Parse Result + self.memory_manger.save_context(ask=prompt_text, reply=f"{self.profile.restart_name}:{self.llm.parse_reply(llm_result.reply)}", no_head=True) return ChatBotReturn(conversation_id=f"{self.profile.conversation_id}", llm=llm_result, - ask=prompt_index, + ask=prompt_text, reply=self.llm.parse_reply(llm_result.reply)) diff --git a/src/llm_kira/client/llms/base.py b/src/llm_kira/client/llms/base.py index 3f2d614..83fd16d 100644 --- a/src/llm_kira/client/llms/base.py +++ b/src/llm_kira/client/llms/base.py @@ -50,9 +50,14 @@ def tokenizer(self, text): return len(text) @abstractmethod - def resize_context(self, text: str, token: int) -> str: + def resize_sentence(self, text: str, token: int) -> str: return text[:token] + @abstractmethod + def resize_context(self, head: list, body: list, foot: list, token: int) -> str: + _all = ''.join(head + body + foot) + return self.resize_sentence(_all, token=token) + @staticmethod def model_context_size(model_name: str) -> int: pass diff --git a/src/llm_kira/client/llms/openai.py b/src/llm_kira/client/llms/openai.py index 068dd4b..e278e8f 100644 --- a/src/llm_kira/client/llms/openai.py +++ b/src/llm_kira/client/llms/openai.py @@ -145,12 +145,30 @@ def parse_reply(self, reply: List[str]) -> str: """处理解码后的列表""" return "".join(reply) - def resize_context(self, text: str, token: int) -> str: + def resize_sentence(self, text: str, token: int) -> str: token = token if token > 5 else 5 while self.tokenizer(text) > token: text = text[4:] return text + def resize_context(self, head: list, body: list, foot: list, token: int) -> str: + token = token if token > 5 else 5 + _head = '\n'.join(head) + "\n" + _body = "\n".join(body) + "\n" + _foot = ''.join(foot) + # Force Resize Head + _head = _head[:int(token * 0.8)] + _all = _head + _body + _foot + while self.tokenizer(_all) > token: + if len(body) > 2: + body.pop(0) + _body = "\n".join(body) + else: + _body = _body[4:] + _all = _head + _body + _foot + self.resize_sentence(_all, token=token) + return _all + @staticmethod def model_context_size(model_name: str) -> int: if model_name == "text-davinci-003": diff --git a/src/llm_kira/client/types.py b/src/llm_kira/client/types.py index 5f6cc7f..690c16b 100644 --- a/src/llm_kira/client/types.py +++ b/src/llm_kira/client/types.py @@ -19,9 +19,9 @@ class LlmReturn(BaseModel): model_flag: Optional[str] prompt: str reply: List[str] - usage: int = 0 + usage: Optional[int] time: int = int(time.time()) - raw: dict + raw: Optional[dict] class ChatBotReturn(BaseModel): @@ -48,3 +48,7 @@ class MemoryItem(BaseModel): class Memory_Flow(BaseModel): content: MemoryItem time: int = int(time.time() * 1000) + + +class LLMException(BaseException): + pass diff --git a/src/llm_kira/openai/api/network.py b/src/llm_kira/openai/api/network.py index 70ada98..287894c 100644 --- a/src/llm_kira/openai/api/network.py +++ b/src/llm_kira/openai/api/network.py @@ -1,4 +1,9 @@ # -*- coding: utf-8 -*- +# @Time : 1/27/23 2:25 PM +# @FileName: network.py +# @Software: PyCharm +# @Github :sudoskys +# -*- coding: utf-8 -*- # @Time : 12/5/22 9:58 PM # @FileName: network.py # @Software: PyCharm @@ -9,9 +14,9 @@ from typing import Any import json -# -import pycurl -from io import BytesIO +import asyncio +import atexit +import httpx __session_pool = {} @@ -25,7 +30,6 @@ async def request( json_body: bool = False, proxy: str = "", call_func=None, - encodings: str = "", **kwargs, ): """ @@ -49,8 +53,7 @@ async def request( } if params is None: params = {} - if not data: - raise Exception("Openai Network:Empty Data") + config = { "method": method.upper(), "url": url, @@ -58,26 +61,33 @@ async def request( "data": data, "headers": headers, } + # 更新 config.update(kwargs) if json_body: config["headers"]["Content-Type"] = "application/json" config["data"] = json.dumps(config["data"]) - if method == "POST": - code, raw_data = await curl_post(url=url, - headers=config["headers"], - params=config["params"], - data=config["data"], - encodings=encodings, - proxy=proxy - ) - else: - code, raw_data = await curl_get(url=url, - headers=config["headers"], - params=config["params"], - encodings=encodings, - proxy=proxy - ) + + # SSL + # config["ssl"] = False + + session = get_session(proxy=proxy) + resp = await session.request(**config) + + # 检查响应头 Content-Length + content_length = resp.headers.get("content-length") + if content_length and int(content_length) == 0: + return None + + # 检查响应头 Content-Type + content_type = resp.headers.get("content-type") + + # Not application/json + if content_type.lower().index("application/json") == -1: + raise Exception("请求不是 application/json 类型") + + # 提取内容 + raw_data = resp.text req_data: dict req_data = json.loads(raw_data) ERROR = req_data.get("error") @@ -89,80 +99,34 @@ async def request( return req_data -async def curl_get(url, - headers: dict, - params, - encodings: str = "", - proxy: str = "", - connect_timeout: int = 120, - timeout: int = 60, - **kwargs - ): - _headers = [] - for key, values in headers.items(): - _headers.append(f"{key}:{values}") - _params = [] - for key, values in params.items(): - _params.append(f"{key}={values}&") - if _params: - url = f"{url}?" + "".join(_params).strip("&") - c = pycurl.Curl() # 通过curl方法构造一个对象 - c.setopt(pycurl.FOLLOWLOCATION, True) # 自动进行跳转抓取 - c.setopt(pycurl.MAXREDIRS, 3) # 设置最多跳转多少次 - c.setopt(pycurl.CONNECTTIMEOUT, connect_timeout) # 设置链接超时 - c.setopt(pycurl.TIMEOUT, timeout) # 下载超时 - if encodings: - c.setopt(pycurl.ENCODING, encodings) # 处理gzip内容 - if proxy: - c.setopt(pycurl.PROXY, proxy) # 代理 - c.fp = BytesIO() - c.setopt(pycurl.URL, url) # 设置要访问的URL - # c.setopt(pycurl.USERAGENT, ua) # 传入User-Agent - c.setopt(pycurl.HTTPHEADER, _headers) # 传入请求头 - c.setopt(pycurl.WRITEFUNCTION, c.fp.write) # 回调写入字符串缓存 - c.perform() - code = c.getinfo(pycurl.RESPONSE_CODE) - raw_data = c.fp.getvalue() # 返回源代码 - c.close() - return code, raw_data - - -async def curl_post(url, - headers: dict, - params, - data, - encodings: str = "", - proxy: str = "", - connect_timeout: int = 120, - timeout: int = 60, - **kwargs - ): - _headers = [] - for key, values in headers.items(): - _headers.append(f"{key}:{values}") - _params = [] - for key, values in params.items(): - _params.append(f"{key}={values}&") - if _params: - url = f"{url}?" + "".join(_params).strip("&") - c = pycurl.Curl() # 通过curl方法构造一个对象 - c.setopt(pycurl.FOLLOWLOCATION, True) # 自动进行跳转抓取 - c.setopt(pycurl.MAXREDIRS, 3) # 设置最多跳转多少次 - c.setopt(pycurl.CONNECTTIMEOUT, connect_timeout) # 设置链接超时 - c.setopt(pycurl.TIMEOUT, timeout) # 下载超时 - if encodings: - c.setopt(pycurl.ENCODING, encodings) # 处理gzip内容 - if proxy: - c.setopt(pycurl.PROXY, proxy) # 代理 - c.fp = BytesIO() - c.setopt(pycurl.URL, url) # 设置要访问的URL - # c.setopt(pycurl.USERAGENT, ua) # 传入User-Agent - c.setopt(pycurl.HTTPHEADER, _headers) # 传入请求头 - c.setopt(pycurl.POST, 1) - c.setopt(pycurl.POSTFIELDS, data) - c.setopt(pycurl.WRITEFUNCTION, c.fp.write) # 回调写入字符串缓存 - c.perform() - code = c.getinfo(pycurl.RESPONSE_CODE) - raw_data = c.fp.getvalue() # 返回源代码 - c.close() - return code, raw_data +def get_session(proxy: str = ""): + global __session_pool + loop = asyncio.get_event_loop() + session = __session_pool.get(loop, None) + if session is None: + if proxy: + proxies = {"all://": proxy} + session = httpx.AsyncClient(timeout=300, proxies=proxies) + else: + session = httpx.AsyncClient(timeout=300) + __session_pool[loop] = session + return session + + +@atexit.register +def __clean(): + """ + 程序退出清理操作。 + """ + try: + loop = asyncio.get_event_loop() + except RuntimeError: + return + + async def __clean_task(): + await __session_pool[loop].close() + + if loop.is_closed(): + loop.run_until_complete(__clean_task()) + else: + loop.create_task(__clean_task()) diff --git a/src/llm_kira/openai/api/network.py.curl b/src/llm_kira/openai/api/network.py.curl new file mode 100644 index 0000000..70ada98 --- /dev/null +++ b/src/llm_kira/openai/api/network.py.curl @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# @Time : 12/5/22 9:58 PM +# @FileName: network.py +# @Software: PyCharm +# @Github :sudoskys +""" +参考 bilibili_api.utils.network_httpx 制造的工具类 +""" + +from typing import Any +import json +# +import pycurl +from io import BytesIO + +__session_pool = {} + + +async def request( + method: str, + url: str, + params: dict = None, + data: Any = None, + auth: str = None, + json_body: bool = False, + proxy: str = "", + call_func=None, + encodings: str = "", + **kwargs, +): + """ + 请求 + :param call_func: 回调函数,用于调整结构 + :param method: + :param url: + :param params: + :param data: + :param auth: + :param json_body: + :param proxy: + :param kwargs: 参数 + :return: + """ + if auth is None: + return Exception("API KEY MISSING") + headers = { + "User-Agent": "Mozilla/5.0", + "Authorization": f"Bearer {auth}" + } + if params is None: + params = {} + if not data: + raise Exception("Openai Network:Empty Data") + config = { + "method": method.upper(), + "url": url, + "params": params, + "data": data, + "headers": headers, + } + # 更新 + config.update(kwargs) + if json_body: + config["headers"]["Content-Type"] = "application/json" + config["data"] = json.dumps(config["data"]) + if method == "POST": + code, raw_data = await curl_post(url=url, + headers=config["headers"], + params=config["params"], + data=config["data"], + encodings=encodings, + proxy=proxy + ) + else: + code, raw_data = await curl_get(url=url, + headers=config["headers"], + params=config["params"], + encodings=encodings, + proxy=proxy + ) + req_data: dict + req_data = json.loads(raw_data) + ERROR = req_data.get("error") + if ERROR: + # if ERROR.get('type') == "insufficient_quota": + if call_func: + call_func(req_data, auth) + raise RuntimeError(f"{ERROR.get('type')}:{ERROR.get('message')}") + return req_data + + +async def curl_get(url, + headers: dict, + params, + encodings: str = "", + proxy: str = "", + connect_timeout: int = 120, + timeout: int = 60, + **kwargs + ): + _headers = [] + for key, values in headers.items(): + _headers.append(f"{key}:{values}") + _params = [] + for key, values in params.items(): + _params.append(f"{key}={values}&") + if _params: + url = f"{url}?" + "".join(_params).strip("&") + c = pycurl.Curl() # 通过curl方法构造一个对象 + c.setopt(pycurl.FOLLOWLOCATION, True) # 自动进行跳转抓取 + c.setopt(pycurl.MAXREDIRS, 3) # 设置最多跳转多少次 + c.setopt(pycurl.CONNECTTIMEOUT, connect_timeout) # 设置链接超时 + c.setopt(pycurl.TIMEOUT, timeout) # 下载超时 + if encodings: + c.setopt(pycurl.ENCODING, encodings) # 处理gzip内容 + if proxy: + c.setopt(pycurl.PROXY, proxy) # 代理 + c.fp = BytesIO() + c.setopt(pycurl.URL, url) # 设置要访问的URL + # c.setopt(pycurl.USERAGENT, ua) # 传入User-Agent + c.setopt(pycurl.HTTPHEADER, _headers) # 传入请求头 + c.setopt(pycurl.WRITEFUNCTION, c.fp.write) # 回调写入字符串缓存 + c.perform() + code = c.getinfo(pycurl.RESPONSE_CODE) + raw_data = c.fp.getvalue() # 返回源代码 + c.close() + return code, raw_data + + +async def curl_post(url, + headers: dict, + params, + data, + encodings: str = "", + proxy: str = "", + connect_timeout: int = 120, + timeout: int = 60, + **kwargs + ): + _headers = [] + for key, values in headers.items(): + _headers.append(f"{key}:{values}") + _params = [] + for key, values in params.items(): + _params.append(f"{key}={values}&") + if _params: + url = f"{url}?" + "".join(_params).strip("&") + c = pycurl.Curl() # 通过curl方法构造一个对象 + c.setopt(pycurl.FOLLOWLOCATION, True) # 自动进行跳转抓取 + c.setopt(pycurl.MAXREDIRS, 3) # 设置最多跳转多少次 + c.setopt(pycurl.CONNECTTIMEOUT, connect_timeout) # 设置链接超时 + c.setopt(pycurl.TIMEOUT, timeout) # 下载超时 + if encodings: + c.setopt(pycurl.ENCODING, encodings) # 处理gzip内容 + if proxy: + c.setopt(pycurl.PROXY, proxy) # 代理 + c.fp = BytesIO() + c.setopt(pycurl.URL, url) # 设置要访问的URL + # c.setopt(pycurl.USERAGENT, ua) # 传入User-Agent + c.setopt(pycurl.HTTPHEADER, _headers) # 传入请求头 + c.setopt(pycurl.POST, 1) + c.setopt(pycurl.POSTFIELDS, data) + c.setopt(pycurl.WRITEFUNCTION, c.fp.write) # 回调写入字符串缓存 + c.perform() + code = c.getinfo(pycurl.RESPONSE_CODE) + raw_data = c.fp.getvalue() # 返回源代码 + c.close() + return code, raw_data From 4a24416707f77a104da491f25d078b703e782c61 Mon Sep 17 00:00:00 2001 From: sudoskys Date: Fri, 27 Jan 2023 14:57:45 +0800 Subject: [PATCH 2/4] =?UTF-8?q?0.2.0=20=E4=BF=AE=E5=A4=8D=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=BA=93=EF=BC=8C=E4=BF=AE=E5=A4=8D=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_kira/client/Optimizer.py | 9 ++++----- src/llm_kira/client/anchor.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/llm_kira/client/Optimizer.py b/src/llm_kira/client/Optimizer.py index 573ba1d..3796083 100644 --- a/src/llm_kira/client/Optimizer.py +++ b/src/llm_kira/client/Optimizer.py @@ -254,11 +254,9 @@ def forgetting_curve(x): # 相似度检索 for i in range(0, len(memory)): ask, reply = MsgFlow.get_content(memory[i], sign=False) - _diff1 = Utils.cosion_sismilarity(pre=prompt, aft=ask) - _diff2 = Utils.cosion_sismilarity(pre=prompt, aft=reply) - _diff = _diff1 if _diff1 > _diff2 else _diff2 - score = _diff * 100 - score = score if score < 90 else 0 + _ask_diff = Utils.cosion_sismilarity(pre=prompt, aft=ask) + _ask_diff = _ask_diff * 100 + score = _ask_diff if _ask_diff < 90 else 0 if score != 0: memory[i]["content"]["weight"].append(score) if ask == reply: @@ -290,6 +288,7 @@ def forgetting_curve(x): score = sum(memory[i]["content"]["weight"]) level = (score / full_score) * 100 ask, reply = MsgFlow.get_content(memory[i], sign=True) + # print(ask, reply, level) if level > 50: _now_token += self.tokenizer(f"{ask}{reply}") if _now_token > _create_token: diff --git a/src/llm_kira/client/anchor.py b/src/llm_kira/client/anchor.py index 89a70d4..7c80c96 100644 --- a/src/llm_kira/client/anchor.py +++ b/src/llm_kira/client/anchor.py @@ -335,7 +335,7 @@ async def predict(self, if not prompt_iscode: _prompt = _prompt.replace("\n\n", "\n") - # TOD + # ODO # logger.warning(_prompt) # Get From 1c036228c81cf13c0afbc17b4922c2f5a6683465 Mon Sep 17 00:00:00 2001 From: sudoskys Date: Fri, 27 Jan 2023 14:58:00 +0800 Subject: [PATCH 3/4] =?UTF-8?q?0.2.0=20=E4=BF=AE=E5=A4=8D=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=BA=93=EF=BC=8C=E4=BF=AE=E5=A4=8D=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_kira/client/anchor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llm_kira/client/anchor.py b/src/llm_kira/client/anchor.py index 7c80c96..598a574 100644 --- a/src/llm_kira/client/anchor.py +++ b/src/llm_kira/client/anchor.py @@ -341,6 +341,7 @@ async def predict(self, # Get llm_result = await self.llm.run(prompt=_prompt, predict_tokens=predict_tokens, llm_param=llm_param) llm_result: LlmReturn + # Parse Result self.memory_manger.save_context(ask=prompt_text, reply=f"{self.profile.restart_name}:{self.llm.parse_reply(llm_result.reply)}", From cb39661f620925fffed949b4f433d1e0467c1877 Mon Sep 17 00:00:00 2001 From: sudoskys Date: Fri, 27 Jan 2023 15:02:00 +0800 Subject: [PATCH 4/4] =?UTF-8?q?0.2.0=20=E4=BF=AE=E5=A4=8D=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=BA=93=EF=BC=8C=E4=BF=AE=E5=A4=8D=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_kira/client/Optimizer.py | 46 ++++++++++++++++---------------- src/llm_kira/utils/data.py | 2 ++ 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/llm_kira/client/Optimizer.py b/src/llm_kira/client/Optimizer.py index 3796083..72dc10f 100644 --- a/src/llm_kira/client/Optimizer.py +++ b/src/llm_kira/client/Optimizer.py @@ -91,40 +91,50 @@ def run(self) -> list: if self.memory is None: return [] _create_token = self.token_limit - self.extra_token + # 入口检查 if len(memory) - attention < 0: return convert_msgflow_to_list(memory) + # 转换为 + for item in range(len(memory)): + if isinstance(memory[item], Memory_Flow): + memory[item] = memory[item].dict() + memory: list + def forgetting_curve(x): _weight = numpy.exp(-x / 5) * 100 + 10 # 低谷值 _weight = _weight if _weight > 0 else 0 # 高度线 _weight = _weight if _weight < 100 else 100 + # 推底值,防止无法唤起 + _weight = _weight if _weight > 15 else 5 return _weight - # 转换为 - for item in range(len(memory)): - memory[item] = memory[item].dict() - memory: list - # 计算初始保留比并初始化 memory = list(reversed(memory)) for i in range(0, len(memory)): _forget = forgetting_curve(i) - if _forget > 10: + if _forget > 5: memory[i]["content"]["weight"] = [_forget] else: memory[i]["content"]["weight"] = [] memory = list(reversed(memory)) + # 筛选标准发言 + _index = [] + for i in range(0, len(memory) - attention): + ask, reply = MsgFlow.get_content(memory[i], sign=False) + if len(ask) < 1 or len(reply) < 1: + memory[i]["content"]["weight"].append(-1000) + # 相似度检索 for i in range(0, len(memory)): ask, reply = MsgFlow.get_content(memory[i], sign=False) - _diff1 = Utils.cosion_sismilarity(pre=prompt, aft=f"{ask}{reply}") - _diff = _diff1 - score = _diff * 100 - score = score if score < 95 else 1 + _ask_diff = Utils.cosion_sismilarity(pre=prompt, aft=ask) + _ask_diff = _ask_diff * 100 + score = _ask_diff if _ask_diff < 90 else 0 if score != 0: memory[i]["content"]["weight"].append(score) @@ -139,19 +149,10 @@ def forgetting_curve(x): if ir in f"{ask}{reply}": score += 1 _get = (score / full_score) * 100 + _get = _get if _get < 95 else 50 if _get != 0: memory[i]["content"]["weight"].append(_get) # 基准数据,置信为 0.5 百分比 - # 预处理 - for i in range(0, len(memory) - attention): - ask, reply = MsgFlow.get_content(memory[i], sign=False) - if self.tokenizer(f"{ask}{reply}") > 240: - if Detect.get_text_language(sentence=f"{ask}{reply}") == "CN": - _sum = Utils.tfidf_summarization(sentence=f"{ask}{reply}", ratio=0.5) - if len(_sum) > 7: - memory[i]["content"]["ask"] = "info" - memory[i]["content"]["reply"] = _sum - # 进行筛选,计算限制 _msg_flow = [] _msg_return = [] @@ -163,7 +164,8 @@ def forgetting_curve(x): score = sum(memory[i]["content"]["weight"]) level = (score / full_score) * 100 ask, reply = MsgFlow.get_content(memory[i], sign=True) - if level > 30: + # print(ask, reply, level) + if level > 50: _now_token += self.tokenizer(f"{ask}{reply}") if _now_token > _create_token: break @@ -259,8 +261,6 @@ def forgetting_curve(x): score = _ask_diff if _ask_diff < 90 else 0 if score != 0: memory[i]["content"]["weight"].append(score) - if ask == reply: - memory[i]["content"]["ask"] = "" # 主题检索 _key = Utils.tfidf_keywords(prompt, topK=5) diff --git a/src/llm_kira/utils/data.py b/src/llm_kira/utils/data.py index 63f2938..8337a00 100644 --- a/src/llm_kira/utils/data.py +++ b/src/llm_kira/utils/data.py @@ -217,6 +217,8 @@ def get_content(memory_flow: Memory_Flow, sign: bool = False) -> tuple: if not sign and ":" in _ask_ and ':' in _reply_: _ask_ = _ask_.split(":", 1)[1] _reply_ = _reply_.split(":", 1)[1] + if _ask_ == _reply_: + _reply_ = "" return _ask_, _reply_ def saveMsg(self, msg: MemoryItem) -> None: