Langchain应用开发之文本翻译
Langchain介绍
随着chatGPT火热,全球关于AIGC的话题也越来越多,也出现了许多AI类型的产品,比如notion
、midjourney
、copilot
等等。
而这些AI应用都离不开大语言模型,只有更好的理解人类语言才能将任务做的更加精准。目前在自然语言理解能力上,OpenAI的GPT4模型可谓是独占鳌头。
相信大家都有用过chatGPT,只要给它一个提示词或者是一些样例,那么它就可以输出一些答案。这里输出的结果可能有好有坏,这就取决于你给的提示词是否好
。
所以可以想象一下:LLM可以帮助我们完成NLP任务,那么提示词就是LLM的编程语言,只要你的提示词能够让LLM完全理解,那么利用LLM来开发NLP任务将大大减少之前机器学习的诸多步骤。
如果我们想利用OpenAI的GPT3.5或者GPT4模型来开发应用,比如:文本翻译、编码、文本总结...
- 首先得先注册获取OPENAI_KEY
- 学习OpenAI的api接口文档
- 自己编写prompt
这是基本的三个步骤,里面的第二步和第三步是核心,也是学习成本比较高的。那么有没有方便的应用开发框架减少我们的开发成本?比如开发一款web应用,Java有Springboot,Python有FastAPI。
对于目前LLM应用开发,Langchain就充当了这么一个应用开发框架的角色,它最大的一个特点就是抽象了模型、抽象了提示词。
官方给它的介绍是:
LangChain 是一个利用语言模型开发应用程序的框架。
它使应用程序能够:
- 数据感知:将语言模型与其他数据源连接起来
- 代理:允许语言模型与其环境交互
开发者文档:python.langchain.com/docs/integr…
langchain应用开发
接下来我将介绍如何使用langchain来开发一款文本翻译工具。
需求: 实现PDF格式文件上传,可以传入需要翻译的语言,然后会将翻译好的内容以文件的形式提供下载。
由于国内的访问限制这里我将利用azure的提供openAI服务,新注册的用户可以免费体验12个月
首先展示一下本应用的一个效果图:

PDF格式解析
这里不是我们的重点,简单介绍一下。
PDF解析我们采用pdfplumber这个python的开源框架
pdfplumber 项目(基于pdfminer.six开发),支持解析PDF文件,获取每个文本字符、矩形和线条的详细信息。此外还支持表格提取和可视化调试。
使用AzureChatOpenAI来构造LLChain
创建一个TranslationChain
类,主要来实现我们的翻译功能
from langchain.chat_models import ChatOpenAI, AzureChatOpenAI
from langchain.chains import LLMChain
from langchain.prompts.chat import (
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
class TranslationChain:
def __init__(self, model_name: str = "gpt-3.5-turbo", verbose: bool = True):
...
这里有一个构造方法:
- model_name:默认使用的是openAI的 gpt3.5模型;
- verbose:表示是否大于langchain日志。
构造提示词模板
在构造函数下面,先构造提示词模板
因为我们使用的是ChatModel
,所以对于的提示词模板需要使用ChatPromptTemplate
# 翻译任务指令始终由 System 角色承担
template = (
"""You are a translation expert, proficient in various languages. \n
Translates {source_language} to {target_language}."""
)
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
# 待翻译文本由 Human 角色输入
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
# 使用 System 和 Human 角色的提示模板构造 ChatPromptTemplate
chat_prompt_template = ChatPromptTemplate.from_messages(
[system_message_prompt, human_message_prompt]
)
创建chatModel实例
接下来在构造函数里面要初始化大语言模型实例
# 为了翻译结果的稳定性,将 temperature 设置为 0
if model_name == "gpt-3.5-turbo":
chat = ChatOpenAI(model_name=model_name, temperature=0, verbose=verbose)
else:
chat = AzureChatOpenAI(
deployment_name="xxx",
openai_api_version="2023-07-01-preview",
openai_api_type="azure",
openai_api_key="xxx",
openai_api_base="https://xxxx.openai.azure.com/",
temperature=0,
verbose=verbose
)
AzureChatOpenAI里面有几个参数是azure提供的openai需要的
- deployment_name:部署的实例名称
- openai_api_key:密钥
- openai_api_base:azure提供的openai访问地址
- openai_api_version:模板版本,有:2023-05-15 和 2023-07-01-preview,2023-07-01-preview可以支持function-calling
初始化LLMChain
提示词模板和模型构造完成之后,就可以构造LLMChain了
self.chain = LLMChain(llm=chat, prompt=chat_prompt_template, verbose=verbose)
创建一个用于翻译工作的方法
通过调用LLMChain的 run
方法,就可以调用模型的api,而且我们有了提示词模板,翻译的目标语言可以动态的传入,其底层就是基于python的f-string的字符串处理
def run(self, text: str, source_language: str, target_language: str) -> (str, bool):
result = ""
try:
result = self.chain.run({
"text": text,
"source_language": source_language,
"target_language": target_language,
})
except Exception as e:
LOG.error(f"An error occurred during translation: {e}")
return result, False
return result, True
结果处理生成文件
对于文本类的生成结果处理比较简单,但是对于表格类型的就需要将文本内容转换为表格。
以下是langchain的日志:
System: You are a translation expert, proficient in various languages.
Translates English to Chinese.
Human: [Fruit, Color, Price (USD)] [Apple, Red, 1.20] [Banana, Yellow, 0.50] [Orange, Orange, 0.80] [Strawberry, Red, 2.50] [Blueberry, Blue, 3.00] [Kiwi, Green, 1.00] [Mango, Orange, 1.50] [Grape, Purple, 2.00]
>Finished chain.
2023-08-28 21:37:23.774 | DEBUG | book.content:set_translation:54 - [translation]
[水果, 颜色, 价格(美元)] [苹果, 红色, 1.20] [香蕉, 黄色, 0.50] [橙子, 橙色, 0.80] [草莓, 红色, 2.50] [蓝莓, 蓝色, 3.00] [猕猴桃, 绿色, 1.00] [芒果, 橙色, 1.50] [葡萄, 紫色, 2.00]
可以发现,传入给模型的格式和模型返回的格式并没法发生变化,那么直接格式进行字符串割接和拼接操作,组成一个pandas对象
import pandas as pd
def set_translation(self, translation, status):
try:
if not isinstance(translation, str):
raise ValueError(f"Invalid translation type. Expected str, but got {type(translation)}")
LOG.debug(f"[translation]\n{translation}")
# Extract column names from the first set of brackets
header = translation.split(']')[0][1:].split(', ')
# Extract data rows from the remaining brackets
data_rows = translation.split('] ')[1:]
# Replace Chinese punctuation and split each row into a list of values
data_rows = [row[1:-1].split(', ') for row in data_rows]
# Create a DataFrame using the extracted header and data
translated_df = pd.DataFrame(data_rows, columns=header)
LOG.debug(f"[translated_df]\n{translated_df}")
self.translation = translated_df
self.status = status
except Exception as e:
LOG.error(f"An error occurred during table translation: {e}")
self.translation = None
self.status = False
使用gradio,生成UI页面
官方文档:Gradio
import sys
import os
import gradio as gr
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
def translation(input_file, source_language, target_language):
LOG.debug(f"[翻译任务]\n源文件: {input_file.name}\n源语言: {source_language}\n目标语言: {target_language}")
output_file_path = Translator.translate_pdf(
input_file.name, source_language=source_language, target_language=target_language)
return output_file_path
def launch_gradio():
iface = gr.Interface(
fn=translation,
title="OpenAI-Translator v2.0(PDF 电子书翻译工具)",
inputs=[
gr.File(label="上传PDF文件"),
gr.Textbox(label="源语言(默认:英文)", placeholder="English", value="English"),
gr.Textbox(label="目标语言(默认:中文)", placeholder="Chinese", value="Chinese")
],
outputs=[
gr.File(label="下载翻译文件")
],
allow_flagging="never"
)
iface.launch(share=True, server_name="0.0.0.0")
if __name__ == "__main__":
# 初始化 translator
#initialize_translator()
# 启动 Gradio 服务
launch_gradio()
需要注意的是,gradio通过 Interface
方法来构造页面
- fn:请求执行的方法
- inputs:请求参数,按照顺序和fn的方法参数匹配。比如这个例子中,fn的方法参数有三个,第一个是文件,第二个是源语言,第三个是目标语言,那么inputs的参数列表需要和它对于上,顺序不能搞乱
- outputs:响应参数
- allow_flagging:服务器是否存储文件
转载自:https://juejin.cn/post/7272282550860578868