Server - 配置 通义法睿 API 与 大模型服务

欢迎关注我的CSDN:https://spike.blog.csdn.net/

本文地址:https://spike.blog.csdn.net/article/details/160468125

免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。


通义法睿 API 是阿里云基于通义千问大模型技术推出的法律行业垂类人工智能服务接口,专为各类系统和应用提供专业、高效、可集成的智能法律能力。它以千问大模型为基座,经过 5 亿 + 裁判文书、300 万 + 法律法规及海量专业法律数据的专项训练,综合运用模型精调、强化学习、RAG 检索增强、法律 Agent 及司法专属小模型等先进技术,能够精准理解法律语言、推理法律适用、分析复杂案情。

登录阿里云的平台,进入访问控制界面:

1. 创建用户

在【RAM 访问控制】 - 【身份管理】 - 【用户】 - 【创建用户】 中,创建用户,即:

RAM = Resource Access Management,资源访问管理

在【创建用户】中,必须添加登录名称,例如 tongyifarui (通义法睿),即:

必须勾选【使用控制台访问】【使用永久 AccessKey 访问】,建议使用【自定义密码】,即:

必须勾选【我确认必须创建 AccessKey】,创建 AccessKey,即:

2. 权限策略

在【RAM 访问控制】 - 【权限管理】 - 【权限策略】 - 【创建权限策略】 中,创建权限策略,即:

在【创建权限策略】中选择【脚本编辑】,写入通义法睿的权限,即:

添加权限文字,注意替换【账号ID】,参考当前账号,填写一串数字,即:

bash 复制代码
{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "farui:*",
      "Resource": "acs:farui:*:【账号ID(参考当前账号,填写一串数字)】:*"
    }
  ]
}

填写策略名称,例如【FaruiFullAccess】,创建成功,即:

例如【FariFullAccess】权限效果,如下:

3. 关联用户与权限策略

在【用户】选择【新增授权】,即:

搜索选择策略,主要是3个策略【FaruiFullAccess】【AliyunBailianFullAccess】【AliyunBailianDataFullAccess】,即:

最终【用户】-【权限管理】的效果,即:

4. 配置 WorkId

WorkId 的 业务空间ID

在 阿里云 首页 中,选择【业务空间】,即:

在【业务空间管理】中,选择【新增业务空间】,新建业务空间,即【通义法睿】,对于【业务空间名称】,即:

在【通义法睿】中,管理【账号管理】的【权限管理】,即:

在【编辑权限】中,点击【权限名称】选择全部权限,即:

权限:Auth.AccessDenied.WorkSpace

bash 复制代码
Code: Auth.AccessDenied.WorkSpace
Message: 无权访问此工作空间

这说明当前 AccessKey 没有被授权访问工作空间。需要在阿里云控制台做以下检查:

1. 确认 AccessKey 归属:登录阿里云控制台 → 右上角头像 → AccessKey 管理,确认这个 Key 属于创建该工作空间的同一账号
2. 子账号授权:如果使用的是 RAM 子账号的 Key,需要主账号在 RAM 控制台为其授予 FaRui 服务相关权限
3. 工作空间成员:进入通义百炼控制台 → 工作空间管理 → 确认该账号已被添加为成员

5. 推理脚本

测试脚本,如下:

python 复制代码
from __future__ import annotations

import hmac
import hashlib
import json
import os
from datetime import datetime
from urllib.parse import urlparse, urlencode, quote
from typing import Optional

import requests

HOST = "farui.cn-beijing.aliyuncs.com"


def _load_config() -> tuple[str, str, str]:
    """从环境变量读取配置,缺失时抛出明确错误。"""
    key_id = os.environ.get("FARUI_ACCESS_KEY_ID", "")
    key_secret = os.environ.get("FARUI_ACCESS_KEY_SECRET", "")
    workspace_id = os.environ.get("FARUI_WORKSPACE_ID", "")
    missing = [k for k, v in {
        "FARUI_ACCESS_KEY_ID": key_id,
        "FARUI_ACCESS_KEY_SECRET": key_secret,
        "FARUI_WORKSPACE_ID": workspace_id,
    }.items() if not v]
    if missing:
        raise EnvironmentError(
            f"缺少必要的环境变量:{', '.join(missing)}\n"
            "请复制 .env.example 为 .env 并填写对应值,然后执行:\n"
            "  export $(cat .env | xargs)"
        )
    return key_id, key_secret, workspace_id


def rfc3986_encode(value: str) -> str:
    return quote(value, safe="-._~")


