
garak 生成器接入指南通过 LangChain 与 LangChain Serve 将任意 LLM 纳入漏洞扫描【免费下载链接】garakthe LLM vulnerability scanner项目地址: https://gitcode.com/GitHub_Trending/ga/garak导读本文围绕 garakthe LLM vulnerability scanner生成器插件体系中的garak.generators.langchain与garak.generators.langchain_serve两个模块展开说明如何利用 LangChain 生态的模型接入能力将尚未被 garak 原生封装的外部 LLM 接入漏洞扫描流程。读完本文你将掌握 LangChainLLMGenerator 的模型直连用法与参数配置、LangChainServeLLMGenerator 的 HTTP 服务接入方式并理解 garak 生成器统一的调用约定、响应解析规则与容错策略。garak 的生成器Generator是其三大插件类型probes / buffs / generators之一负责向被测模型发送提示词并取回生成结果。绝大部分官方生成器都针对特定模型服务做了专门封装而 LangChain 生态覆盖了大量模型供应商。为了让 garak 能复用 LangChain 的模型集成能力项目在 garak/generators/langchain.py 中提供了LangChainLLMGenerator并在 garak/generators/langchain_serve.py 中提供了面向 LangChain Serve 部署的LangChainServeLLMGenerator。这两者正好对应两种接入范式进程内直接实例化模型客户端与通过 HTTP API 访问远程部署的模型服务。LangChainLLMGenerator进程内直连 LangChain 支持的 LLM设计定位与职责边界从源码看LangChainLLMGenerator的设计原则非常明确garak 将绝大部分职责委托给 LangChain自身只做最小化的转发。类的文档字符串garak/generators/langchain.py给出了三条清晰约定生成器对 LLM 调用invoke()方法这是 LangChain 各集成中支持面最广的调用方式与 LangChain 相关的环境变量需要在 garak 外部自行配置好例如各云厂商的 API Key不支持 Chain只对接 LangChain 的 LLM 接口本身。这意味着LangChainLLMGenerator不针对任何具体模型做专项校验正如文档所述 No per-LLM specific checking, so make sure the right environment variables are set——环境变量的正确性由使用者负责。类结构与默认参数DEFAULT_PARAMS Generator.DEFAULT_PARAMS | { temperature: 0.750, k: 0, p: 0.75, preset: None, frequency_penalty: 0.0, presence_penalty: 0.0, stop: [], model_provider: None, configurable_fields: None, }它继承自基类Generator.DEFAULT_PARAMSgarak/generators/base.py后者定义了max_tokens150、temperatureNone、top_kNone、context_lenNone、skip_seq_startNone、skip_seq_endNone等通用参数。合并后的完整参数集覆盖了采样温度、核采样、惩罚项、停止序列等常见采样控制项。各参数作用如下参数默认值说明temperature0.750采样温度控制生成随机性k0top-k 采样0 表示不启用p0.75核采样top-p阈值presetNone模型预设配置名透传给 LangChainfrequency_penalty0.0频率惩罚系数presence_penalty0.0存在惩罚系数stop[]停止序列列表model_providerNone模型提供方标识透传给 LangChainconfigurable_fieldsNone需要透传给 LangChaininit_chat_model的可配置字段列表注意k0的语义是不启用 top-k这一点与直接向部分模型服务传参时0 表示不采样的惯例一致而p0.75则是一个相对保守的核采样阈值兼顾多样性与稳定性。此外类还声明了extra_dependency_names [langchain.chat_models]即必须安装 LangChain 的聊天模型模块否则 garak 会在加载时明确报错并提示安装缺失依赖的报错逻辑见 garak/configurable.py。模型实例化init_chat_model 与 unsafe 属性机制_load_unsafe()garak/generators/langchain.py是模型客户端的实际构建入口self.generator self.langchain_chat_models.init_chat_model( self.name, configurable_fieldsself.configurable_fields, **configured_fields )其中configured_fields的构造逻辑是先遍历configurable_fields中列出的字段把 garak 实例上已配置的同名属性收集起来如果 garak 侧配置了api_key且尚未被收集则自动补入api_key。这意味着既可以通过 garak 的配置直接指定 api_key也可以依赖环境变量二者互不冲突。_unsafe_attributes [generator]是 garak 插件框架的一个重要约定该属性持有的是 LangChain 模型对象无法被序列化因此在多进程场景如generate()内部的多 worker 并行下会被排除出序列化状态并在反序列化后通过__setstate__重新加载参见 garak/configurable.py 的__getstate__/__setstate__实现。调用约定invoke 一次、生成一条_call_model()garak/generators/langchain.py实现了与基类的统一接口def _call_model(self, prompt, generations_this_call1): conv self._conversation_to_list(prompt) resp self.generator.invoke(conv) return [Message(resp.content)] if hasattr(resp, content) else [None]它先把 garak 内部的Conversation对象转换为 LangChain 风格的[{role: ..., content: ...}, ...]列表转换逻辑见 garak/generators/base.py 的_conversation_to_list再调用invoke()。响应提取上做了防御处理只有响应对象带有content属性时才构造Message否则返回None——在 garak 的语义中None代表本次调用未取得有效输出记为 miss而不是抛出异常。值得强调的是garak 的generate()框架要求_call_model返回恰好一个元素的列表_verify_target_result会做严格断言见 garak/generators/base.py因此LangChainLLMGenerator每次invoke只产出一条生成结果supports_multiple_generations保持默认的False。若需要多次采样应由上层generate(prompt, generations_this_callN)循环调用完成——当配置了parallel_requests 1时基类会通过 multiprocessing 进程池并行执行_call_model见 garak/generators/base.py。命令行使用方式按类文档说明使用时应通过--target_name指定 LangChain 支持的 LLM 类型名称garak --model_type langchain --target_name gpt-4o --probes promptinject--model_type等价于-t/--target_type与--target_name等价于-n/--model_name的定义见 garak/cli.py。加载器会根据target_typelangchain定位到garak.generators.langchain模块并将target_name作为self.name传入构造函数——self.name最终就是传给init_chat_model的模型名。由于该模块声明了额外依赖langchain.chat_models若环境未安装garak 会直接报错并给出pip install提示。LangChainServeLLMGenerator通过 HTTP 访问 LangChain Serve 部署适用场景并非所有模型都适合进程内直连私有化部署、容器化服务、或未直接集成进 LangChain 库的外部 LLM都可以通过 LangChain Serve 暴露为 HTTP API。LangChainServeLLMGenerator正是为此设计其类文档garak/generators/langchain_serve.py明确指出它通过 HTTP POST 调用 LangChain Serve 的/invoke端点从而利用未被 LangChain 库直接集成的外部 LLM 完成扫描。环境变量与端点构造服务地址通过环境变量LANGCHAIN_SERVE_URI指定例如export LANGCHAIN_SERVE_URIhttp://127.0.0.1:8000/rag-chroma-private初始化时生成器从 URI 的最后一段提取服务名作为self.name并拼接出完整 API 端点self.name self.uri.split(/)[-1] # 例如 rag-chroma-private self.api_endpoint f{self.uri}/invoke # 例如 http://127.0.0.1:8000/rag-chroma-private/invoke测试用例对此做了精确验证设置LANGCHAIN_SERVE_URIhttp://127.0.0.1:8000后generator.name 127.0.0.1:8000、api_endpoint http://127.0.0.1:8000/invoke见 tests/generators/test_langchain_serve.py。模块还提供了_validate_uri()静态方法用urlparse校验 URI 必须同时具备 scheme 与 netlocbad_uri这类非法值会校验失败对应测试见 tests/generators/test_langchain_serve.py。此外DEFAULT_PARAMS在基类参数之上新增了config_hash default它会被拼进请求 URL 的查询参数?config_hashdefault用于在服务端选择不同的运行配置。请求与响应处理_call_model()garak/generators/langchain_serve.py的完整请求流程如下取prompt.last_message().text作为输入文本仅取对话最后一轮不展开整段多轮历史构造POST请求Content-Type与Accept均为application/json载荷格式为{input: prompt_text, config: {}, kwargs: {}}符合 LangServe/invoke的入参规范请求地址为{api_endpoint}?config_hash{config_hash}。错误处理采用分级策略与 garak 宁可记为 miss 也不要中断扫描 的整体哲学一致4xx 客户端错误记录日志并返回[None]记为一次 miss5xx 服务端错误记录日志后重新抛出异常交由上层处理网络层RequestException记录日志并返回[None]响应 JSON 解析失败或缺少output字段记录日志并返回[None]。响应文本提取规则LangServe 的/invoke会把 Runnable 的输出直接放在output字段下但其形态因链路类型而异。_extract_output_text()garak/generators/langchain_serve.py专门处理三种合法形态输出形态示例说明纯字符串{output: Generated text}字符串/LLM 链路的直接输出平铺消息字典{output: {content: ..., type: ai}}聊天模型的序列化消息构造函数形态{output: {lc: 1, type: constructor, id: [...], kwargs: {content: ...}}}LangChain 的构造器序列化形式对于其他任何形态如{error: err val}这类映射、列表输出、缺少output键等一律返回None绝不把对象字符串化后当作模型输出。配套的测试矩阵tests/generators/test_langchain_serve.py 与 tests/_assets/generators/langchain_serve.json覆盖了全部八种场景三种合法形态提取成功、五种异常形态意外字典、列表、缺 output 键、客户端错误、服务端错误行为正确。尤其值得注意的断言是extract({error: err val}) is None——这从测试层面保证了错误对象不会被误当成生成文本污染扫描结果。命令行使用方式由于服务地址来自环境变量命令行只需指定生成器类型即可export LANGCHAIN_SERVE_URIhttp://127.0.0.1:8000/rag-chroma-private garak --model_type langchain_serve --probes promptinject生成器名从 URI 自动提取无需也不应额外传--target_name构造函数签名中name参数默认即为None。两种接入方式的对比与选型维度LangChainLLMGeneratorLangChainServeLLMGenerator接入方式进程内实例化 LangChain 聊天模型客户端HTTP POST 访问 LangServe/invoke端点模型来源LangChain 官方集成列表内的模型任意通过 LangServe 暴露的 Runnable/LLM 服务服务地址环境变量 模型名--target_nameLANGCHAIN_SERVE_URI环境变量额外依赖langchain.chat_models无仅需requests多轮对话转换完整Conversation为消息列表仅取最后一轮消息响应解析提取resp.content按字符串/平铺字典/构造器三种形态解析output失败策略无 content 属性则返回None4xx/网络/解析失败返回None5xx 抛出选型建议若目标模型已被 LangChain 集成且环境可直接访问如各类云 API优先使用LangChainLLMGenerator它能保留完整多轮上下文若模型以私有服务形式部署、或需要复用已有 LangServe 应用如 RAG 链路则应使用LangChainServeLLMGenerator。与 garak 生成器体系的联动机制两个生成器都遵循 garak 的统一插件契约这一点在测试中被强制校验tests/generators/test_generators.py必须实现_call_model(prompt, generations_this_call)且prompt类型注解为Conversation、返回List[Union[None, Message]]必须通过generate()对外提供服务generate与_call_model的签名均有测试覆盖test_generator_signatureDEFAULT_PARAMS中的每个参数必须被_supported_params支持否则test_generator_structure会失败。LangChainLLMGenerator因依赖第三方模型名限制被排除在通用实例化测试之外见 tests/generators/test_generators.py而LangChainServeLLMGenerator参与了通用结构测试与签名测试并拥有独立的 HTTP 行为测试套件。基类generate()garak/generators/base.py在两者之上统一提供了 seed 设置、skip 序列清理、多次生成与多进程并行等能力因此无论选择哪种 LangChain 接入方式garak 的探测流程probes 构造提示词 → 生成器取回响应 → detectors 判定都能无缝衔接。使用前提与限制依赖安装LangChainLLMGenerator需要额外安装langchain.chat_models缺失时 garak 会在加载插件时抛出ModuleNotFoundError并提示安装命令。环境变量两类生成器都不处理模型服务的鉴权细节。直连方式下各云厂商的 API Key 等环境变量需自行配置Serve 方式下需确保LANGCHAIN_SERVE_URI指向可达的服务地址。能力边界不支持 LangChain Chain、Agent 等复合结构仅对接 LLM 级接口Serve 方式仅取对话最后一轮不适合需要完整多轮上下文的场景。响应契约LangServe 端返回的output若不符合字符串/平铺字典/构造器三种形态将被记为 missNone而非报错这是有意为之的容错设计避免错误对象污染扫描统计。【免费下载链接】garakthe LLM vulnerability scanner项目地址: https://gitcode.com/GitHub_Trending/ga/garak创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考