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 genaiscript@1.75.3 run demo
,如果你本地或者全域性安裝的版本不是@1.75.3
,那npm會自動下載genaiscript@1.75.3
到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))
}
}