Skip to main content

阿里通义大模型与 LangChainGo 集成案例

概述

本案例将展示如何将阿里通义大模型(如通义千问)与 LangChainGo 框架集成,实现文本生成、对话交互等功能。通义大模型是阿里巴巴达摩院开发的大语言模型,具有强大的中文理解和生成能力,结合 LangChainGo 可以快速构建复杂的 AI 应用。

环境准备

前提条件

  • Go 1.21+ 开发环境
  • 阿里通义大模型 API 访问密钥(API Key 和 Secret Key)
  • 已安装 langchaingo

获取API key https://bailian.console.aliyun.com/?tab=model#/api-key

安装依赖

go get github.com/tmc/langchaingo
go get github.com/aliyun/alibaba-cloud-sdk-go/services/dashscope

实现代码

1. 通义大模型客户端实现

首先,我们需要实现一个 LangChainGo 兼容的通义大模型客户端:

package main

import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/aliyun/alibaba-cloud-sdk-go/services/dashscope"
"github.com/tmc/langchaingo/llms"
)

// TongyiLLM 通义大模型客户端
type TongyiLLM struct {
apiKey string
modelName string
client *dashscope.Client
}

// NewTongyi 创建新的通义大模型实例
func NewTongyi(apiKey string, modelName string) (*TongyiLLM, error) {
client, err := dashscope.NewClientWithAccessKey("cn-beijing", apiKey)
if err != nil {
return nil, err
}

return &TongyiLLM{
apiKey: apiKey,
modelName: modelName,
client: client,
}, nil
}

// GenerateContent 实现 llms.Model 接口
func (t *TongyiLLM) GenerateContent(ctx context.Context, messages []llms.MessageContent, options ...llms.CallOption) (*llms.ContentResponse, error) {
// 解析调用选项
opts := llms.CallOptions{}
for _, opt := range options {
opt(&opts)
}

// 转换消息格式
var chatMessages []dashscope.ChatMessage
for _, msg := range messages {
role := convertRole(msg.Role)
content := strings.Join(msg.Parts, "\n")
chatMessages = append(chatMessages, dashscope.ChatMessage{
Role: role,
Content: content,
})
}

// 构建请求
req := dashscope.NewChatCompletionRequest()
req.Model = t.modelName
req.Messages = &chatMessages

if opts.Temperature > 0 {
req.Parameters = map[string]interface{}{
"temperature": opts.Temperature,
}
}

// 发送请求
resp, err := t.client.ChatCompletion(req)
if err != nil {
return nil, err
}

// 处理响应
if resp.Body.Code != "200" {
return nil, fmt.Errorf("通义大模型调用失败: %s, %s", resp.Body.Code, resp.Body.Message)
}

// 解析结果
var result map[string]interface{}
if err := json.Unmarshal([]byte(resp.Body.Result), &result); err != nil {
return nil, err
}

choices := result["choices"].([]interface{})
firstChoice := choices[0].(map[string]interface{})
message := firstChoice["message"].(map[string]interface{})
content := message["content"].(string)

return &llms.ContentResponse{
Choices: []llms.ContentChoice{
{
Content: llms.MessageContent{
Role: llms.ChatMessageTypeAI,
Parts: []string{content},
},
},
},
}, nil
}

// 转换角色名称
func convertRole(role llms.ChatMessageType) string {
switch role {
case llms.ChatMessageTypeSystem:
return "system"
case llms.ChatMessageTypeHuman:
return "user"
case llms.ChatMessageTypeAI:
return "assistant"
default:
return "user"
}
}

// 实现其他必要接口
func (t *TongyiLLM) GetNumTokens(text string) int {
// 简单的令牌计数实现,实际应用中可能需要更精确的计算
return len(strings.Fields(text))
}

2. 文本生成示例

使用通义大模型进行文本生成:

package main

import (
"context"
"fmt"
"log"
"os"

"github.com/tmc/langchaingo/llms"
)

func main() {
// 从环境变量获取 API Key
apiKey := os.Getenv("DASHSCOPE_API_KEY")
if apiKey == "" {
log.Fatal("请设置 DASHSCOPE_API_KEY 环境变量")
}

// 创建通义大模型实例,使用通义千问模型
llm, err := NewTongyi(apiKey, "qwen-plus")
if err != nil {
log.Fatal(err)
}

// 简单文本生成
ctx := context.Background()
prompt := "请介绍一下Go语言的主要特点"

// 调用大模型生成内容
result, err := llms.GenerateFromSinglePrompt(ctx, llm, prompt,
llms.WithTemperature(0.7),
)
if err != nil {
log.Fatal(err)
}

fmt.Println("生成结果:")
fmt.Println(result)
}

3. 带记忆的对话示例

结合 LangChainGo 的记忆功能实现多轮对话:

package main

import (
"context"
"fmt"
"log"
"os"

"github.com/tmc/langchaingo/chains"
"github.com/tmc/langchaingo/memory"
"github.com/tmc/langchaingo/prompts"
)

func main() {
// 初始化通义大模型
apiKey := os.Getenv("DASHSCOPE_API_KEY")
if apiKey == "" {
log.Fatal("请设置 DASHSCOPE_API_KEY 环境变量")
}

llm, err := NewTongyi(apiKey, "qwen-plus")
if err != nil {
log.Fatal(err)
}

// 创建对话记忆
chatMemory := memory.NewConversationBufferMemory()

// 创建提示模板
prompt := prompts.NewChatPromptTemplate(
[]prompts.MessageFormatter{
prompts.NewSystemMessagePromptTemplate(
"你是一个友好的助手,帮助用户解答问题。请用中文回答。",
nil,
),
prompts.NewHumanMessagePromptTemplate(
"{{.input}}",
[]string{"input"},
),
},
)

// 创建对话链
chain := chains.NewLLMChain(llm, prompt, chains.WithMemory(chatMemory))

// 对话循环
for {
var input string
fmt.Print("你: ")
fmt.Scanln(&input)

if input == "exit" {
break
}

result, err := chains.Call(context.Background(), chain, map[string]any{"input": input})
if err != nil {
log.Fatal(err)
}

fmt.Println("AI:", result["text"])
}
}

4. 文档摘要示例

使用通义大模型实现文档摘要功能:

package main

import (
"context"
"fmt"
"log"
"os"
"strings"

"github.com/tmc/langchaingo/chains"
"github.com/tmc/langchaingo/documentloaders"
"github.com/tmc/langchaingo/textsplitter"
)

func main() {
// 初始化通义大模型
apiKey := os.Getenv("DASHSCOPE_API_KEY")
if apiKey == "" {
log.Fatal("请设置 DASHSCOPE_API_KEY 环境变量")
}

llm, err := NewTongyi(apiKey, "qwen-plus")
if err != nil {
log.Fatal(err)
}

// 创建摘要链
summaryChain := chains.LoadRefineSummarization(llm)

// 示例文档内容
docContent := `Go语言是一种由Google开发的开源编程语言,于2009年11月正式发布。
它的设计目标是简单、高效、并发支持良好,以及易于学习和使用。

Go语言具有以下主要特点:
1. 简洁的语法:Go语言的语法简洁明了,减少了不必要的语法元素,使代码更易于阅读和编写。
2. 内置并发支持:Go语言通过goroutine和channel提供了简洁而强大的并发编程模型。
3. 静态类型:Go语言是静态类型的,这有助于在编译时捕获错误,提高代码的可靠性。
4. 垃圾回收:Go语言具有自动垃圾回收机制,减轻了开发者的内存管理负担。
5. 跨平台编译:Go语言支持跨平台编译,可以轻松生成不同操作系统的可执行文件。

由于这些特点,Go语言在云原生、微服务、分布式系统等领域得到了广泛应用。`

// 加载并分割文档
docs, err := documentloaders.NewText(strings.NewReader(docContent)).LoadAndSplit(
context.Background(),
textsplitter.NewRecursiveCharacter(),
)
if err != nil {
log.Fatal(err)
}

// 执行摘要
output, err := chains.Call(context.Background(), summaryChain, map[string]any{
"input_documents": docs,
})
if err != nil {
log.Fatal(err)
}

// 输出结果
fmt.Println("文档摘要:")
fmt.Println(output["text"])
}

运行方法

  1. 首先设置环境变量:
export DASHSCOPE_API_KEY="你的阿里通义API密钥"
  1. 运行相应的示例代码:
go run tongyi_example.go

关键技术点解析

  1. 模型适配:实现了 LangChainGo 的 llms.Model 接口,使通义大模型能够无缝集成到 LangChainGo 生态中

  2. 消息转换:处理了通义大模型与 LangChainGo 之间的消息格式差异,包括角色映射和内容转换

  3. 参数配置:支持温度等生成参数的配置,控制输出的随机性

  4. 功能集成:展示了如何将通义大模型与 LangChainGo 的链(Chains)、记忆(Memory)等组件结合使用

扩展方向

  1. 添加流式输出支持:实现 GenerateContentStream 方法,支持实时输出

  2. 完善令牌计数:实现更精确的中文字符令牌计数

  3. 支持更多模型:扩展支持通义大模型家族的其他模型,如 qwen-vl 多模态模型

  4. 工具调用:集成工具调用能力,使通义大模型能够使用外部工具

通过以上案例,我们展示了如何将阿里通义大模型与 LangChainGo 框架集成,利用 LangChainGo 的丰富组件快速构建强大的 AI 应用。