利用OpenRouter API,搭建google/gemma-7b-it:free本地客户端

这篇文章起源于小毕超的《无需 GPU 服务器,借助 OpenRouter 零成本搭建自己的大模型助手-CSDN博客》。关于OpenRouter的介绍,此文章已经比较全面。该文章中使用 Python + tornado 实现 Web 服务,前端使用基础的 Html + Jquery编写的server.py、app.py和html文件为我提供了重要帮助。之所以写这篇文章,是因为在使用server.py中出现了“405 服务接口调用异常”。在利用chrome devtool跟踪网络请求后,发现tornado.web.Application的“/assistant”路由,在向app.py发起post请求之后,还将发起第二次options请求,而文章中的Assistant并没有加入响应options请求的处理代码。

        经询问kimi AIKimi.ai - 帮你看更大的世界,了解问题出在“在使用Tornado搭建的服务端时,如果遇到发起OPTIONS请求出错的问题,这通常是由于预请求(pre-flight request)导致的。在HTTP协议中,OPTIONS请求是一种预请求,用于客户端在发送实际请求之前,询问服务器是否允许某个HTTP方法(如POST、GET、PUT、DELETE等)”。解决方案为:

  • 配置CORS:可以使用Tornado的tornado.web.CorsFilter来设置CORS策略,或者手动设置响应头Access-Control-Allow-Methods

  • 添加OPTIONS请求处理器:在Tornado中,可以为路由添加一个OPTIONS方法的处理器,返回允许的HTTP方法。

       server.py中对cors的设置已经由set_default_headers正确设置,但Assistant类中缺少options处理方法。修改后的server.py代码如下:

from tornado.concurrent import run_on_executor
from tornado.web import  RequestHandler
import tornado.gen
from openai import OpenAI
import json