def ali_sign(url: str, method: str, headers: dict, body: dict,
             access_key_id: str, access_key_secret: str) -> str:
    url_object = urlparse(url)
    canonical_uri = url_object.path or "/"

    query_params: dict = {}
    if url_object.query:
        for part in url_object.query.split("&"):
            k, _, v = part.partition("=")
            query_params[k] = v
    canonical_query_string = urlencode(
        {rfc3986_encode(k): rfc3986_encode(v) for k, v in sorted(query_params.items())}
    )

    lower_headers = {k.lower(): v for k, v in headers.items()}
    sign_keys = sorted(
        k for k in lower_headers if k.startswith("x-acs-") or k in ("host", "content-type")
    )
    canonical_headers = "".join(f"{k}:{lower_headers[k].strip()}\n" for k in sign_keys)
    signed_headers = ";".join(sign_keys)

    hashed_payload = hashlib.sha256(json.dumps(body, ensure_ascii=False).encode()).hexdigest()

    canonical_request = "\n".join([
        method,
        canonical_uri,
        canonical_query_string,
        canonical_headers,
        signed_headers,
        hashed_payload,
    ])

    algorithm = "ACS3-HMAC-SHA256"
    hashed_canonical_request = hashlib.sha256(canonical_request.encode()).hexdigest()
    string_to_sign = f"{algorithm}\n{hashed_canonical_request}"

    signature = hmac.new(
        access_key_secret.encode(), string_to_sign.encode(), hashlib.sha256
    ).hexdigest()

    return f"{algorithm} Credential={access_key_id},SignedHeaders={signed_headers},Signature={signature}"


def search_law(
    query: str,
    query_keywords: Optional[list[str]] = None,
    page_number: int = 1,
    page_size: int = 10,
) -> dict:
    """法规检索接口。

    Args:
        query: 自然语言检索描述
        query_keywords: 额外关键词列表(可选)
        page_number: 页码,从 1 开始
        page_size: 每页条数,最大 20

    Returns:
        API 响应的 JSON 字典
    """
    access_key_id, access_key_secret, workspace_id = _load_config()

    url = f"https://{HOST}/{workspace_id}/farui/search/law/query"
    body: dict = {
        "appId": "farui",
        "workspaceId": workspace_id,
        "query": query,
        "pageParam": {
            "pageSize": page_size,
            "pageNumber": page_number,
        },
    }
    if query_keywords:
        body["queryKeywords"] = query_keywords

    timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
    headers = {
        "host": HOST,
        "Content-Type": "application/json",
        "x-acs-action": "RunSearchLawQuery",
        "x-acs-version": "2024-06-28",
        "x-acs-date": timestamp,
    }
    headers["Authorization"] = ali_sign(
        url, "POST", headers, body, access_key_id, access_key_secret
    )

    response = requests.post(url, headers=headers, data=json.dumps(body, ensure_ascii=False))
    response.raise_for_status()
    return response.json()


def print_results(result: dict) -> None:
    if result.get("Code") or result.get("code"):
        print(f"请求失败: {result.get('Message') or result.get('message')}")
        return

    data = result.get("data") or result.get("Data") or {}
    items = data.get("lawResult") or data.get("list") or data.get("items") or []
    keywords = data.get("queryKeywords") or []

    print(f"检索关键词:{keywords}")
    print(f"共返回 {len(items)} 条法规:\n")
    for i, item in enumerate(items, 1):
        law = item.get("lawDomain") or item
        name = law.get("lawName") or law.get("title") or "(无标题)"
        pub_date = law.get("releaseYearMonthDate") or law.get("publishDate") or ""
        impl_date = law.get("implementYearMonthDate") or ""
        timeliness = law.get("timeliness") or ""
        issuing_no = law.get("issuingNo") or ""
        similarity = item.get("similarity") or ""

        organ_str = law.get("issuingOrgan") or ""
        try:
            organ = json.loads(organ_str)
            dept = organ.get("level3Name") or organ.get("level2Name") or ""
        except (json.JSONDecodeError, TypeError):
            dept = organ_str

        print(f"{i}. 【{name}】")
        if issuing_no:
            print(f"   文号:{issuing_no}")
        if dept:
            print(f"   发布机构:{dept}")
        if pub_date:
            print(f"   发布日期:{pub_date}")
        if impl_date:
            print(f"   实施日期:{impl_date}")
        if timeliness:
            print(f"   时效性:{timeliness}")
        if similarity:
            print(f"   相似度:{float(similarity):.4f}")
        print()
相关推荐
同聘云2 小时前
阿里云国际站服务器DNS服务器设置成什么?服务器dns怎么填写?
服务器·阿里云·云计算·云小强
code_li1 天前
阿里云 OSS(对象存储)接入 Cloudflare 回源流量全免,每月 1 亿次免费请求
阿里云·云计算
大橙子打游戏1 天前
talkcozy像聊微信一样多项目同时开发
人工智能·vibecoding
SpikeKing2 天前
Server - 配置 SQLBot 智能问数项目
运维·server·sqlbot
圆山猫2 天前
[Linux] Ubuntu 26.04 换阿里云镜像源(最新方法)
linux·ubuntu·阿里云
阿里-于怀2 天前
【无标题】阿里云 AI 网关支持 DeepSeek V4
人工智能·阿里云·云计算·deepseek
新知图书2 天前
通过阿里云百炼平台调用DeepSeek大模型
人工智能·阿里云·云计算·langchian
sevenll072 天前
在 OpenCode 中快速启用 DeepSeek V4 模型
deepseek·vibecoding·opencode