genaiscript踩坑:设置proxyman抓包、兼容qwen72b funtion-call

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") {
+      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))
        }
      }
// 只设置ssl_verify=false,关闭ssl验证
// node_modules/node-fetch/lib/index.js
// ... existing code ...
	let agent = request.agent;
	if (typeof agent === 'function') {
		agent = agent(parsedURL);
	}

	// HTTP-network fetch step 4.2
	// chunked encoding is handled by Node.js

+	// 直接忽略 SSL 证书验证
+	if (parsedURL.protocol === 'https:') {
+        if (agent) {
+            agent.options.rejectUnauthorized = false;
+        } else {
+            agent = new HttpsProxyAgent(parsedURL.href, { rejectUnauthorized: false });
+        }
+        return Object.assign({}, parsedURL, {
+            method: request.method,
+            headers: exportNodeCompatibleHeaders(headers),
+            agent
+        });
+	} else {
+		return Object.assign({}, parsedURL, {
+			method: request.method,
+			headers: exportNodeCompatibleHeaders(headers),
+			agent
+		});
+	}

	return Object.assign({}, parsedURL, {
		method: request.method,
		headers: exportNodeCompatibleHeaders(headers),
		agent
	});
posted @   索美不达米亚  阅读(29)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示