金融AI:零样本到少样本的智能进化
一.项目背景
在当今金融数据爆发式增长的当下,如何从海量信息中挖掘价值以辅助决策、规避风险,已成为行业痛点。随着人工智能技术的成熟,将其应用于金融数据分析已成为热门趋势。这不仅能提升金融服务的精准度与效率,更能有效辅助投资者优化决策,因此该领域的研究兼具理论价值与现实意义。
二.项目任务和方法介绍
项目任务主要分为三个业务场景,分别为文本分类,文本信息抽取,文本匹配。而对应选择的大模型为deepseek,采用思想是基于Few-Shot+Zero-Shot以及Instrunction的思想,来设计对应prompt,从而完成对应项目的三个业务。
2.1 什么是Shot
"Shot"在机器学习中指的是样本数量,即模型在完成任务前能看到多少个示例。比如下面3个shot的对应含义及例子数量对比:
类型 含义 示例数量 Zero-Shot 零样本学习 0个示例 One-Shot 单样本学习 1个示例 Few-Shot 少样本学习 少量示例(通常1-5个)
2.2 Zero-Shot(零样本)
Zero-Shot是指模型在没有任何示例的情况下,仅通过任务描述直接完成任务。
优点:简单快捷、节省token、适合常见任务
缺点:复杂任务可能效果不佳
2.3 Few-Shot(少样本)
Few-Shot(少样本)是指在提示中提供少量输入-输出示例,让模型通过"上下文学习"理解任务模式。
优点:能处理复杂任务、输出格式更可控、准确率更高
缺点:占用更多token、需要精心设计示例
2.4 Instruction(指令微调)
是指通过大量"指令-期望输出"配对数据对模型进行训练,让模型更好地理解和遵循人类指令。也就是要使用预训练模型,在指令微调的条件下,使模型更能理解人类意图,通过这个过程得到的模型对于Zero-Shot能力有着很大的提升。
三种关系图如下所示:
2.5 总结
建议:
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 简单常见任务 | Zero-Shot | 快速高效 |
| 复杂/特殊格式任务 | Few-Shot | 示例能明确期望 |
| 需要稳定专业输出 | Instruction+Few-Shot | 双重保障 |
| 推理类问题 | Zero-Shot+CoT | 让模型逐步思考 |
总之Zero-Shot是"直接下命令",Few-Shot是"先看例子再干活",Instruction是"提前培训让员工更懂你"。三者结合使用,能让大语言模型发挥最大价值!
三.环境准备
此项目运行所需要安装的相关依赖包如下所示:
四.实现金融文本分类任务
4.1 介绍
列举一个例子:
- 下面几段文本来自某平台发布的金融领域文本:
1."今日,央行发布公告宣布降低利率,以刺激经济增长。这一降息举措将影响贷款利率,并在未来几个季度内对金融市场产生影响。", 2."ABC公司今日发布公告称,已成功完成对XYZ公司股权的收购交易。本次交易是ABC公司在扩大业务范围、加强市场竞争力方面的重要举措。据悉,此次收购将进一步巩固ABC公司在行业中的地位,并为未来业务发展提供更广阔的发展空间。详情请见公司官方网站公告栏", 3."公司资产负债表显示,公司偿债能力强劲,现金流充足,为未来投资和扩张提供了坚实的财务基础。", 4."最新的分析报告指出,可再生能源行业预计将在未来几年经历持续增长,投资者应该关注这一领域的投资机会",该任务目的是期望模型能够帮助我们识别出这4段话中,每一句话描述的是一个什么类型的报告。
因此,我们期望模型输出的结果为:
['新闻报道', '公司公告', '财务公告 '分析师报告']4.2 对应代码实现
导入必要的包以及样例:
# 利用LLM进行文本分类任务 from rich import print from rich.console import Console import requests import json DEEPSEEK_API_KEY = "your_deepseek_api_key" # 替换成你的DeepSeek API Key DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1/chat/completions" # 基础地址 MODEL_NAME = "deepseek-chat" # 可根据需求调整 # 提供所有类别以及每个类别下的样例 class_examples = { '新闻报道': '今日,股市经历了一轮震荡,受到宏观经济数据和全球贸易紧张局势的影响。投资者密切关注美联储可能的政策调整,以适应市场的不确定性。', '财务报告': '本公司年度财务报告显示,去年公司实现了稳步增长的盈利,同时资产负债表呈现强劲的状况。经济环境的稳定和管理层的有效战略执行为公司的健康发展奠定了基础。', '公司公告': '本公司高兴地宣布成功完成最新一轮并购交易,收购了一家在人工智能领域领先的公司。这一战略举措将有助于扩大我们的业务领域,提高市场竞争力', '分析师报告': '最新的行业分析报告指出,科技公司的创新将成为未来增长的主要推动力。云计算、人工智能和数字化转型被认为是引领行业发展的关键因素,投资者应关注这些趋势' }构建init_prompt()函数
# 构建init_prompt()函数 prompt设计 def init_prompt(): # 初始化前置prompt,便于模型做 incontext Learning class_list = list(class_examples.keys()) pre_history = [ { "role": "user", "content": f'现在你是一个文本分类器,需要按照要求将我给你的句子进行分类:{class_list}类别中。' }, { "role": "assistant", "content": "好的。" } ] # 补充少样本示例到对话历史 for _type, example in class_examples.items(): pre_history.append({ "role": "user", "content": f'"{example}"是{class_list}里的什么类别?' }) pre_history.append({ "role": "assistant", "content": _type }) return {'class_list': class_list, 'pre_history': pre_history}实现文本分类
# 实现文本分类 def inference( sentences: list, # 待推理的句子。 custom_settings: dict # 初始设定,包含人为给定的 few-shot example。 ): console = Console() # 初始化console用于状态提示 headers = { "Content-Type": "application/json", "Authorization": f"Bearer {DEEPSEEK_API_KEY}" } for sentence in sentences: with console.status("[bold bright_green] Model Inference..."): # 构建当前待分类的请求 current_prompt = f"“{sentence}”是 {custom_settings['class_list']} 里的什么类别?" # 拼接完整的对话历史(少样本示例 + 当前请求) messages = custom_settings['pre_history'] + [ {"role": "user", "content": current_prompt} ] # 构造API请求体 payload = { "model": MODEL_NAME, "messages": messages, "temperature": 0.1, # 分类任务建议低温度,保证结果稳定 "max_tokens": 50, # 分类结果仅需类别名称,限制token数 "stream": False # 非流式响应 } # 调用DeepSeek API response = requests.post( url=DEEPSEEK_BASE_URL, headers=headers, data=json.dumps(payload), timeout=30 ) response.raise_for_status() # 抛出HTTP请求异常 result = response.json() # 提取模型回复 inference_answer = result["choices"][0]["message"]["content"].strip() # 打印结果 print(f'>>> [bold bright_red]sentence: {sentence}') print(f'>>> [bold bright_green]inference answer: {inference_answer}')最后调用模型,运行即可得到结果
if __name__ == '__main__': # 初始化分类配置 custom_settings = init_prompt() print("初始化prompt配置:", custom_settings) # 待分类的句子列表 sentences = [ "今日,央行发布公告宣布降低利率,以刺激经济增长。这一降息举措将影响贷款利率,并在未来几个季度内对金融市场产生影响。", "ABC公司今日发布公告称,已成功完成对XYZ公司股权的收购交易。本次交易是ABC公司在扩大业务范围、加强市场竞争力方面的重要举措。据悉,此次收购将进一步巩固ABC公司在行业中的地位,并为未来业务发展提供更广阔的发展空间。详情请见公司官方网站公告栏", "公司资产负债表显示,公司偿债能力强劲,现金流充足,为未来投资和扩张提供了坚实的财务基础。", "最新的分析报告指出,可再生能源行业预计将在未来几年经历持续增长,投资者应该关注这一领域的投资机会", ] # 执行分类推理 inference(sentences, custom_settings)五.实现金融文本信息抽取
5.1 介绍
首先,定义其中信息抽取的Schema:
# 定义不同实体下的具备属性 schema = { '金融': ['日期', '股票名称', '开盘价', '收盘价', '成交量'], }比如下面几段文本的股票信息(来源于网络):
1.'2023-02-15,寓意吉祥的节日,股票佰笃[BD]美股开盘价10美元,虽然经历了波动,但最终以13美元收盘,成交量微幅增加至460,000,投资者情绪较为平稳。', 2.'2023-04-05,市场迎来轻松氛围,股票盘古(0021)开盘价23元,尽管经历了波动,但最终以26美元收盘,成交量缩小至310,000,投资者保持观望态度。',主要目标就是将这几段股票信息提取其中上述所描述的Schema的相关信息。
5.2 对应代码实现
导入必备的工具包:
import re import json from rich import print from transformers import AutoTokenizer, AutoModel # 定义不同实体下的具备属性 schema = { '金融': ['日期', '股票名称', '开盘价', '收盘价', '成交量'], } IE_PATTERN = "{}\n\n提取上述句子中{}的实体,并按照JSON格式输出,上述句子中不存在的信息用['原文中未提及']来表示,多个值之间用','分隔。" # 提供一些例子供模型参考 ie_examples = { '金融': [ { 'content': '2023-01-10,股市震荡。股票古哥-D[EOOE]美股今日开盘价100美元,一度飙升至105美元,随后回落至98美元,最终以102美元收盘,成交量达到520000。', 'answers': { '日期': ['2023-01-10'], '股票名称': ['古哥-D[EOOE]美股'], '开盘价': ['100美元'], '收盘价': ['102美元'], '成交量': ['520000'], } } ] }构建init_prompts()函数
def init_prompts(): """ 初始化前置prompt,便于模型做 incontext learning。 """ ie_pre_history = [ ( "现在你需要帮助我完成信息抽取任务,当我给你一个句子时,你需要帮我抽取出句子中实体信息,并按照JSON的格式输出,上述句子中没有的信息用['原文中未提及']来表示,多个值之间用','分隔。", '好的,请输入您的句子。' ) ] for _type, example_list in ie_examples.items(): print(f'信息抽取样本的原始句子是--》{example_list}') for example in example_list: sentence = example['content'] properties_str = ', '.join(schema[_type]) schema_str_list = f'“{_type}”({properties_str})' sentence_with_prompt = IE_PATTERN.format(sentence, schema_str_list) ie_pre_history.append(( f'{sentence_with_prompt}', f"{json.dumps(example['answers'], ensure_ascii=False)}" )) print(f'ie_pre_history-->{ie_pre_history}') return {'ie_pre_history': ie_pre_history}构建clean_response()函数
def clean_response(response: str): """ 后处理模型输出。 Args: response (str): _description_ """ if '```json' in response: res = re.findall(r'```json(.*?)```', response) if len(res) and res[0]: response = res[0] response.replace('、', ',') try: return json.loads(response) except: return response构建inference()函数
def inference( sentences: list, custom_settings: dict ): """ 推理函数。 Args: sentences (List[str]): 待抽取的句子。 custom_settings (dict): 初始设定,包含人为给定的 few-shot example。 """ for sentence in sentences: cls_res = "金融" if cls_res not in schema: print(f'The type model inferenced {cls_res} which is not in schema dict, exited.') exit() properties_str = ', '.join(schema[cls_res]) schema_str_list = f'“{cls_res}”({properties_str})' sentence_with_ie_prompt = IE_PATTERN.format(sentence, schema_str_list) ie_res, _ = model.chat(tokenizer, sentence_with_ie_prompt, history=custom_settings['ie_pre_history']) ie_res = clean_response(ie_res) print(f'>>> [bold bright_red]sentence: {sentence}') print(f'>>> [bold bright_green]inference answer: ') print(ie_res)代码调用
if __name__ == '__main__': #device = 'cuda:0' device = 'cpu' tokenizer = AutoTokenizer.from_pretrained("./ChatGLM-6B/THUDM/chatglm-6b", trust_remote_code=True) #model = AutoModel.from_pretrained("./ChatGLM-6B/THUDM/chatglm-6b", # trust_remote_code=True).half().cuda() model = AutoModel.from_pretrained("./ChatGLM-6B/THUDM/chatglm-6b", trust_remote_code=True).float() model.to(device) sentences = [ '2023-02-15,寓意吉祥的节日,股票佰笃[BD]美股开盘价10美元,虽然经历了波动,但最终以13美元收盘,成交量微幅增加至460,000,投资者情绪较为平稳。', '2023-04-05,市场迎来轻松氛围,股票盘古(0021)开盘价23元,尽管经历了波动,但最终以26美元收盘,成交量缩小至310,000,投资者保持观望态度。', ] custom_settings = init_prompts() inference( sentences, custom_settings )六. 实现金融文本匹配
6.1 介绍
例如下面几段中,每一对句字相比较,看是否相似,由大模型输出,即相似与不相似。
1.('股票市场今日大涨,投资者乐观。', '持续上涨的市场让投资者感到满意。'), 2.('油价大幅下跌,能源公司面临挑战。', '未来智能城市的建设趋势愈发明显。'), 3.('利率上升,影响房地产市场。', '高利率对房地产有一定冲击。'),6.2 对应代码实现
# 导入必备的工具包 from rich import print from transformers import AutoTokenizer, AutoModel import os # 提供相似、不相似的语义匹配例子 examples = { '是': [ ('公司ABC发布了季度财报,显示盈利增长。', '财报披露,公司ABC利润上升。'), ], '不是': [ ('黄金价格下跌,投资者抛售。', '外汇市场交易额创下新高。'), ('央行降息,刺激经济增长。', '新能源技术的创新。') ] } # 3.2 构建 init_prompts() 函数 def init_prompts(): """ 初始化前置 prompt,便于模型做 in-context learning。 Returns: dict: 包含 pre_history 的字典,用于后续推理 """ pre_history = [ ( '现在你需要帮助我完成文本匹配任务,当我给你两个句子时,你需要回答我这两句话语义是否相似。只需要回答是否相似,不要做多余的回答。', '好的,我将只回答"是"或"不是"。' ) ] for key, sentence_pairs in examples.items(): for sentence_pair in sentence_pairs: sentence1, sentence2 = sentence_pair pre_history.append(( f'句子一:{sentence1}\n句子二:{sentence2}\n上面两句话是相似的语义吗?', key )) return {'pre_history': pre_history} # 3.3 构建 inference() 函数 def inference(sentence_pairs: list, custom_settings: dict, model, tokenizer): """ 推理函数。 Args: sentence_pairs (List[tuple]): 待推理的句子对列表 custom_settings (dict): 初始设定,包含人为给定的 few-shot example model: 加载的语言模型 tokenizer: 加载的分词器 """ print("\n" + "="*60) print("[bold cyan]开始语义匹配推理[/bold cyan]") print("="*60 + "\n") results = [] for idx, sentence_pair in enumerate(sentence_pairs, 1): sentence1, sentence2 = sentence_pair sentence_with_prompt = ( f'句子一:{sentence1}\n' f'句子二:{sentence2}\n' f'上面两句话是相似的语义吗?' ) response, history = model.chat( tokenizer, sentence_with_prompt, history=custom_settings['pre_history'] ) results.append({ 'id': idx, 'sentence1': sentence1, 'sentence2': sentence2, 'answer': response }) print(f"[bold yellow]【样本 {idx}】[/bold yellow]") print(f" 句子一:[white]{sentence1}[/white]") print(f" 句子二:[white]{sentence2}[/white]") print(f" 匹配结果:[bold green]{response}[/bold green]\n") print("="*60) print(f"[bold cyan]推理完成,共处理 {len(results)} 个样本[/bold cyan]") print("="*60) return results # 主程序入口 if __name__ == '__main__': # 设备配置 device = 'cpu' # 可根据需要改为 'cuda:0' # 加载模型和分词器 print("[bold blue]正在加载 ChatGLM-6B 模型...[/bold blue]") tokenizer = AutoTokenizer.from_pretrained( "./ChatGLM-6B/THUDM/chatglm-6b", trust_remote_code=True ) model = AutoModel.from_pretrained( "./ChatGLM-6B/THUDM/chatglm-6b", trust_remote_code=True ).float().to(device) print("[bold green]模型加载完成![/bold green]\n") # 待测试的句子对 sentence_pairs = [ ('股票市场今日大涨,投资者乐观。', '持续上涨的市场让投资者感到满意。'), ('油价大幅下跌,能源公司面临挑战。', '未来智能城市的建设趋势愈发明显。'), ('利率上升,影响房地产市场。', '高利率对房地产有一定冲击。'), ] # 初始化 prompt custom_settings = init_prompts() # 执行推理 results = inference(sentence_pairs, custom_settings, model, tokenizer)七. 总结
这是一个利用大语言模型处理金融文本的项目,核心是用"提示工程"让AI干三件事:给金融文本分类、从文本里抽取关键信息、判断两句话意思是否相似。项目的关键在于教会AI怎么干活——简单任务直接下命令(Zero-Shot),复杂任务先给几个例子让它照猫画虎(Few-Shot),专业任务则提前训练让它更懂行(Instruction)。具体实现上,文本分类用DeepSeek API调用,信息抽取和文本匹配用本地ChatGLM-6B模型(对应api接口暂时没钱了),都是通过构建"示例+指令"的提示模板,让模型在对话历史中学习任务模式,最后输出结构化结果。整体思路就是"给例子、下指令、调参数",用最小成本让大模型在金融场景下发挥最大价值。
