genaiscript有个很棒的日志系统,但是碰到接口报错就没用了,还是得抓包来看,为了设置proxy,得修改源码。genaiscript是通过npx运行的,包的执行优先顺序是本地依赖目录npm install genaiscript
——npm全局依赖目录npm install -g genaiscript
——npx缓存目录从没有安装过本地包
,在Mac上对应的文件夹路径是 /你的本地项目/node_modules/genaiscript/built/genaiscript.cjs
——/Users/username/.nvm/versions/node/v20.15.1/lib/node_modules/genaiscript/built/genaiscript.cjs
——/Users/username/.npm/_npx/86ce7b375aee60ee/node_modules/genaiscript/built/genaiscript.cjs
,注意如果运行npx --yes [email protected] run demo
,如果你本地或者全局安装的版本不是@1.75.3
,那npm会自动下载[email protected]
到npx缓存目录运行,所以版本号也要一致。genaiscript.cjs是一个快10万行的打包js文件,好在代码是非压缩的,可以方便地直接修改。我修改的版本是@1.75.3
// genaiscript.cjs
// ../core/src/openai.ts
function getConfigHeaders(cfg) {
let { token, type, base } = cfg;
// ... existing code ...
const fetchHeaders = {
...getConfigHeaders(cfg),
"Content-Type": "application/json",
...headers || {}
};
traceFetchPost(trace, url, fetchHeaders, postReq);
const body = JSON.stringify(postReq);
let r2;
+ // 增加代理抓包,仅针对OpenAI接口的请求
+ const { HttpsProxyAgent } = require('https-proxy-agent');
+ const proxy = 'http://192.168.8.110:9090';
+ const agent = new HttpsProxyAgent(proxy);
try {
r2 = await fetchRetry(url, {
+ agent:agent,
headers: fetchHeaders,
body,
method: "POST",
signal: toSignal(cancellationToken),
...rest || {}
});
// ... existing code ...
+ let toolCall_ids = new Set();
const doChoices = (json, tokens) => {
const obj = JSON.parse(json);
if (!postReq.stream) trace.detailsFenced(`response`, obj, "json");
if (obj.usage) usage = obj.usage;
if (!responseModel && obj.model) responseModel = obj.model;
if (!obj.choices?.length) return;
else if (obj.choices?.length != 1)
throw new Error("too many choices in response");
const choice = obj.choices[0];
const { finish_reason } = choice;
if (finish_reason) finishReason = finish_reason;
if (choice.delta) {
const { delta, logprobs } = choice;
if (logprobs?.content) lbs.push(...logprobs.content);
if (typeof delta?.content === "string" && delta?.content !== "") {
numTokens += estimateTokens(delta.content, encoder);
chatResp += delta.content;
tokens.push(
...serializeChunkChoiceToLogProbs(choice)
);
trace.appendToken(delta.content);
} else if (Array.isArray(delta.tool_calls)) {
const { tool_calls } = delta;
for (const call of tool_calls) {
+ // 兼容siliconflow, aliyun的qwen72b调用index不正确
+ let id = call.id;
+ if (typeof id == 'string' && id.length > 0 && !toolCall_ids.has(id)) {
+ toolCall_ids.add(id);
+ }
+ let uniq_index = toolCall_ids.size - 1
+ const tc = toolCalls[uniq_index] || (toolCalls[uniq_index] = {
- const tc = toolCalls[call.index] || (toolCalls[call.index] = {
id: call.id,
name: call.function.name,
arguments: ""
});
if (call.function.arguments)
tc.arguments += call.function.arguments;
// console.log(JSON.stringify(toolCalls))
}
}
标签:...,genaiscript,proxyman,call,delta,obj,const
From: https://www.cnblogs.com/mesopotamiaa/p/18555652