CangChain:面向软件与模型厂商,助力终端用户快速开发AI应用

基于Cangjie的多智能体协同框架

分支3Tags0

介绍

苍穹用来形容广阔的天空、壮阔的景象,代表着壮阔、辽阔的意境。比如《诗经》中的“苍苍者天”,《庄子》中的“苍苍乎如在其上”的描述。苍穹常常被用来比喻高远的理想或抱负,也可以指代神话中的天空之神。
苍穹(CangChain)框架服务于软件厂商、模型厂商,帮助终端用户快速开发AI应用。
团队成员来自华为仓颉语言库团队、高校课题组(江南大学/浙江大学...)、社区开发者,是一支横跨学届和业界的开发团队。

特性

  • 🚀 Query优化

  • 🚀 提示词优化

  • 💪 严格的鉴权机制

  • 🛠️ 支持联邦学习

  • 🌍 隐私保护机制

路线

软件架构

架构图

源码目录

.
├── build
│   ├── bin
│   └── cangchain
├── c_src
│   ├── api_request_multi.c
│   ├── build.sh
│   ├── google_search.c
│   ├── hnswlib
│   ├── hnswlibcj.h
│   ├── hnswlib.cpp
│   ├── include
│   ├── onnxruntime_c_api.h
│   ├── onnxruntime_cj_api.c
│   ├── onnx_runtime_wrapper.cc
│   └── README.md
├── doc
│   ├── assets
│   ├── cangchain-project-v3.pdf
│   ├── design.md
│   ├── feature_api.md
│   ├── langchain survey report.pdf
│   ├── privacy_data_training.csv
│   ├── 关于CUDA运行模型.pdf
│   ├── 分词器调研.pdf
│   ├── 提示词优化和向量调研.pdf
│   └── 自主智能体.pdf
├── lib
│   ├── charset
│   ├── crypto4cj
│   ├── libapirequest.so
│   ├── libcrypto.so
│   ├── libduckdb.so
│   ├── libgooglesearch.so
│   ├── libhnswlibcj.so
│   ├── libmycrypto.so
│   ├── libonnxruntime_cj_api.so
│   ├── libonnxruntime_providers_cuda.so
│   ├── libonnxruntime_providers_shared.so
│   ├── libonnxruntime_providers_tensorrt.so
│   ├── libonnxruntime.so -> libonnxruntime.so.1.15.1
│   ├── libonnxruntime.so.1.15.1
│   ├── libonnxutils.so
│   ├── README.md
│   └── uuid4cj
├── LICENSE
├── module.json
├── resource
│   ├── embedding_model.onnx
│   ├── privacy
│   ├── tokenizer.json
│   └── vectordb
├── src
│   ├── agent
│   ├── chain
│   ├── llmapi
│   ├── main.cj
│   ├── onnx
│   ├── onnxrt
│   ├── schema
│   ├── titoken
│   ├── tool
│   └── vdclient
└── test
    ├── HLT
    └── LLT
  • doc 文档目录,用于存放设计、API接口等文档
  • src 仓颉源码目录
  • c_src C语言的源码库,主要存放跨语言操作的封装C库的代码
  • test 测试目录
  • lib 项目依赖的三方库目录,包括C库so、仓颉库cjo等
  • build CangChain项目的编译生成的文件
  • module.json CangChain项目编译的配置文件,cjpm会读取这个文件

接口说明

主要类和函数接口说明详见 API

使用说明

编译构建

cangjie版本: 0.51.4 C语言库的构建:

cd c_src
./build.sh

设置环境变量:

先切换到CangChain项目根目录

cd ../
export CANGCHAIN_HOME=$(pwd)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CANGCHAIN_HOME/lib:$CANGCHAIN_HOME/lib/charset:$CANGCHAIN_HOME/lib/crypto4cj:$CANGCHAIN_HOME/lib/uuid4cj
export CANGJIE_PATH=$CANGCHAIN_HOME/lib:$CANGCHAIN_HOME/lib/charset:$CANGCHAIN_HOME/lib/crypto4cj:$CANGCHAIN_HOME/lib/uuid4cj
export OPENAI_API_KEY=sess-y9JL7f5Y922VDrzonaDuQZmwIfqnkdUq7xqb8oea
export GOOGLE_API_KEY=AIzaSyDtj86vYYVIt2wA4TPpbrerYweQSq4xaX0
export SEARCH_ENGINE_ID=f4ece9b85ae75403b

*CANGCHAIN_HOME是CangChain项目的根目录,OPENAI_API_KEY、GOOGLE_API_KEY、SEARCH_ENGINE_ID是项目测试使用,请勿扩散。

仓颉语言的编译:

cjpm clean
cjpm build

