ollama+tts+vlm+langchain 示例代码
负责定义基于LangChain的视觉AI代理使用RunnableWithMessageHistory import sys import os sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import time from datetime import datetime from typing import List, Dict, Any, Optional import base64 import io import logging # LangChain相关导入 from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.output_parsers import StrOutputParser # 截图实现 import base64 import subprocess from datetime import datetime from PIL import Image import io import os def take_screenshot(): 获取屏幕截图返回base64数据 try: timestamp datetime.now().strftime(%Y%m%d_%H%M%S) filepath ftemp_screenshot_{timestamp}.png ps_script f Add-Type -AssemblyName System.Windows.Forms,System.Drawing $bounds [System.Windows.Forms.Screen]::PrimaryScreen.Bounds $bmp New-Object System.Drawing.Bitmap($bounds.width, $bounds.height) $graphics [System.Drawing.Graphics]::FromImage($bmp) $graphics.CopyFromScreen($bounds.X, $bounds.Y, 0, 0, $bounds.size) $bmp.Save({filepath}, [System.Drawing.Imaging.ImageFormat]::Png) $graphics.Dispose() $bmp.Dispose() subprocess.run([ powershell.exe, -NoProfile, -ExecutionPolicy, Bypass, -Command, ps_script ], capture_outputTrue) if os.path.exists(filepath): image Image.open(filepath) if image.width 2048 or image.height 2048: ratio min(2048/image.width, 2048/image.height) new_size (int(image.width*ratio), int(image.height*ratio)) image image.resize(new_size, Image.Resampling.LANCZOS) buffer io.BytesIO() image.save(buffer, formatPNG) base64_data base64.b64encode(buffer.getvalue()).decode() os.remove(filepath) return {success: True, data: base64_data} else: return {success: False, data: , error: 文件未生成} except Exception as e: return {success: False, data: , error: str(e)} import asyncio # TTS相关导入 import edge_tts # 配置日志 logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) logging.getLogger(mem0).setLevel(logging.CRITICAL) # 会话存储 store {} async def speak_text(text: str, voice: str zh-CN-XiaoxiaoNeural): 使用edge-tts合成并播放语音Windows原生API import tempfile import sys from ctypes import create_unicode_buffer, windll, wintypes if sys.platform ! win32: logger.warning(TTS仅支持Windows系统) return communicate edge_tts.Communicate(text, voice) # 创建临时MP3文件 with tempfile.NamedTemporaryFile(suffix.mp3, deleteFalse) as temp_file: temp_path temp_file.name try: # 保存音频到临时文件 await communicate.save(temp_path) # 使用Windows原生MCI API播放 _get_short_path_name_w windll.kernel32.GetShortPathNameW _get_short_path_name_w.argtypes [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD] _get_short_path_name_w.restype wintypes.DWORD def get_short_path_name(long_name: str) - str: output_buf_size 0 while True: output_buf create_unicode_buffer(output_buf_size) needed _get_short_path_name_w(long_name, output_buf, output_buf_size) if output_buf_size needed: return output_buf.value output_buf_size needed mci_send_string_w windll.winmm.mciSendStringW def mci_send(msg: str) - None: result mci_send_string_w(msg, 0, 0, 0) if result ! 0: logger.warning(fMCI错误 {result}: {msg}) # 获取短文件名并播放 mp3_shortname get_short_path_name(temp_path) mci_send(Close All) mci_send(fOpen {mp3_shortname} Type MPEGVideo Alias theMP3) mci_send(Play theMP3 Wait) mci_send(Close theMP3) except Exception as e: logger.error(fTTS播放失败: {e}) finally: # 立即清理临时文件 try: os.unlink(temp_path) except: pass def get_session_history(session_id: str): 获取会话历史 - 使用您提供的标准实现 if session_id not in store: store[session_id] ChatMessageHistory() return store[session_id] class LangChainVLMAgent: 基于LangChain的视觉语言模型代理 def __init__(self): # 使用OpenAI兼容协议连接Ollama self.llm ChatOpenAI( modelqwen3-vl:4b, base_urlhttp://localhost:11434/v1, api_keyollama, temperature0.7, timeout300, ) # 定义系统提示词 self.system_prompt 温顺的18岁AI少女,对话内容控制在30个字 # 创建提示模板 self.prompt ChatPromptTemplate.from_messages([ (system, self.system_prompt), MessagesPlaceholder(variable_namehistory), (human, {input}) ]) # 创建带历史记录的可运行对象 self.conversation RunnableWithMessageHistory( self.prompt | self.llm, get_session_history, input_messages_keyinput, history_messages_keyhistory ) async def process_message(self, user_input: str, session_id: str default) - str: 处理用户消息并返回AI回复 Args: user_input (str): 用户输入 session_id (str): 会话ID Returns: str: AI回复 try: # 获取截图 result take_screenshot() if result[success]: screenshot_base64 result[data] # 构造包含图像的消息 message_content [ {type: text, text: f用户{user_input}}, { type: image_url, image_url: { url: fdata:image/png;base64,{screenshot_base64} } } ] else: print(f截图失败: {result.get(error, 未知错误)}) message_content f用户{user_input} # 调用模型获取回复 response self.conversation.invoke( {input: message_content}, config{configurable: {session_id: session_id}} ) ai_response response.content if hasattr(response, content) else str(response) return ai_response except Exception as e: logger.error(f处理消息时发生错误: {e}) import traceback logger.error(f详细错误信息: {traceback.format_exc()}) return 抱歉我遇到了一些问题请稍后再试。 def save_to_memory_log(content: str): 将内容保存到memory文件夹下的日志文件中 current_date datetime.now().strftime(%Y-%m-%d) memory_dir os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), memory_data) if not os.path.exists(memory_dir): os.makedirs(memory_dir) log_file_path os.path.join(memory_dir, f{current_date}.txt) timestamp datetime.now().strftime(%Y-%m-%d %H:%M) try: with open(log_file_path, a, encodingutf-8) as f: f.write(f[{timestamp}] {content}\n) logger.info(f已保存到日志文件: {log_file_path}) except Exception as e: logger.error(f保存日志失败: {e}) # 创建全局代理实例 vlm_agent LangChainVLMAgent() async def chat_with_agent(user_input: str, session_id: str default) - str: 与视觉AI代理进行单次对话并播放TTS回复 ai_response await vlm_agent.process_message(user_input, session_id) save_to_memory_log(ai_response) print(fAI回复: {ai_response}) # 使用TTS播放回复 await speak_text(ai_response) return ai_response if __name__ __main__: import asyncio asyncio.run(chat_with_agent(屏幕有什么内容))