class Assistant(RequestHandler):
    model = "google/gemma-7b-it:free"
    client = OpenAI(
        base_url="https://openrouter.ai/api/v1",
        api_key="sk-##########################",
    )
    default_prompt = "You are an AI assistant that helps people find information."

    def prepare(self):
        self.executor = self.application.pool

    def set_default_headers(self):
        self.set_header('Access-Control-Allow-Origin', "*")
        self.set_header('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept")
        self.set_header('Access-Control-Allow-Methods', "GET, POST, PUT, DELETE, OPTIONS")

    def options(self):
        # 直接调用set_default_headers来设置CORS头部
        self.set_default_headers()
        # OPTIONS请求不需要响应体,因此直接finish
        self.finish()

    @tornado.gen.coroutine
    def post(self):
        json_data = json.loads(self.request.body)
        if 'questions' not in json_data or 'history' not in json_data:
            self.write({
                "code": 400,
                "message": "缺少必填参数"
            })
            return
        questions = json_data['questions']
        history = json_data['history']
        result = yield self.do_handler(questions, history)
        self.write(result)

    @run_on_executor
    def do_handler(self, questions, history):
        try:
            answer, history = self.llm(questions, history)
            return {
                "code": 200,
                "message": "success",
                "answer": answer,
                "history": history
            }
        except Exception as e:
            return {
                "code": 400,
                "message": str(e)
            }

    def llm(self, user_prompt, messages, system_prompt=default_prompt):
        if not messages:
            messages = []
        messages.append({"role": "user", "content": user_prompt})
        completion = self.client.chat.completions.create(
            extra_headers={
                "HTTP-Referer": "http://localhost:8088",
                "X-Title": "test",
            },
            model=self.model,
            messages=messages,
            max_tokens=2048
        )
        answer = completion.choices[0].message.content
        messages.append({"role": "assistant", "content": answer})
        return answer, messages

app.py和本地html文件无需更改。

最后,openrouter中还有其他免费的LLM,但是免费的LLM都有一定的限制,google/gemma-7b-it:free在处理中文方面还存在不足,会出现中英文混排输出和乱码的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/604314.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Baidu Comate智能编码助手:提升软件生产力的高效工具使用教程

目录 一、前言 二、Comate助手概览 三、核心功能详解 智能推荐与自动补全 生成单元测试 代码注释生成 四、使用场景与优势 五、总结与展望 一、前言 随着信息技术的飞速发展,编程已经成为许多行业不可或缺的一部分。然而,编程过程中的繁琐和重复…

基于51单片机交通灯设计—汇编语言

基于51单片机的交通灯设计 (仿真+程序设计报告) 功能介绍 具体功能: 1.南北方向绿灯20s(最后3s闪烁)后转黄灯常亮5s,同时东西方向红灯25秒;东西方向绿灯20s(最后3s闪烁…

【三】DRF序列化进阶

序列化器的定义与使用 多表关联序列化 【1】准备工作 # settings.py DATABASES {default: {# 数据库引擎选择使用MySQLENGINE: django.db.backends.mysql,# 指定数据库名字,需提前创建NAME: books,# 指定数据库用户名USER: root,# 指定数据库用户密码PASSWORD: …

Redis 主从复制 初步认识

文章目录 定义拓扑拓扑定义单从拓扑多从拓扑树型拓扑 使用原理建立流程持续复制 定义 Redis主从复制技术的主要满足的需求是①数据恢复②负载均衡 ①数据恢复的理解:将数据同步到多个Redis服务器中,其中一个节点数据损毁,可通过复制其他节点…

FreeRTOS学习笔记-基于stm32(6)时间片调度实验

1、什么是时间片调度 在任务优先级相同的时候,CPU会轮流使用相同的时间去执行它,即时间片调度。这个相同的时间就是时间片。而时间片的大小就是SysTick的中断周期(SysTick的中断周期可以修改)。 比如有三个相同优先级的任务在运行…

一张贴纸50万,炒房炒币的怎么都来炒CSGO皮肤了

一张贴纸50万,为什么炒房炒币的都来炒CSGO饰品了? 一张贴纸50万,炒房炒币的怎么都来炒CSGO皮肤了? 经常有人问我,天天看你们买卖装备,买卖皮肤,说到底这都是虚拟产品,看得见摸不着的…

ue引擎游戏开发笔记(35)——为射击添加轨道,并显示落点

1.需求分析: 我们只添加了开枪特效,事实上并没有实际的效果产生例如弹痕,落点等等。所以逐步实现射击的完整化,先从实现落点开始。 2.操作实现: 1.思路:可以这样理解,每次射击的过程是一次由摄…

二层交换机与防火墙连通上网实验

防火墙是一种网络安全设备,用于监控和控制网络流量。它可以帮助防止未经授权的访问,保护网络免受攻击和恶意软件感染。防火墙可以根据预定义的规则过滤流量,例如允许或阻止特定IP地址或端口的流量。它也可以检测和阻止恶意软件、病毒和其他威…

Ansible-playbook剧本

目录 一、Ansible playbook简介 2.1 playbook格式 2.2 playbook组成部分 二、playbook示例 2.1 yaml文件编写 2.2 运行playbook 2.3 定义、引用变量 2.4 指定远程主机sudo切换用户 2.5 when条件判断 2.6 迭代 三、总结 Ansible中使用playbook脚本的作用和好处 一、A…

5月8日学习记录

_[FBCTF2019]RCEService(preg_match函数的绕过) 涉及知识点:preg_match函数绕过,json的格式,正则回溯 打开环境,要求用json的格式输入 搜索学习一下json的语法规则 数组(Array)用方括…

OpenMV 图像串口传输示例

注意:本程序根据 OpenMV采集图片通过串口发送,PC接收并保存为图片 更改。 一、例程说明 这个例程主要实现了以下功能: 1. OpenMV 端采集图像:使用OpenMV开发板上的摄像头采集实时图像数据。 2. 通过串口传输图像数据:将采集到的图像数据打包成字节流,…

智慧工地的5大系统是什么?SaaS化大型微服务架构(智慧工地云平台源码)可多端展示登录

智慧工地解决方案依托计算机技术、物联网、云计算、大数据、人工智能、VR&AR等技术相结合,为工程项目管理提供先进技术手段,构建工地现场智能监控和控制体系,弥补传统方法在监管中的缺陷,最终实现项目对人、机、料、法、环的全…

外企接受大龄程序员吗?

本人知乎账号同公众号:老胡聊Java,欢迎留言并咨询 亲身体会外企经历所见所闻,外企能接受大龄程序员。 1 大概是10年的时候,进一家知名外企,和我一起进的一位manager,后来听下来,年龄35&#xf…

html的标签

基础标签 标签描述<h1>-<h6>定义标题&#xff0c;h1最大&#xff0c;h6最小<font>定义文本的字体&#xff0c;字体尺寸&#xff0c;字体颜色<b>定义粗体文本<i>定义斜体文本<u>定义文本下划线<center>定义文本居中<p>定义段落…

俄罗斯国际消费类电子电器展ICEE:人潮如织,盛况空前

近日&#xff0c;备受全球瞩目的俄罗斯国际消费类电子电器展ICEE在莫斯科盛大落幕。本次展会为期四天&#xff0c;真的攒足了眼球&#xff0c;不仅俄罗斯这边的很多媒体和自媒体有报道&#xff0c;展会第一天&#xff0c;很多参展商通过短视频平台将展会的盛况传到了国内&#…

Ubuntu22.04下安装kafka_2.11-0.10.1.0并运行简单实例

目录 一、版本信息 二、安装Kafka 1.将Kafka安装包移到下载目录中 2.下载Spark并确保hadoop用户对Spark目录有操作权限 三、启动Kafka并测试Kafka是否正常工作 1.启动Kafka 2.测试Kafka是否正常工作 一、版本信息 虚拟机产品&#xff1a;VMware Workstation 17 Pro 虚…

AI PC,到底谁的梦想、谁的红利?

世界上第一台通用计算机是1946年诞生的埃尼阿克&#xff0c;世界上第一台便携电脑是1981年诞生的“奥斯本1号”&#xff0c;世界上第一部智能手机是1993年诞生的IBM Simon。 它们之间看起来毫无关系&#xff0c;但却暗含一种关于创新的微妙潜规则——随着时间推移&#xff0c;…

MM模块学习一(供应商创建,物料类型的定义及功能)

物料管理流程&#xff1a; 源头&#xff1a;采购需求->采购申请 MRP&#xff1a;物料需求计划。运行物料需求计划的结果&#xff0c;根据物料的性质来判断是外购&#xff08;采购申请&#xff09;或者是生产&#xff08;计划订单->生产订单&#xff09;。 采购申请&am…

acwing算法提高之数据结构--平衡树Treap

目录 1 介绍2 训练 1 介绍 本博客用来记录使用平衡树求解的题目。 插入、删除、查询操作的时间复杂度都是O(logN)。 动态维护一个有序序列。 2 训练 题目1&#xff1a;253普通平衡树 C代码如下&#xff0c; #include <cstdio> #include <cstring> #include …

Postgresql源码(128)深入分析JIT中的函数内联llvm_inline

相关 《Postgresql源码&#xff08;127&#xff09;投影ExecProject的表达式执行分析》 《LLVM的ThinLTO编译优化技术在Postgresql中的应用》 《LLVM&#xff08;5&#xff09;ORC实例分析》 1 JIT优化效果 create table t1(i int primary key, j int, k int); insert into t1…
最新文章