生成的可执行文件的路径:./build/bin/main

功能示例

OpenAI模型交互

功能示例描述:

对输入的语句先进行分词,然后计算embedding

示例代码如下:

import llmapi.*

main() {
  let llm = getLLMInstance(LLMType.OPEN_AI)
  println(llm.query("who are you?"))
  println(llm.query("translate what you have said into Chinese"))
}

执行结果如下:

I am an AI language model developed by OpenAI. I am designed to assist with answering questions and providing information on various topics.
我是由OpenAI开发的AI语言模型。我被设计用于回答问题并提供各种主题的信息。

onnx模型推理

功能示例描述:

加载模型,推理输出结果。

示例代码如下:

from std import collection.*
from std import fs.*
from std import os.*
from std import os.posix.*
from std import math.*
import onnx.*
import titoken.*


func isPrivateData(res:HashMap<String, IDArray>):Int64{
    var arr = softmax(res)
    var maxIndex = argmax(arr)
    return maxIndex;
}

func softmax(res:HashMap<String, IDArray>):ArrayList<Float32>{
    var output = (res["output"] as XDArray<Float32>).getOrThrow()
    var v1:Float32 = output[0,0]
    var v2:Float32 = output[0,1]
    var expv1 =  math.exp(v1)
    var expv2 = math.exp(v2)
    var sum = expv1 + expv2
    var s1 = expv1/sum
    var s2 = expv2/sum
    var arr = ArrayList<Float32>()
    arr.append(s1)
    arr.append(s2)
    return arr
}

func argmax(arr:ArrayList<Float32>):Int64{
    return if(arr[0]>arr[1]){0}else{1}
}

main() {
    let model = ONNXModel(path:getcwd()+"/resource/privacy/privacy_model.onnx", option: CPU)
    println("${model}")
    let tokenizer = Tokenizer(tokensFilePath:getcwd()+"/resource/privacy/tokenizer.json")
    var encodeInput = HashMap<String, IDArray>()
    var attention_mask = [[1, 1, 1, 1, 1, 1, 1],  [1, 1, 1, 1, 1, 1, 0],  [1, 1, 1, 1, 1, 1, 0]]
    encodeInput["input_ids"] = XDArray<Int64>([[101, 3736, 5722, 4689,  102]])
    encodeInput["attention_mask"] = XDArray<Int64>([[1, 1, 1, 1, 1]])
    // let encodeInput = tokenizer(["江苏省"])
    println("encodeInput: ${encodeInput}")
    let output = model(encodeInput)
    println("output: ${output}")
    let result = isPrivateData(output)
    println("result: ${result}")
    if(result == 0){
        println("非隐私数据")
    }else{
        println("隐私数据")
    }
}

执行结果如下:

cpuModel Path: /home/yang/sda/github/cangchain/resource/privacy/privacy_model.onnx
inputs:
        input_ids: [-1 -1]    TYPE_INT64
        attention_mask: [-1 -1]    TYPE_INT64
inputs:
        output: [-1 2]    TYPE_FLOAT

encodeInput: [(input_ids, [[ 101 3736 5722 4689  102]]), (attention_mask, [[1 1 1 1 1]])]
output: [(output, [[-1.070493  0.485676]])]
result: 1
隐私数据

计算embedding

功能示例描述:

对输入的语句先进行分词,然后计算embedding

示例代码如下:

from std import collection.*
from std import os.*
from std import os.posix.*
import titoken.*

main(): Int64 {
    var sentences:Array<String> =  ["苍穹是什么","苍穹"]
    //分词
    let tokenizer = Tokenizer(tokensFilePath: getcwd()+"/resource/privacy/tokenizer.json")
    let embedder = Embedder(modelPath: getcwd()+"/resource/embedding_model.onnx", tokensFilePath:getcwd()+"/resource/tokenizer.json")
    println("tokens: ${tokenizer(sentences)}")
    //计算词嵌入向量
    let sentence_embeddings = embedder(sentences)
    println("embedding: ${sentence_embeddings}")
    return 0 
}

执行结果如下:

tensor.device: cpu
tokens: [(input_ids, [[ 101 5721 4957  102  784  720  102]
 [ 101 5721 4957  102  784  720  102]]), (token_type_ids, [[0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0]]), (attention_mask, [[1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]])]
embedding: [[0.010859, -0.030754, -0.044018, 0.058661, -0.166377, -0.056781, -0.050275, ..., 0.076615, 0.034190], [0.010859, -0.030754, -0.044018, 0.058661, -0.166377, -0.056781, -0.050275, -0.043021, -0.039094, -0.065006, ..., 0.076615, 0.034190]]

本地向量数据访问

功能示例描述: 在本地构建向量数据,文本相似度计算,

示例代码如下:

from std import collection.*
from std import os.*
from std import os.posix.*
from std import fs.*

import titoken.*
import vdclient.*


main(){
    //创建Client
    let vdclient = Client(persist_directory: getcwd()+"/resource/vectordb/")

    //创建collection
    let meta_data = HashMap<String, String>([("author","cangchain"),("name", "test")])
    let vdclient_collection = vdclient.create_collection("test", meta_data)

    //添加文本
    println("添加文本")
    let documents = Array<String>(["苍穹用来形容广阔的天空、壮阔的景象,代表着壮阔、辽阔的意境。比如《诗经》中的“苍苍者天”,《庄子》中的“苍苍乎如在其上”的描述。苍穹常常被用来比喻高远的理想或抱负,也可以指代神话中的天空之神。","服务于软件厂商、模型厂商,帮助终端用户快速开发AI应用"])
    let metadata1 = HashMap<String, String>(("doc66","id66"))
    let metadata2 = HashMap<String, String>(("doc67","id67"))
    let isadd = vdclient_collection.add(Array<Int32>([66,67]), documents, Array<HashMap<String, String>>([metadata1,metadata2]))
    if (isadd) {
        println("添加成功!")
    }

    //更新文本
    println("\n更新文本")
    let update_id = Array<Int32>([1])
    let update_text = "PyTorch 提供特定于领域的库,如 TorchText, TorchVision 和 TorchAudio,所有这些库都包含数据集。我们将Dataset作为参数传递给DataLoader。这将在我们的数据集上包装一个迭代器,并支持自动批处理、采样、随机打乱和多进程数据加载。 在这里,我们定义了一个大小为64的批处理,即 DataLoader 迭代器中的每个元素都会返回一个由64个特征和标签组成的批次数据。"
    println("更新内容:${update_text}")
    let isupdate = vdclient_collection.update(update_id, None, Array<String>([update_text]), None)
    if (isupdate) {
        println("更新成功!")
    }

    //query
    println("\nQuery_1")
    let query_text = "PyTorch"
    let top_k: Int32 = 1
    println("Query: ${query_text}")
    let query_res = vdclient_collection.query(Array<String>([query_text]), top_k, None)
    let res_doc = query_res[0][0][3]
    println("doc信息:")
    println("内容:${res_doc}")
    println("dist:${query_res[1][0]}")

    println("\nQuery_2")
    let query_text2 = "苍穹是什么"
    let top_k2: Int32 = 1
    println("Query2: ${query_text2}")
    let query_res2 = vdclient_collection.query(Array<String>([query_text2]), top_k2, None)
    let res_doc2 = query_res2[0][0][3]
    println("doc信息:")
    println("内容:${res_doc2}")
    println("dist:${query_res2[1][0]}")

    //结束Client
    let kill = vdclient.end()
}

执行结果如下:

tensor.device: cpu
添加文本
添加成功!

更新文本
更新内容:PyTorch 提供特定于领域的库,如 TorchText, TorchVision 和 TorchAudio,所有这些库都包含数据集。我们将Dataset作为参数传递给DataLoader。这将在我们的数据集上包装一个迭代器,并支持自动批处理、采样、随机打乱和多进程数据加载。 在这里,我们定义了一个大小为64的批处理,即 DataLoader 迭代器中的每个元素都会返回一个由64个特征和标签组成的批次数据。
更新成功!

Query_1
Query: PyTorch
doc信息:
内容:服务于软件厂商、模型厂商,帮助终端用户快速开发AI应用
dist:0.532009

Query_2
Query2: 苍穹是什么
doc信息:
内容:服务于软件厂商、模型厂商,帮助终端用户快速开发AI应用
dist:1.007491
成功保存!

功能示例描述:

利用谷歌的search的api,获得专业知识和答案,以减轻大模型的幻觉。

示例代码如下:

from std import collection.*
from std import fs.*
import titoken.*
import vdclient.*
import tool.*

main(){
    let google_tool = GoogleSearchRun()
    let result: String = google_tool.run("cangjie")
    println("result: ${result}")
    return 0
}

执行结果如下:

result:  "Cangjie ... This article is about the legendary figure. For the typing method, see Cangjie input method. Cangjie [tsʰáŋ.tɕjě] (simplified Chinese: 仓颉; ...",

开源协议

MIT

参与贡献

欢迎给我们提交PR,欢迎给我们提交Issue,欢迎参与任何形式的贡献。

项目介绍

基于Cangjie的多智能体协同框架

定制我的领域

下载使用量

0

项目总下载次数(含Clone、Pull、 zip 包及 release 下载),每日凌晨更新

语言类型

C++77.27%
Cangjie14.25%
C8.26%
Python0.16%
Shell0.05%