!LangChain大语言模型接口层源码与调用机制深度解析(68)

LangChain大语言模型接口层源码与调用机制深度解析

I. 接口层概述

1.1 接口层在LangChain中的定位

LangChain大语言模型接口层是连接外部大语言模型(LLM)与上层应用逻辑的核心枢纽。它通过标准化的接口封装不同厂商的LLM服务,如OpenAI、Anthropic、Hugging Face等,使开发者能够以统一方式调用各类模型,而无需关注底层API细节。这种设计极大提升了框架的扩展性和兼容性,让开发者可以灵活切换模型以适应不同应用场景需求。

1.2 核心功能与设计目标

接口层的核心功能包括:

  1. 模型连接与认证:处理与外部模型服务的连接,管理API密钥、访问令牌等认证信息
  2. 请求标准化:将上层应用的请求转换为符合模型API规范的格式
  3. 响应解析:解析模型返回的响应数据,统一输出格式
  4. 错误处理:捕获调用过程中的异常,提供统一的错误反馈机制

其设计目标是实现"插拔式"的模型接入,通过抽象层将模型差异隐藏,为上层应用提供简洁、统一的调用体验。

1.3 面临的挑战与解决方案

接口层面临的主要挑战包括:

  • API规范差异:不同模型服务商的API参数、请求格式、响应结构各不相同
  • 速率限制处理:各平台对API调用频率、并发量的限制不同
  • 版本兼容性:模型服务更新可能导致接口变动

LangChain通过以下方案应对:

  • 抽象基类设计:定义统一的LLM抽象类,要求具体模型类实现标准方法
  • 配置驱动架构:通过配置文件管理模型参数和认证信息
  • 重试与降级策略:内置重试机制处理速率限制,提供降级方案保障服务可用性
  • 版本适配层:通过适配器模式兼容模型接口版本变化

II. 抽象基类与接口定义

2.1 LLM抽象基类

LangChain通过LLM抽象基类定义大语言模型的标准接口,位于langchain/llms/base.py

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional

