Databricks
Databricks 数据湖平台将数据、分析和人工智能统一在一个平台上。
这个示例笔记本展示了如何将 Databricks 端点封装为 LangChain 中的 LLMs。 它支持两种端点类型:
- 服务端点,推荐用于生产和开发,
- 集群驱动程序代理应用,推荐用于交互式开发。
from langchain.llms import Databricks
封装一个服务端点
先决条件:
- 已经注册并部署了一个 LLM 到 Databricks 服务端点。
- 您对端点具有 "Can Query" 权限。
预期的 MLflow 模型签名是:
- 输入:[{"name": "prompt", "type": "string"}, {"name": "stop", "type": "list[string]"}]
- 输出:[{"type": "string"}]
如果模型签名不兼容或者您想插入额外的配置,可以相应地设置 transform_input_fn 和 transform_output_fn。
# 如果在 "single user" 或 "no isolation shared" 模式下运行附加到交互式集群的 Databricks 笔记本,
# 您只需要指定端点名称即可创建一个 `Databricks` 实例,以查询同一工作区中的服务端点。
llm = Databricks(endpoint_name="dolly")
llm("你好吗?")
    '很高兴听到你身体健康,一如既往地感谢你。'
llm("你好吗?", stop=["。"])
    '好'
# 否则,您可以手动指定 Databricks 工作区主机名和个人访问令牌,
# 或分别设置 `DATABRICKS_HOST` 和 `DATABRICKS_TOKEN` 环境变量。
# 请参阅 https://docs.databricks.com/dev-tools/auth.html#databricks-personal-access-tokens
# 我们强烈建议不要在笔记本中明确暴露 API 令牌。
# 您可以使用 Databricks 密钥管理器来安全地存储 API 令牌。
# 请参阅 https://docs.databricks.com/dev-tools/databricks-utils.html#secrets-utility-dbutilssecrets
import os
os.environ["DATABRICKS_TOKEN"] = dbutils.secrets.get("myworkspace", "api_token")
llm = Databricks(host="myworkspace.cloud.databricks.com", endpoint_name="dolly")
llm("你好吗?")
    '我很好。谢谢!'
# 如果服务端点接受额外的参数,比如 `temperature`,
# 您可以在 `model_kwargs` 中设置它们。
llm = Databricks(endpoint_name="dolly", model_kwargs={"temperature": 0.1})
llm("你好吗?")
    '我很好。'
# 如果服务端点期望不同的输入模式并且不返回 JSON 字符串,
# 或者您想在其上应用提示模板,则使用 `transform_input_fn` 和 `transform_output_fn`。
def transform_input(**request):
    full_prompt = f"""{request["prompt"]}
    言简意赅。
    """
    request["prompt"] = full_prompt
    return request
llm = Databricks(endpoint_name="dolly", transform_input_fn=transform_input)
llm("你好吗?")
    '我很好。你呢?'
封装一个集群驱动程序代理应用
先决条件:
- 在 "single user" 或 "no isolation shared" 模式下的 Databricks 交互式集群上加载了一个 LLM。
- 在驱动程序节点上运行一个本地 HTTP 服务器,使用 HTTP POST 和 JSON 输入/输出来为模型提供服务,路径为 "/"。
- 它使用一个介于 [3000, 8000]之间的端口号,并监听驱动程序 IP 地址或仅仅是0.0.0.0,而不是仅限于 localhost。
- 您对集群具有 "Can Attach To" 权限。
预期的服务器模式(使用 JSON 模式)是:
- 输入:{"type": "object",
 "properties": {
 "prompt": {"type": "string"},
 "stop": {"type": "array", "items": {"type": "string"}}},
 "required": ["prompt"]}
- 输出:{"type": "string"}
如果服务器模式不兼容或者您想插入额外的配置,可以使用 transform_input_fn 和 transform_output_fn。
以下是一个运行驱动程序代理应用来提供 LLM 服务的最小示例:
from flask import Flask, request, jsonify
import torch
from transformers import pipeline, AutoTokenizer, StoppingCriteria
model = "databricks/dolly-v2-3b"
tokenizer = AutoTokenizer.from_pretrained(model, padding_side="left")
dolly = pipeline(model=model, tokenizer=tokenizer, trust_remote_code=True, device_map="auto")
device = dolly.device
class CheckStop(StoppingCriteria):
    def __init__(self, stop=None):
        super().__init__()
        self.stop = stop or []
        self.matched = ""
        self.stop_ids = [tokenizer.encode(s, return_tensors='pt').to(device) for s in self.stop]
    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs):
        for i, s in enumerate(self.stop_ids):
            if torch.all((s == input_ids[0][-s.shape[1]:])).item():
                self.matched = self.stop[i]
                return True
        return False
def llm(prompt, stop=None, **kwargs):
  check_stop = CheckStop(stop)
  result = dolly(prompt, stopping_criteria=[check_stop], **kwargs)
  return result[0]["generated_text"].rstrip(check_stop.matched)
app = Flask("dolly")
@app.route('/', methods=['POST'])
def serve_llm():
  resp = llm(**request.json)
  return jsonify(resp)
app.run(host="0.0.0.0", port="7777")
一旦服务器运行起来,您可以创建一个 Databricks 实例来封装它作为一个 LLM。
# 如果在运行应用的集群上附加了一个 Databricks 笔记本,
# 您只需要指定驱动程序端口即可创建一个 `Databricks` 实例。
llm = Databricks(cluster_driver_port="7777")
llm("你好吗?")
    '你好,谢谢你的关心。很高兴听到你身体健康。'
# 否则,您可以手动指定要使用的集群 ID,
# 以及 Databricks 工作区主机名和个人访问令牌。
llm = Databricks(cluster_id="0000-000000-xxxxxxxx", cluster_driver_port="7777")
llm("你好吗?")
    '我很好。你呢?'
# 如果应用接受额外的参数,比如 `temperature`,
# 您可以在 `model_kwargs` 中设置它们。
llm = Databricks(cluster_driver_port="7777", model_kwargs={"temperature": 0.1})
llm("你好吗?")
    '我很好。很高兴认识你。'
# 如果应用期望不同的输入模式并且不返回 JSON 字符串,
# 或者您想在其上应用提示模板,则使用 `transform_input_fn` 和 `transform_output_fn`。
def transform_input(**request):
    full_prompt = f"""{request["prompt"]}
    言简意赅。
    """
    request["prompt"] = full_prompt
    return request
def transform_output(response):
    return response.upper()
llm = Databricks(
    cluster_driver_port="7777",
    transform_input_fn=transform_input,
    transform_output_fn=transform_output,
)
llm("你好吗?")
    '我很好,谢谢。'