相关新闻

计算机毕业设计springboot试卷生成器 基于SpringBoot的智能组卷系统设计与实现 SpringBoot在线考试与试卷自动生成平台

计算机毕业设计springboot试卷生成器 基于SpringBoot的智能组卷系统设计与实现 SpringBoot在线考试与试卷自动生成平台

计算机毕业设计springboot试卷生成器7v0z790e(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着教育信息化的深入发展,传统的纸质考试方式正逐渐向电子化、网络化转…

2026/7/7 6:18:03 阅读更多 →
基于SpringBoot+Vue的设计素材服务平台设计与实现

基于SpringBoot+Vue的设计素材服务平台设计与实现

前言 🌞博主介绍:✌CSDN特邀作者、全栈领域优质创作者、10年IT从业经验、码云/掘金/知乎/B站/华为云/阿里云等平台优质作者、专注于Java、小程序/APP、python、大数据等技术领域和毕业项目实战,以及程序定制化开发、文档编写、答疑辅导等。✌…

2026/7/6 11:32:35 阅读更多 →
计算机毕业设计springboot高校资源共享平台 基于SpringBoot的高等院校教学资源协同共享系统 SpringBoot框架下高校数字化学习资源互通服务平台

计算机毕业设计springboot高校资源共享平台 基于SpringBoot的高等院校教学资源协同共享系统 SpringBoot框架下高校数字化学习资源互通服务平台

计算机毕业设计springboot高校资源共享平台1rfk9sjb (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 在数字化教育快速发展的背景下,高等教育资源的整合与共享已成为…

2026/7/5 9:39:55 阅读更多 →

最新新闻

OceanBase发布“湖库一体”AI数据库:一套引擎替代交易库+数仓+向量库+数据湖

OceanBase发布“湖库一体”AI数据库:一套引擎替代交易库+数仓+向量库+数据湖

6月29日,OceanBase正式发布面向AI时代的湖库一体AI数据库,提出以“湖库一体”为核心架构,将数据湖的开放与海量存储能力、数据库的事务处理与分析能力,以及多模态数据处理能力统一到一套强一致的数据底座上,帮助Agent&…

2026/7/7 6:15:44 阅读更多 →
eHR 五层完整架构解析:分清基础刚需功能与高阶增值能力

eHR 五层完整架构解析:分清基础刚需功能与高阶增值能力

人力资源eHR软件系统(Electronic Human Resources System),是指通过信息化手段将企业HR管理全流程数字化、自动化的软件平台,涵盖招聘、入职、薪酬、绩效、考勤、培训等核心模块,帮助企业告别纸质档案与Excel表格&…

2026/7/7 6:13:44 阅读更多 →
Python处理气象NetCDF数据:读取、裁剪、统计与可视化

Python处理气象NetCDF数据:读取、裁剪、统计与可视化

一、前言 做气象、海洋、能源研究的同学,几乎每天都要和NetCDF(.nc)格式打交道。这种格式虽然跨平台、自带元数据,但对新手来说,用Python读取、裁剪、计算区域平均、画图,每一步都可能踩坑。本文基于公开的…

2026/7/7 6:09:43 阅读更多 →
《我的倒霉蛋宝贝》 泰剧|在线观看|奇幻|浪漫|Unlucky Bae

《我的倒霉蛋宝贝》 泰剧|在线观看|奇幻|浪漫|Unlucky Bae

《我的倒霉蛋宝贝》 泰剧|在线观看|奇幻|浪漫|Unlucky Bae资料可在线播放《我的倒霉蛋宝贝》https://tool.nineya.com/s/1jskahdln English Practice Fantasy Romance Edition 以《我的倒霉蛋宝贝》为主题的英语练习,边追剧边学英语。Part 1 Vocabulary Choose th…

2026/7/7 6:09:43 阅读更多 →
Stable Diffusion本地部署指南:免费无限量AI绘画实战

Stable Diffusion本地部署指南:免费无限量AI绘画实战

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在AI绘画领域,不少开发者都遇到了同样的问题:云端AI绘画工具要么收费昂贵,要么生成次数有限制…

2026/7/7 6:09:43 阅读更多 →
YimMenu技术架构深度解析:从游戏逆向工程到现代C++菜单设计

YimMenu技术架构深度解析:从游戏逆向工程到现代C++菜单设计

YimMenu技术架构深度解析:从游戏逆向工程到现代C菜单设计 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/Y…

2026/7/7 6:07:42 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