lmdeploy.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import warnings
  2. import pipmaster as pm # Pipmaster for dynamic library install
  3. # install specific modules
  4. if not pm.is_installed("lmdeploy"):
  5. pm.install("lmdeploy[all]")
  6. from lightrag.exceptions import (
  7. APIConnectionError,
  8. RateLimitError,
  9. APITimeoutError,
  10. )
  11. from tenacity import (
  12. retry,
  13. stop_after_attempt,
  14. wait_exponential,
  15. retry_if_exception_type,
  16. )
  17. from functools import lru_cache
  18. @lru_cache(maxsize=1)
  19. def initialize_lmdeploy_pipeline(
  20. model,
  21. tp=1,
  22. chat_template=None,
  23. log_level="WARNING",
  24. model_format="hf",
  25. quant_policy=0,
  26. ):
  27. from lmdeploy import pipeline, ChatTemplateConfig, TurbomindEngineConfig
  28. lmdeploy_pipe = pipeline(
  29. model_path=model,
  30. backend_config=TurbomindEngineConfig(
  31. tp=tp, model_format=model_format, quant_policy=quant_policy
  32. ),
  33. chat_template_config=(
  34. ChatTemplateConfig(model_name=chat_template) if chat_template else None
  35. ),
  36. log_level="WARNING",
  37. )
  38. return lmdeploy_pipe
  39. @retry(
  40. stop=stop_after_attempt(3),
  41. wait=wait_exponential(multiplier=1, min=4, max=10),
  42. retry=retry_if_exception_type(
  43. (RateLimitError, APIConnectionError, APITimeoutError)
  44. ),
  45. )
  46. async def lmdeploy_model_if_cache(
  47. model,
  48. prompt,
  49. system_prompt=None,
  50. history_messages=[],
  51. enable_cot: bool = False,
  52. chat_template=None,
  53. model_format="hf",
  54. quant_policy=0,
  55. **kwargs,
  56. ) -> str:
  57. """Run lmdeploy generation with LightRAG-compatible shims.
  58. Structured output note:
  59. - This adapter does not support OpenAI-style ``response_format`` JSON mode.
  60. - If callers pass ``response_format``, it is stripped before generation.
  61. - Deprecated ``keyword_extraction`` and ``entity_extraction`` booleans are
  62. accepted only as compatibility shims; they emit warnings and are ignored.
  63. Args:
  64. model (str): The path to the model.
  65. It could be one of the following options:
  66. - i) A local directory path of a turbomind model which is
  67. converted by `lmdeploy convert` command or download
  68. from ii) and iii).
  69. - ii) The model_id of a lmdeploy-quantized model hosted
  70. inside a model repo on huggingface.co, such as
  71. "InternLM/internlm-chat-20b-4bit",
  72. "lmdeploy/llama2-chat-70b-4bit", etc.
  73. - iii) The model_id of a model hosted inside a model repo
  74. on huggingface.co, such as "internlm/internlm-chat-7b",
  75. "Qwen/Qwen-7B-Chat ", "baichuan-inc/Baichuan2-7B-Chat"
  76. and so on.
  77. chat_template (str): needed when model is a pytorch model on
  78. huggingface.co, such as "internlm-chat-7b",
  79. "Qwen-7B-Chat ", "Baichuan2-7B-Chat" and so on,
  80. and when the model name of local path did not match the original model name in HF.
  81. tp (int): tensor parallel
  82. prompt (Union[str, List[str]]): input texts to be completed.
  83. do_preprocess (bool): whether pre-process the messages. Default to
  84. True, which means chat_template will be applied.
  85. skip_special_tokens (bool): Whether or not to remove special tokens
  86. in the decoding. Default to be True.
  87. do_sample (bool): Whether or not to use sampling, use greedy decoding otherwise.
  88. Default to be False, which means greedy decoding will be applied.
  89. """
  90. if enable_cot:
  91. from lightrag.utils import logger
  92. logger.debug(
  93. "enable_cot=True is not supported for lmdeploy and will be ignored."
  94. )
  95. try:
  96. import lmdeploy
  97. from lmdeploy import version_info, GenerationConfig
  98. except Exception:
  99. raise ImportError("Please install lmdeploy before initialize lmdeploy backend.")
  100. kwargs.pop("hashing_kv", None)
  101. # lmdeploy has no JSON mode; drop response_format and warn when legacy
  102. # boolean shim flags are set.
  103. if kwargs.pop("keyword_extraction", False):
  104. warnings.warn(
  105. "lmdeploy_model_if_cache(keyword_extraction=True) is deprecated; "
  106. "pass response_format={'type': 'json_object'} instead.",
  107. DeprecationWarning,
  108. stacklevel=2,
  109. )
  110. if kwargs.pop("entity_extraction", False):
  111. warnings.warn(
  112. "lmdeploy_model_if_cache(entity_extraction=True) is deprecated; "
  113. "pass response_format={'type': 'json_object'} instead.",
  114. DeprecationWarning,
  115. stacklevel=2,
  116. )
  117. kwargs.pop("response_format", None)
  118. max_new_tokens = kwargs.pop("max_tokens", 512)
  119. tp = kwargs.pop("tp", 1)
  120. skip_special_tokens = kwargs.pop("skip_special_tokens", True)
  121. do_preprocess = kwargs.pop("do_preprocess", True)
  122. do_sample = kwargs.pop("do_sample", False)
  123. gen_params = kwargs
  124. version = version_info
  125. if do_sample is not None and version < (0, 6, 0):
  126. raise RuntimeError(
  127. "`do_sample` parameter is not supported by lmdeploy until "
  128. f"v0.6.0, but currently using lmdeloy {lmdeploy.__version__}"
  129. )
  130. else:
  131. do_sample = True
  132. gen_params.update(do_sample=do_sample)
  133. lmdeploy_pipe = initialize_lmdeploy_pipeline(
  134. model=model,
  135. tp=tp,
  136. chat_template=chat_template,
  137. model_format=model_format,
  138. quant_policy=quant_policy,
  139. log_level="WARNING",
  140. )
  141. messages = []
  142. if system_prompt:
  143. messages.append({"role": "system", "content": system_prompt})
  144. messages.extend(history_messages)
  145. messages.append({"role": "user", "content": prompt})
  146. gen_config = GenerationConfig(
  147. skip_special_tokens=skip_special_tokens,
  148. max_new_tokens=max_new_tokens,
  149. **gen_params,
  150. )
  151. response = ""
  152. async for res in lmdeploy_pipe.generate(
  153. messages,
  154. gen_config=gen_config,
  155. do_preprocess=do_preprocess,
  156. stream_response=False,
  157. session_id=1,
  158. ):
  159. response += res.response
  160. return response