





















@@ -2319,6 +2319,117 @@ describe("createOllamaStreamFn", () => {
23192319);
23202320});
232123212322+it("sets top_p=1 for native Ollama greedy sampling requests", async () => {
2323+await withMockNdjsonFetch(
2324+[
2325+'{"model":"m","created_at":"t","message":{"role":"assistant","content":"ok"},"done":false}',
2326+'{"model":"m","created_at":"t","message":{"role":"assistant","content":""},"done":true,"prompt_eval_count":1,"eval_count":1}',
2327+],
2328+async (fetchMock) => {
2329+const stream = await createOllamaTestStream({
2330+baseUrl: "http://ollama-host:11434",
2331+model: {
2332+params: {
2333+num_ctx: 4096,
2334+top_p: 0.9,
2335+thinking: false,
2336+},
2337+},
2338+options: { temperature: 0 },
2339+});
2340+2341+const events = await collectStreamEvents(stream);
2342+expect(events.at(-1)?.type).toBe("done");
2343+2344+const requestInit = getGuardedFetchCall(fetchMock).init ?? {};
2345+if (typeof requestInit.body !== "string") {
2346+throw new Error("Expected string request body");
2347+}
2348+const requestBody = JSON.parse(requestInit.body) as {
2349+options: {
2350+temperature?: number;
2351+top_p?: number;
2352+};
2353+};
2354+expect(requestBody.options.temperature).toBe(0);
2355+expect(requestBody.options.top_p).toBe(1);
2356+},
2357+);
2358+});
2359+2360+it("sets top_p=1 for native Ollama greedy requests without configured top_p", async () => {
2361+await withMockNdjsonFetch(
2362+[
2363+'{"model":"m","created_at":"t","message":{"role":"assistant","content":"ok"},"done":false}',
2364+'{"model":"m","created_at":"t","message":{"role":"assistant","content":""},"done":true,"prompt_eval_count":1,"eval_count":1}',
2365+],
2366+async (fetchMock) => {
2367+const stream = await createOllamaTestStream({
2368+baseUrl: "http://ollama-host:11434",
2369+model: {
2370+params: {
2371+num_ctx: 4096,
2372+thinking: false,
2373+},
2374+},
2375+options: { temperature: 0 },
2376+});
2377+2378+const events = await collectStreamEvents(stream);
2379+expect(events.at(-1)?.type).toBe("done");
2380+2381+const requestInit = getGuardedFetchCall(fetchMock).init ?? {};
2382+if (typeof requestInit.body !== "string") {
2383+throw new Error("Expected string request body");
2384+}
2385+const requestBody = JSON.parse(requestInit.body) as {
2386+options: {
2387+temperature?: number;
2388+top_p?: number;
2389+};
2390+};
2391+expect(requestBody.options.temperature).toBe(0);
2392+expect(requestBody.options.top_p).toBe(1);
2393+},
2394+);
2395+});
2396+2397+it("preserves configured top_p for native Ollama non-greedy sampling requests", async () => {
2398+await withMockNdjsonFetch(
2399+[
2400+'{"model":"m","created_at":"t","message":{"role":"assistant","content":"ok"},"done":false}',
2401+'{"model":"m","created_at":"t","message":{"role":"assistant","content":""},"done":true,"prompt_eval_count":1,"eval_count":1}',
2402+],
2403+async (fetchMock) => {
2404+const stream = await createOllamaTestStream({
2405+baseUrl: "http://ollama-host:11434",
2406+model: {
2407+params: {
2408+top_p: 0.9,
2409+},
2410+},
2411+options: { temperature: 0.2 },
2412+});
2413+2414+const events = await collectStreamEvents(stream);
2415+expect(events.at(-1)?.type).toBe("done");
2416+2417+const requestInit = getGuardedFetchCall(fetchMock).init ?? {};
2418+if (typeof requestInit.body !== "string") {
2419+throw new Error("Expected string request body");
2420+}
2421+const requestBody = JSON.parse(requestInit.body) as {
2422+options: {
2423+temperature?: number;
2424+top_p?: number;
2425+};
2426+};
2427+expect(requestBody.options.temperature).toBe(0.2);
2428+expect(requestBody.options.top_p).toBe(0.9);
2429+},
2430+);
2431+});
2432+23222433it("omits num_ctx when the model has no params.num_ctx and no catalog window", async () => {
23232434await withMockNdjsonFetch(
23242435[
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。