class LLM(ABC):
    @abstractmethod
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        """核心调用方法,子类需实现具体调用逻辑"""
        pass
    
    @property
    @abstractmethod
    def _llm_type(self) -> str:
        """返回模型类型标识"""
        pass
    
    def __call__(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        """对外暴露的调用接口,调用子类实现的_call方法"""
        return self._call(prompt, stop)

该基类定义了两个抽象方法:

  • _call:核心调用逻辑,接收提示词和停止序列,返回模型生成结果
  • _llm_type:返回模型类型字符串标识

2.2 接口方法设计解析

2.2.1 _call方法

_call方法是模型调用的核心,其设计要点包括:

  • 输入参数

    • prompt:必选的提示词字符串
    • stop:可选的停止序列列表,用于提前终止生成
  • 返回值:模型生成的文本结果

2.2.2 _llm_type属性

_llm_type属性用于标识模型类型,主要作用:

  1. 方便框架进行类型检查和日志记录
  2. 支持按模型类型进行功能扩展和适配

2.3 接口扩展与兼容性设计

为支持更多功能,接口层采用以下扩展设计:

  • 参数扩展:通过additional_kwargs字典传递额外参数
class MyLLM(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
        temperature = kwargs.get('temperature', 0.7)
        # 使用temperature参数调用模型
  • 异步接口:通过继承AsyncLLM基类实现异步调用
from langchain.llms.base import AsyncLLM

class AsyncMyLLM(AsyncLLM):
    async def _acall(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        # 异步调用实现

III. 具体模型类实现

3.1 OpenAI模型实现

OpenAI模型类位于langchain/llms/openai.py,继承自LLM基类:

from langchain.llms.base import LLM
import openai

class OpenAI(LLM):
    openai_api_key: str
    model_name: str = "text-davinci-003"
    temperature: float = 0.7
    max_tokens: int = 1024

    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        openai.api_key = self.openai_api_key

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response = openai.Completion.create(
            engine=self.model_name,
            prompt=prompt,
            temperature=self.temperature,
            max_tokens=self.max_tokens,
            stop=stop
        )
        return response.choices[0].text.strip()
    
    @property
    def _llm_type(self) -> str:
        return "openai"

关键实现细节:

  1. 初始化:设置OpenAI API密钥,支持通过配置覆盖默认参数
  2. _call方法:调用OpenAI Completion API,解析响应并返回结果
  3. _llm_type:返回"openai"标识

3.2 Hugging Face模型实现

Hugging Face模型类通过HuggingFacePipeline实现,位于langchain/llms/huggingface_pipeline.py

from langchain.llms.base import LLM
from transformers import pipeline

class HuggingFacePipeline(LLM):
    pipeline: Any
    model_kwargs: Dict[str, Any] = {}

    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        self.pipeline = pipeline("text-generation", **self.model_kwargs)

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        result = self.pipeline(prompt, **self.model_kwargs)[0]["generated_text"]
        if stop:
            for s in stop:
                if s in result:
                    result = result[:result.index(s)]
        return result
    
    @property
    def _llm_type(self) -> str:
        return "huggingface_pipeline"

实现要点:

  1. 初始化:基于text-generation任务创建Hugging Face pipeline
  2. _call方法:调用pipeline生成文本,支持停止序列处理
  3. 参数传递:通过model_kwargs传递模型参数

3.3 Anthropic模型实现

Anthropic模型类位于langchain/llms/anthropic.py

from langchain.llms.base import LLM
import anthropic

class Anthropic(LLM):
    anthropic_api_key: str
    model: str = anthropic.DEFAULT_MODEL
    temperature: float = 0
    max_tokens_to_sample: int = 256

    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        self.client = anthropic.Client(self.anthropic_api_key)

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response = self.client.completion(
            prompt=f"{anthropic.HUMAN_PROMPT} {prompt}{anthropic.AI_PROMPT}",
            model=self.model,
            temperature=self.temperature,
            max_tokens_to_sample=self.max_tokens_to_sample,
            stop_sequences=stop
        )
        return response["completion"].strip()
    
    @property
    def _llm_type(self) -> str:
        return "anthropic"

关键逻辑:

  1. 初始化:创建Anthropic客户端,设置API密钥
  2. _call方法:按照Anthropic格式构造请求,解析响应
  3. 格式处理:自动添加HUMAN_PROMPTAI_PROMPT标记

IV. 请求处理流程

4.1 请求参数处理

接口层对请求参数的处理包括:

  1. 参数校验
class OpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        if not isinstance(prompt, str):
            raise ValueError("prompt must be a string")
        # ...
  1. 默认值设置
class OpenAI(LLM):
    temperature: float = 0.7
    def _call(self, prompt: str, stop: Optional[List[str]] = None, temperature: Optional[float] = None) -> str:
        temperature = temperature if temperature is not None else self.temperature
        # ...
  1. 参数转换:将通用参数映射为模型特定参数
class Anthropic(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None, max_tokens: Optional[int] = None) -> str:
        max_tokens_to_sample = max_tokens if max_tokens is not None else self.max_tokens_to_sample
        response = self.client.completion(
            # 使用max_tokens_to_sample参数

4.2 请求构造与发送

以OpenAI为例,请求构造过程:

class OpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        payload = {
            "engine": self.model_name,
            "prompt": prompt,
            "temperature": self.temperature,
            "max_tokens": self.max_tokens,
            "stop": stop
        }
        response = openai.Completion.create(**payload)
        return response.choices[0].text.strip()

关键步骤:

  1. 构建符合OpenAI API规范的请求参数
  2. 使用openai.Completion.create方法发送请求
  3. 解析响应并返回结果

4.3 速率限制处理

接口层通过重试机制处理速率限制:

import openai
import time

class OpenAI(LLM):
    max_retries = 3
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        retries = 0
        while retries < self.max_retries:
            try:
                response = openai.Completion.create(
                    # 请求参数...
                )
                return response.choices[0].text.strip()
            except openai.error.RateLimitError:
                retries += 1
                time.sleep(2 ** retries)
        raise Exception("Max retries exceeded")

处理逻辑:

  1. 捕获RateLimitError异常
  2. 按照指数退避算法进行重试
  3. 达到最大重试次数后抛出异常

V. 响应解析机制

5.1 统一响应格式

接口层将不同模型的响应统一为字符串格式:

class OpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response = openai.Completion.create(
            # 请求参数...
        )
        return response.choices[0].text.strip()

class Anthropic(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response = self.client.completion(
            # 请求参数...
        )
        return response["completion"].strip()

通过提取关键字段并统一返回字符串,屏蔽不同模型的响应差异。

5.2 错误处理与异常封装

接口层对模型返回的错误进行统一封装:

import openai
from langchain.llms.base import LLM

class OpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        try:
            response = openai.Completion.create(
                # 请求参数...
            )
            return response.choices[0].text.strip()
        except openai.error.OpenAIError as e:
            raise ValueError(f"OpenAI API Error: {e}")

处理方式:

  1. 捕获模型API抛出的原始异常
  2. 封装为统一的ValueError异常
  3. 保留原始错误信息便于排查

5.3 结果后处理

对生成结果进行后处理:

  1. 去除空白字符
class OpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response = openai.Completion.create(
            # 请求参数...
        )
        return response.choices[0].text.strip()
  1. 停止序列截断
class HuggingFacePipeline(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        result = self.pipeline(prompt, **self.model_kwargs)[0]["generated_text"]
        if stop:
            for s in stop:
                if s in result:
                    result = result[:result.index(s)]
        return result

VI. 认证与配置管理

6.1 API密钥管理

6.1.1 环境变量配置

以OpenAI为例,通过环境变量获取API密钥:

import os
import openai

class OpenAI(LLM):
    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        openai.api_key = os.environ.get("OPENAI_API_KEY")
        if not openai.api_key:
            raise ValueError("OPENAI_API_KEY environment variable not set")
6.1.2 显式参数传递

支持通过参数直接传递密钥:

llm = OpenAI(openai_api_key="your_api_key")

6.2 模型配置管理

6.2.1 默认参数设置

各模型类定义默认参数:

class OpenAI(LLM):
    model_name: str = "text-davinci-003"
    temperature: float = 0.7
    max_tokens: int = 1024
6.2.2 动态参数覆盖

支持通过实例化参数覆盖默认值:

llm = OpenAI(model_name="gpt-3.5-turbo", temperature=0.5)

6.3 配置文件支持

通过配置文件管理多模型配置:

models:
  - name: openai
    type: openai
    config:
      openai_api_key: your_api_key
      model_name: gpt-3.5-turbo
  - name: anthropic
    type: anthropic
    config:
      anthropic_api_key: your_anthropic_key
      model: claude-v1.3
from langchain.llms import load_llm

llm = load_llm("config.yaml", "openai")

VII. 调用链集成

7.1 与Prompt模板结合

接口层与Prompt模板无缝集成:

from langchain.llms import OpenAI
from langchain import PromptTemplate

llm = OpenAI()
prompt = PromptTemplate(
    input_variables=["question"],
    template="Answer the following question: {question}"
)

formatted_prompt = prompt.format(question="What is the capital of France?")
result = llm(formatted_prompt)

集成方式:

  1. 使用PromptTemplate构造提示词
  2. 将格式化后的提示词传递给LLM接口

7.2 在Chain中的应用

ConversationChain中的应用示例:

from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

llm = OpenAI()
memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm=llm,
    memory=memory
)

response = conversation.predict(input="Hello")

关键流程:

  1. 将LLM实例传入ConversationChain
  2. ConversationChain调用LLM接口生成回复
  3. 结合ConversationBufferMemory管理对话历史

7.3 与Agent的协同

Agent中的调用逻辑:

from langchain.llms import OpenAI
from langchain.agents import load_tools, initialize_agent

llm = OpenAI()
tools = load_tools(["serpapi", "llm-math"], llm=llm)
agent = initialize_agent(tools, llm, agent="zero-shot-react-description")

result = agent.run("Who won the FIFA World Cup in 2022?")

协同机制:

  1. Agent根据任务选择合适工具
  2. 调用LLM进行推理和决策
  3. 整合工具结果生成最终回复

VIII. 异步调用支持

8.1 异步基类定义

AsyncLLM基类定义异步接口:

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional
import asyncio

class AsyncLLM(ABC):
    @abstractmethod

LangChain大语言模型接口层源码与调用机制深度解析

VIII. 异步调用支持

8.1 异步基类定义

AsyncLLM基类定义异步接口:

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional
import asyncio

class AsyncLLM(ABC):
    @abstractmethod
    async def _acall(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        """核心异步调用方法,子类需实现具体异步调用逻辑"""
        pass
    
    @property
    @abstractmethod
    def _llm_type(self) -> str:
        """返回模型类型标识"""
        pass
    
    async def __call__(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        """对外暴露的异步调用接口,调用子类实现的_acall方法"""
        return await self._acall(prompt, stop)

该基类通过_acall方法定义异步调用的核心逻辑,要求子类实现具体的异步请求发送与响应处理。__call__方法使用await关键字确保异步调用的正确执行,保持与同步接口一致的调用方式。

8.2 异步模型类实现

以OpenAI异步实现为例,位于langchain/llms/openai.py

import openai
from langchain.llms.base import AsyncLLM

class AsyncOpenAI(AsyncLLM):
    openai_api_key: str
    model_name: str = "text-davinci-003"
    temperature: float = 0.7
    max_tokens: int = 1024

    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        openai.api_key = self.openai_api_key

    async def _acall(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response = await openai.Completion.acreate(
            engine=self.model_name,
            prompt=prompt,
            temperature=self.temperature,
            max_tokens=self.max_tokens,
            stop=stop
        )
        return response.choices[0].text.strip()
    
    @property
    def _llm_type(self) -> str:
        return "openai"

关键实现点:

  • 调用openai.Completion.acreate发送异步请求,利用OpenAI官方提供的异步接口
  • 使用await等待异步操作完成,获取响应结果并进行解析
  • 保持与同步版本一致的参数处理和返回值格式

8.3 异步调用场景与优势

异步调用在以下场景体现显著优势:

  1. 高并发请求:在处理大量用户请求时,异步调用能充分利用系统资源,避免线程阻塞。例如在一个支持多用户同时提问的问答系统中,异步调用允许同时处理多个用户的请求,提升系统吞吐量。
async def handle_user_requests():
    llm = AsyncOpenAI()
    requests = ["问题1", "问题2", "问题3"]
    tasks = [llm(req) for req in requests]
    results = await asyncio.gather(*tasks)
    return results
  1. I/O密集型操作:由于LLM调用主要是网络I/O操作,异步编程能在等待响应时释放线程,执行其他任务。如在一个结合了数据库查询和LLM调用的应用中,在等待LLM响应的过程中,可以同时进行数据库的其他查询操作。
  2. 提升用户体验:在交互式应用中,异步调用能避免界面卡顿,用户可以在发起请求后继续进行其他操作,无需等待响应返回。

IX. 模型中间件与扩展

9.1 中间件概念与作用

模型中间件是位于接口层与具体模型实现之间的可插拔组件,用于在请求发送前和响应接收后对数据进行处理。其主要作用包括:

  • 日志记录:记录请求和响应信息,便于调试和监控
  • 性能统计:统计模型调用耗时、成功率等指标
  • 数据转换:对输入输出数据进行格式转换或内容修改
  • 安全控制:添加额外的安全验证或数据脱敏处理

9.2 中间件实现方式

LangChain通过装饰器模式实现中间件功能。以日志记录中间件为例:

import functools
from langchain.llms.base import LLM

def log_call(func):
    @functools.wraps(func)
    def wrapper(self, prompt, *args, **kwargs):
        print(f"Calling LLM with prompt: {prompt}")
        start_time = time.time()
        try:
            result = func(self, prompt, *args, **kwargs)
            print(f"LLM call completed in {time.time() - start_time} seconds")
            return result
        except Exception as e:
            print(f"LLM call failed: {e}")
            raise
    return wrapper

class LoggedOpenAI(LLM):
    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        self._call = log_call(self._call)

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        # 实际调用逻辑,这里假设继承自OpenAI的实现
        pass
    
    @property
    def _llm_type(self) -> str:
        return "openai"

上述代码通过log_call装饰器,在调用_call方法前后添加日志记录,不改变原有模型类的核心逻辑,实现了功能扩展的解耦。

9.3 自定义中间件扩展

用户可以根据需求自定义中间件。例如,实现一个性能统计中间件:

import functools
import time
import statistics
from typing import Dict

class PerformanceStats:
    def __init__(self):
        self.timings: Dict[str, list] = {}

    def record_timing(self, name: str, start_time: float, end_time: float):
        if name not in self.timings:
            self.timings[name] = []
        self.timings[name].append(end_time - start_time)

    def get_stats(self, name: str):
        timings = self.timings.get(name, [])
        return {
            "average": statistics.mean(timings) if timings else 0,
            "min": min(timings) if timings else 0,
            "max": max(timings) if timings else 0
        }

def performance_monitor(stats: PerformanceStats):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(self, prompt, *args, **kwargs):
            start_time = time.time()
            try:
                result = func(self, prompt, *args, **kwargs)
                end_time = time.time()
                stats.record_timing(func.__name__, start_time, end_time)
                return result
            except Exception as e:
                end_time = time.time()
                stats.record_timing(func.__name__, start_time, end_time)
                raise
        return wrapper
    return decorator

# 使用示例
stats = PerformanceStats()
class MonitoredOpenAI(LLM):
    def __init__(self, **kwargs: Any):
        super().__init__(**kwargs)
        self._call = performance_monitor(stats)(self._call)

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        # 实际调用逻辑
        pass
    
    @property
    def _llm_type(self) -> str:
        return "openai"

# 获取性能统计信息
print(stats.get_stats("_call"))

通过这种方式,用户可以灵活添加各类中间件,扩展模型接口层的功能。

X. 多模型集成与切换

10.1 多模型配置管理

LangChain支持在一个应用中配置和使用多个大语言模型。通过配置文件实现多模型管理,例如models.yaml

models:
  - name: openai_model
    type: openai
    config:
      openai_api_key: YOUR_OPENAI_KEY
      model_name: gpt-3.5-turbo
  - name: huggingface_model
    type: huggingface_pipeline
    config:
      model_name: distilgpt2
      model_kwargs:
        temperature: 0.8

在代码中加载并使用配置的模型:

from langchain.llms import load_llm

openai_llm = load_llm("models.yaml", "openai_model")
huggingface_llm = load_llm("models.yaml", "huggingface_model")

response1 = openai_llm("使用OpenAI模型回答问题")
response2 = huggingface_llm("使用Hugging Face模型回答问题")

load_llm函数根据配置文件中的type字段,动态实例化对应的模型类,并传入config中的参数。

10.2 模型切换策略

在实际应用中,可能需要根据不同场景切换模型。例如,根据用户输入的复杂程度选择不同能力的模型:

def select_model(user_input: str, models: dict):
    if "复杂计算" in user_input or "深度分析" in user_input:
        return models["openai_model"]
    return models["huggingface_model"]

models = {
    "openai_model": load_llm("models.yaml", "openai_model"),
    "huggingface_model": load_llm("models.yaml", "huggingface_model")
}

user_input = "分析市场趋势"
selected_llm = select_model(user_input, models)
response = selected_llm(user_input)

上述代码通过自定义的select_model函数,根据用户输入内容判断并选择合适的模型,实现灵活的模型切换。

10.3 模型融合应用

除了单独使用模型,还可以将多个模型的结果进行融合。例如,结合OpenAI和Hugging Face模型的回答,生成更全面的回复:

def merge_responses(response1: str, response2: str):
    return f"OpenAI回答:{response1}\nHugging Face回答:{response2}"

openai_llm = load_llm("models.yaml", "openai_model")
huggingface_llm = load_llm("models.yaml", "huggingface_model")

question = "介绍人工智能的发展历史"
response1 = openai_llm(question)
response2 = huggingface_llm(question)

merged_response = merge_responses(response1, response2)
print(merged_response)

通过融合多个模型的输出,可以综合不同模型的优势,提供更丰富、准确的回答。

XI. 版本兼容性与升级策略

11.1 接口版本适配

随着大语言模型服务商更新API,LangChain需要保持兼容性。通过版本适配层处理接口变化,以OpenAI为例:

import openai

class OpenAIVersionAdapter:
    def __init__(self, api_version: str):
        self.api_version = api_version

    def create_completion(self, **kwargs):
        if self.api_version >= "2023-12-01":
            # 使用新版API参数和调用方式
            return openai.Completion.create(**kwargs, api_version=self.api_version)
        return openai.Completion.create(**kwargs)

# 使用示例
adapter = OpenAIVersionAdapter("2023-12-01")
response = adapter.create_completion(
    engine="text-davinci-003",
    prompt="测试问题",
    temperature=0.7
)

OpenAIVersionAdapter类根据指定的API版本,动态调整请求参数和调用方式,确保在模型API更新时,上层调用代码无需修改。

11.2 升级测试与迁移

在LangChain升级时,需要进行全面的兼容性测试:

  1. 单元测试:针对每个模型类编写单元测试,验证核心功能是否正常。例如,对OpenAI模型类编写测试用例:
import unittest
from langchain.llms import OpenAI

class TestOpenAI(unittest.TestCase):
    def test_openai_call(self):
        llm = OpenAI(openai_api_key="TEST_KEY")
        result = llm("测试问题")
        self.assertEqual(isinstance(result, str), True)

if __name__ == '__main__':
    unittest.main()
  1. 集成测试:在实际应用场景中测试模型调用,确保与其他模块的兼容性。例如,在对话链中测试模型升级后的表现。
  2. 迁移指南:为用户提供详细的升级指南,说明API变化和迁移步骤。例如,当OpenAI模型接口参数调整时,在文档中明确指出旧参数与新参数的对应关系,以及代码修改示例。

11.3 长期维护策略

为保证长期兼容性,LangChain采用以下策略:

  • 语义化版本控制:严格遵循语义化版本号规则,明确不同版本的变更范围
  • 弃用警告机制:在计划移除或修改接口前,提前多个版本发出弃用警告,给用户足够的迁移时间
  • 社区反馈机制:通过社区收集用户在升级过程中遇到的问题,及时修复兼容性Bug

XII. 安全性增强机制

12.1 输入验证与过滤

为防止恶意输入导致的安全风险,接口层对输入进行严格验证和过滤:

import re
from langchain.llms.base import LLM

class SafeOpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        # 过滤恶意SQL注入语句
        if re.search(r'(SELECT|INSERT|UPDATE|DELETE|DROP)', prompt, re.IGNORECASE):
            raise ValueError("Invalid input detected")
        return super()._call(prompt, stop)
    
    @property
    def _llm_type(self) -> str:
        return "openai"

上述代码通过正则表达式检测输入中是否包含危险的SQL关键词,若检测到则拒绝请求,防止SQL注入攻击。同时,还可以针对其他类型的恶意输入(如命令注入、XSS攻击相关内容)进行类似的过滤处理。

12.2 输出脱敏处理

对于包含敏感信息的输出结果,进行脱敏处理:

import re
from langchain.llms.base import LLM

class DesensitizedOpenAI(LLM):
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        result = super()._call(prompt, stop)
        # 脱敏邮箱地址
        result = re.sub(r'[\w\.-]+@[\w\.-]+\.\w+', '[脱敏邮箱]', result)
        # 脱敏身份证号码
        result = re.sub(r'\d{17}[\dXx]', '[脱敏身份证号]', result)
        return result
    
    @property
    def _llm_type(self) -> str:
        return "openai"

通过正则表达式匹配敏感信息,并替换为脱敏后的内容,避免在输出中泄露用户隐私数据。

12.3 访问控制与审计

实现基于角色的访问控制(RBAC)和操作审计:

from enum import Enum
from langchain.llms.base import LLM

class Role(Enum):
    ADMIN = "admin"
    USER = "user"
    GUEST = "guest"

class AccessControlledOpenAI(LLM):
    def __init__(self, role: Role, **kwargs: Any):
        super().__init__(**kwargs)
        self.role = role

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        if self.role == Role.GUEST and "敏感操作" in prompt:
            raise PermissionError("Guest role not allowed for this operation")
        return super()._call(prompt, stop)
    
    @property
    def _llm_type(self) -> str:
        return "openai"

# 操作审计日志记录
import logging

logging.basicConfig(filename='llm_access.log', level=logging.INFO)

def log_llm_call(llm, prompt, result):
    logging.info(f"Role: {llm.role}, Prompt: {prompt}, Result: {result}")

# 使用示例
admin_llm = AccessControlledOpenAI(role=Role.ADMIN)
user_llm = AccessControlledOpenAI(role=Role.USER)

admin_result = admin_llm("执行敏感操作")
log_llm_call(admin_llm, "执行敏感操作", admin_result)

try:
    user_result = user_llm("执行敏感操作")
except PermissionError as e:
    log_llm_call(user_llm, "执行敏感操作", str(e))

通过AccessControlledOpenAI类实现基于角色的访问控制,同时使用日志记录每次模型调用的相关信息,便于后续审计和安全分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android 小码蜂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值